diff --git a/pom.xml b/pom.xml index ce4b76a..7a0d536 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ io.qase qase-java pom - 3.1.1 + 3.2.0 qase-api qase-testng diff --git a/qase-api/README.md b/qase-api/README.md index 1ae0a41..7c4237b 100644 --- a/qase-api/README.md +++ b/qase-api/README.md @@ -8,7 +8,7 @@ Add the following dependency and repository to your pom.xml: io.qase qase-api - 3.1.1 + 3.2.0 ``` diff --git a/qase-api/pom.xml b/qase-api/pom.xml index a58f31c..65c1648 100644 --- a/qase-api/pom.xml +++ b/qase-api/pom.xml @@ -5,7 +5,7 @@ qase-java io.qase - 3.1.1 + 3.2.0 4.0.0 diff --git a/qase-api/src/main/java/io/qase/api/utils/CucumberUtils.java b/qase-api/src/main/java/io/qase/api/utils/CucumberUtils.java index 8cffb2e..eca5789 100644 --- a/qase-api/src/main/java/io/qase/api/utils/CucumberUtils.java +++ b/qase-api/src/main/java/io/qase/api/utils/CucumberUtils.java @@ -1,5 +1,6 @@ package io.qase.api.utils; +import java.net.URI; import java.util.List; import static io.qase.api.utils.IntegrationUtils.CASE_TAGS; @@ -20,4 +21,8 @@ public static Long getCaseId(List tags) { } return null; } + + public static int getHash(URI uri, Long line) { + return (uri.toString() + line).hashCode(); + } } diff --git a/qase-cucumber3-jvm/README.md b/qase-cucumber3-jvm/README.md index 3eb5d01..0d03446 100644 --- a/qase-cucumber3-jvm/README.md +++ b/qase-cucumber3-jvm/README.md @@ -42,7 +42,7 @@ Add the following dependency and repository to your pom.xml: io.qase qase-cucumber3-jvm - 3.1.1 + 3.2.0 diff --git a/qase-cucumber3-jvm/pom.xml b/qase-cucumber3-jvm/pom.xml index c27395a..20c4cfe 100644 --- a/qase-cucumber3-jvm/pom.xml +++ b/qase-cucumber3-jvm/pom.xml @@ -5,7 +5,7 @@ qase-java io.qase - 3.1.1 + 3.2.0 4.0.0 diff --git a/qase-cucumber4-jvm/README.md b/qase-cucumber4-jvm/README.md index 3380559..42b4f51 100644 --- a/qase-cucumber4-jvm/README.md +++ b/qase-cucumber4-jvm/README.md @@ -42,7 +42,7 @@ Add the following dependency and repository to your pom.xml: io.qase qase-cucumber4-jvm - 3.1.1 + 3.2.0 diff --git a/qase-cucumber4-jvm/pom.xml b/qase-cucumber4-jvm/pom.xml index 0123329..20474e8 100644 --- a/qase-cucumber4-jvm/pom.xml +++ b/qase-cucumber4-jvm/pom.xml @@ -5,7 +5,7 @@ qase-java io.qase - 3.1.1 + 3.2.0 4.0.0 diff --git a/qase-cucumber5-jvm/README.md b/qase-cucumber5-jvm/README.md index 7a3c136..8a07653 100644 --- a/qase-cucumber5-jvm/README.md +++ b/qase-cucumber5-jvm/README.md @@ -42,7 +42,7 @@ Add the following dependency and repository to your pom.xml: io.qase qase-cucumber5-jvm - 3.1.1 + 3.2.0 diff --git a/qase-cucumber5-jvm/pom.xml b/qase-cucumber5-jvm/pom.xml index 21c6cbd..2005df6 100644 --- a/qase-cucumber5-jvm/pom.xml +++ b/qase-cucumber5-jvm/pom.xml @@ -5,7 +5,7 @@ qase-java io.qase - 3.1.1 + 3.2.0 4.0.0 diff --git a/qase-cucumber6-jvm/README.md b/qase-cucumber6-jvm/README.md index c75376c..6ca3e2f 100644 --- a/qase-cucumber6-jvm/README.md +++ b/qase-cucumber6-jvm/README.md @@ -42,7 +42,7 @@ Add the following dependency and repository to your pom.xml: io.qase qase-cucumber6-jvm - 3.1.1 + 3.2.0 diff --git a/qase-cucumber6-jvm/pom.xml b/qase-cucumber6-jvm/pom.xml index 7e2a234..5711386 100644 --- a/qase-cucumber6-jvm/pom.xml +++ b/qase-cucumber6-jvm/pom.xml @@ -5,7 +5,7 @@ qase-java io.qase - 3.1.1 + 3.2.0 4.0.0 diff --git a/qase-cucumber7-jvm/README.md b/qase-cucumber7-jvm/README.md index 7d16297..03a8aee 100644 --- a/qase-cucumber7-jvm/README.md +++ b/qase-cucumber7-jvm/README.md @@ -42,7 +42,7 @@ Add the following dependency and repository to your pom.xml: io.qase qase-cucumber7-jvm - 3.1.1 + 3.2.0 diff --git a/qase-cucumber7-jvm/pom.xml b/qase-cucumber7-jvm/pom.xml index c81443b..4fb4cee 100644 --- a/qase-cucumber7-jvm/pom.xml +++ b/qase-cucumber7-jvm/pom.xml @@ -5,7 +5,7 @@ qase-java io.qase - 3.1.1 + 3.2.0 4.0.0 diff --git a/qase-cucumber7-jvm/src/main/java/io/qase/cucumber7/QaseEventListener.java b/qase-cucumber7-jvm/src/main/java/io/qase/cucumber7/QaseEventListener.java index b401a02..e836648 100644 --- a/qase-cucumber7-jvm/src/main/java/io/qase/cucumber7/QaseEventListener.java +++ b/qase-cucumber7-jvm/src/main/java/io/qase/cucumber7/QaseEventListener.java @@ -1,6 +1,14 @@ package io.qase.cucumber7; +import io.cucumber.gherkin.GherkinParser; +import io.cucumber.messages.types.*; import io.cucumber.plugin.ConcurrentEventListener; +import io.cucumber.plugin.event.TestCase; +import io.cucumber.plugin.event.TestCaseFinished; +import io.cucumber.plugin.event.TestCaseStarted; +import io.cucumber.plugin.event.TestRunFinished; +import io.cucumber.plugin.event.TestStepFinished; +import io.cucumber.plugin.event.TestStepStarted; import io.cucumber.plugin.event.*; import io.qase.api.QaseClient; import io.qase.api.StepStorage; @@ -15,17 +23,24 @@ import io.qase.cucumber7.guice.module.Cucumber7Module; import lombok.AccessLevel; import lombok.Getter; +import lombok.extern.slf4j.Slf4j; -import java.util.LinkedList; -import java.util.List; -import java.util.Optional; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; +import java.util.stream.Stream; +import static io.qase.api.utils.CucumberUtils.getHash; import static io.qase.api.utils.IntegrationUtils.getStacktrace; +@Slf4j public class QaseEventListener implements ConcurrentEventListener { + private static final Map> EXAMPLES = new HashMap<>(); private static final String REPORTER_NAME = "Cucumber 7-JVM"; - @Getter(lazy = true, value = AccessLevel.PRIVATE) private final QaseTestCaseListener qaseTestCaseListener = createQaseListener(); @@ -40,11 +55,37 @@ public void setEventPublisher(EventPublisher publisher) { publisher.registerHandlerFor(TestCaseFinished.class, this::testCaseFinished); publisher.registerHandlerFor(TestRunFinished.class, this::testRunFinished); publisher.registerHandlerFor(TestStepFinished.class, this::testStepFinished); - publisher.registerHandlerFor(TestStepStarted.class, this::testCaseStarted); + publisher.registerHandlerFor(TestStepStarted.class, this::testStepStarted); } } - private void testCaseStarted(TestStepStarted testStepStarted) { + private void parseExamples(URI uri, Envelope envelope) { + envelope.getGherkinDocument() + .flatMap(GherkinDocument::getFeature) + .ifPresent(feature -> { + for (int i = 0; i < feature.getChildren().size(); i++) { + Scenario scenario = feature.getChildren().get(i).getScenario().get(); + for (Examples exampleItem : scenario.getExamples()) { + List headers = new ArrayList<>(); + exampleItem.getTableHeader() + .ifPresent(headerCell -> + headerCell.getCells().forEach(h -> headers.add(h.getValue()))); + List tableBody = exampleItem.getTableBody(); + for (TableRow tableRow : tableBody) { + List cells = tableRow.getCells(); + HashMap example = new HashMap<>(); + for (int k = 0; k < cells.size(); k++) { + String value = cells.get(k).getValue(); + example.put(headers.get(k), value); + } + EXAMPLES.put(getHash(uri, tableRow.getLocation().getLine()), example); + } + } + } + }); + } + + private void testStepStarted(TestStepStarted testStepStarted) { if (testStepStarted.getTestStep() instanceof PickleStepTestStep) { StepStorage.startStep(); } @@ -88,6 +129,19 @@ private void testRunFinished(TestRunFinished testRunFinished) { } private void testCaseStarted(TestCaseStarted event) { + if (EXAMPLES.get(getHash(event.getTestCase().getUri(), (long) event.getTestCase().getLocation().getLine())) == null) { + TestCase testCase = event.getTestCase(); + URI uri = testCase.getUri(); + GherkinParser gherkinParser = GherkinParser.builder().build(); + try { + Path path = Paths.get(this.getClass().getClassLoader() + .getResource(uri.toString().replace("classpath:", "")).toURI()); + Stream envelopes = gherkinParser.parse(path); + envelopes.forEach(e -> parseExamples(uri, e)); + } catch (IOException | URISyntaxException e) { + log.error(e.getMessage()); + } + } getQaseTestCaseListener().onTestCaseStarted(); } @@ -96,12 +150,13 @@ private void testCaseFinished(TestCaseFinished event) { } private void setupResultItem(ResultCreate resultCreate, TestCaseFinished event) { - List tags = event.getTestCase().getTags(); + TestCase testCase = event.getTestCase(); + List tags = testCase.getTags(); Long caseId = CucumberUtils.getCaseId(tags); String caseTitle = null; if (caseId == null) { - caseTitle = event.getTestCase().getName(); + caseTitle = testCase.getName(); } StatusEnum status = convertStatus(event.getResult().getStatus()); @@ -122,6 +177,8 @@ private void setupResultItem(ResultCreate resultCreate, TestCaseFinished event) .stacktrace(stacktrace) .steps(steps.isEmpty() ? null : steps) .defect(isDefect); + Map params = EXAMPLES.get(getHash(testCase.getUri(), (long) testCase.getLocation().getLine())); + resultCreate.param(params); } private StatusEnum convertStatus(Status status) { diff --git a/qase-cucumber7-jvm/src/test/java/io/qase/cucumber7/QaseEventListenerTests.java b/qase-cucumber7-jvm/src/test/java/io/qase/cucumber7/QaseEventListenerTests.java index 243738a..0e6d87e 100644 --- a/qase-cucumber7-jvm/src/test/java/io/qase/cucumber7/QaseEventListenerTests.java +++ b/qase-cucumber7-jvm/src/test/java/io/qase/cucumber7/QaseEventListenerTests.java @@ -74,7 +74,8 @@ void bulk() { String[] args = new String[]{ "-g", "io.qase.cucumber7", "--plugin", "io.qase.cucumber7.QaseEventListener", - "classpath:features/" + "classpath:features/", + "--threads", "2" }; Main.run(args, Thread.currentThread().getContextClassLoader()); @@ -155,8 +156,100 @@ void bulk() { " \"status\" : \"passed\",\n" + " \"action\" : \"Given success step\"\n" + " } ]\n" + + " }, {\n" + + " \"case\" : {\n" + + " \"title\" : \"success with Positive Examples\"\n" + + " },\n" + + " \"status\" : \"passed\",\n" + + " \"time_ms\" : \"${json-unit.ignore}\",\n" + + " \"defect\" : false,\n" + + " \"param\" : {\n" + + " \"a\" : \"\\\"1\\\"\",\n" + + " \"b\" : \"\\\"2\\\"\"\n" + + " },\n" + + " \"steps\" : [ {\n" + + " \"position\" : 1,\n" + + " \"status\" : \"passed\",\n" + + " \"action\" : \"Given success step with parameter \\\"1\\\"\"\n" + + " }, {\n" + + " \"position\" : 2,\n" + + " \"status\" : \"passed\",\n" + + " \"action\" : \"Given success step with parameter \\\"2\\\"\"\n" + + " } ]\n" + + " }, {\n" + + " \"case\" : {\n" + + " \"title\" : \"success with Positive Examples\"\n" + + " },\n" + + " \"status\" : \"passed\",\n" + + " \"time_ms\" : \"${json-unit.ignore}\",\n" + + " \"defect\" : false,\n" + + " \"param\" : {\n" + + " \"a\" : \"\\\"3\\\"\",\n" + + " \"b\" : \"\\\"4\\\"\"\n" + + " },\n" + + " \"steps\" : [ {\n" + + " \"position\" : 1,\n" + + " \"status\" : \"passed\",\n" + + " \"action\" : \"Given success step with parameter \\\"3\\\"\"\n" + + " }, {\n" + + " \"position\" : 2,\n" + + " \"status\" : \"passed\",\n" + + " \"action\" : \"Given success step with parameter \\\"4\\\"\"\n" + + " } ]\n" + + " }, {\n" + + " \"case\" : {\n" + + " \"title\" : \"success with Positive Examples\"\n" + + " },\n" + + " \"status\" : \"passed\",\n" + + " \"time_ms\" : \"${json-unit.ignore}\",\n" + + " \"defect\" : false,\n" + + " \"param\" : {\n" + + " \"a\" : \"\\\"5\\\"\",\n" + + " \"b\" : \"\\\"6\\\"\"\n" + + " },\n" + + " \"steps\" : [ {\n" + + " \"position\" : 1,\n" + + " \"status\" : \"passed\",\n" + + " \"action\" : \"Given success step with parameter \\\"5\\\"\"\n" + + " }, {\n" + + " \"position\" : 2,\n" + + " \"status\" : \"passed\",\n" + + " \"action\" : \"Given success step with parameter \\\"6\\\"\"\n" + + " } ]\n" + + " }, {\n" + + " \"case\" : {\n" + + " \"title\" : \"success with Positive Examples\"\n" + + " },\n" + + " \"status\" : \"passed\",\n" + + " \"time_ms\" : \"${json-unit.ignore}\",\n" + + " \"defect\" : false,\n" + + " \"param\" : {\n" + + " \"a\" : \"\\\"7\\\"\",\n" + + " \"b\" : \"\\\"8\\\"\"\n" + + " },\n" + + " \"steps\" : [ {\n" + + " \"position\" : 1,\n" + + " \"status\" : \"passed\",\n" + + " \"action\" : \"Given success step with parameter \\\"7\\\"\"\n" + + " }, {\n" + + " \"position\" : 2,\n" + + " \"status\" : \"passed\",\n" + + " \"action\" : \"Given success step with parameter \\\"8\\\"\"\n" + + " } ]\n" + + " }, {\n" + + " \"case\" : {\n" + + " \"title\" : \"Success scenario\"\n" + + " },\n" + + " \"status\" : \"passed\",\n" + + " \"time_ms\" : \"${json-unit.ignore}\",\n" + + " \"defect\" : false,\n" + + " \"steps\" : [ {\n" + + " \"position\" : 1,\n" + + " \"status\" : \"passed\",\n" + + " \"action\" : \"Given success step\"\n" + + " } ]\n" + " } ]\n" + - "}"))); + "}", true, false))); } @Test diff --git a/qase-cucumber7-jvm/src/test/java/io/qase/cucumber7/Steps.java b/qase-cucumber7-jvm/src/test/java/io/qase/cucumber7/Steps.java index b60c543..598b8da 100644 --- a/qase-cucumber7-jvm/src/test/java/io/qase/cucumber7/Steps.java +++ b/qase-cucumber7-jvm/src/test/java/io/qase/cucumber7/Steps.java @@ -10,6 +10,10 @@ public class Steps { public void success() { } + @Given("success step with parameter {string}") + public void success_step_with_parameter(String string) { + } + @Given("timeout {int} seconds") public void success(int integer) throws InterruptedException { TimeUnit.SECONDS.sleep(integer); diff --git a/qase-cucumber7-jvm/src/test/resources/features/with_examples.feature b/qase-cucumber7-jvm/src/test/resources/features/with_examples.feature new file mode 100644 index 0000000..44e7b68 --- /dev/null +++ b/qase-cucumber7-jvm/src/test/resources/features/with_examples.feature @@ -0,0 +1,15 @@ +Feature: New case with examples + + Scenario Outline: success with Positive Examples + Given success step with parameter + Given success step with parameter + + Examples: + | a | b | + | "1" | "2" | + | "3" | "4" | + | "5" | "6" | + | "7" | "8" | + + Scenario: Success scenario + Given success step \ No newline at end of file diff --git a/qase-junit4-aspect/pom.xml b/qase-junit4-aspect/pom.xml index 8f8fcfd..1ee7dff 100644 --- a/qase-junit4-aspect/pom.xml +++ b/qase-junit4-aspect/pom.xml @@ -6,7 +6,7 @@ io.qase qase-java - 3.1.1 + 3.2.0 qase-junit4-aspect diff --git a/qase-junit4/README.md b/qase-junit4/README.md index 6e3bfb9..9bb51c4 100644 --- a/qase-junit4/README.md +++ b/qase-junit4/README.md @@ -12,7 +12,7 @@ Add the following dependency and repository to your pom.xml: io.qase qase-junit4 - 3.1.1 + 3.2.0 test @@ -63,9 +63,9 @@ configurations { dependencies { aspectjweaver "org.aspectj:aspectjweaver:1.9.8" - testImplementation 'io.qase:qase-api:3.1.1' - testImplementation 'io.qase:qase-junit4:3.1.1' - testImplementation 'io.qase:qase-junit4-aspect:3.1.1' + testImplementation 'io.qase:qase-api:3.2.0' + testImplementation 'io.qase:qase-junit4:3.2.0' + testImplementation 'io.qase:qase-junit4-aspect:3.2.0' testImplementation 'junit:junit:4.13.2' } diff --git a/qase-junit4/pom.xml b/qase-junit4/pom.xml index 6c9ec32..e34d759 100644 --- a/qase-junit4/pom.xml +++ b/qase-junit4/pom.xml @@ -5,7 +5,7 @@ qase-java io.qase - 3.1.1 + 3.2.0 4.0.0 diff --git a/qase-junit5/README.md b/qase-junit5/README.md index 6cc1905..21531b8 100644 --- a/qase-junit5/README.md +++ b/qase-junit5/README.md @@ -12,7 +12,7 @@ Add the following dependency and repository to your pom.xml: io.qase qase-junit5 - 3.1.1 + 3.2.0 @@ -55,7 +55,7 @@ add the below code to build.gradle: ``` dependencies { ... - testImplementation 'io.qase:qase-junit5:3.1.1' + testImplementation 'io.qase:qase-junit5:3.2.0' } test { diff --git a/qase-junit5/pom.xml b/qase-junit5/pom.xml index 00119d5..1a33b5b 100644 --- a/qase-junit5/pom.xml +++ b/qase-junit5/pom.xml @@ -5,7 +5,7 @@ qase-java io.qase - 3.1.1 + 3.2.0 4.0.0 diff --git a/qase-testng/README.md b/qase-testng/README.md index 69ea7d8..ee4ac52 100644 --- a/qase-testng/README.md +++ b/qase-testng/README.md @@ -22,7 +22,7 @@ Add the following dependency to your pom.xml: io.qase qase-testng - 3.1.1 + 3.2.0 test @@ -67,7 +67,7 @@ configurations { dependencies { aspectjweaver "org.aspectj:aspectjweaver:1.9.8" - testImplementation 'io.qase:qase-testng:3.1.1' + testImplementation 'io.qase:qase-testng:3.2.0' testImplementation 'org.testng:testng:7.1.0' } diff --git a/qase-testng/pom.xml b/qase-testng/pom.xml index ba2053d..6b6cb90 100644 --- a/qase-testng/pom.xml +++ b/qase-testng/pom.xml @@ -5,7 +5,7 @@ qase-java io.qase - 3.1.1 + 3.2.0 4.0.0