diff --git a/qase-cucumber5-jvm/pom.xml b/qase-cucumber5-jvm/pom.xml index 2005df6..a6dbc10 100644 --- a/qase-cucumber5-jvm/pom.xml +++ b/qase-cucumber5-jvm/pom.xml @@ -34,6 +34,11 @@ cucumber-java ${cucumber5-java.version} + + io.cucumber + gherkin + 5.1.0 + org.projectlombok lombok diff --git a/qase-cucumber5-jvm/src/main/java/io/qase/cucumber5/QaseEventListener.java b/qase-cucumber5-jvm/src/main/java/io/qase/cucumber5/QaseEventListener.java index b262a42..63d153e 100644 --- a/qase-cucumber5-jvm/src/main/java/io/qase/cucumber5/QaseEventListener.java +++ b/qase-cucumber5-jvm/src/main/java/io/qase/cucumber5/QaseEventListener.java @@ -1,5 +1,8 @@ package io.qase.cucumber5; +import gherkin.AstBuilder; +import gherkin.Parser; +import gherkin.ast.*; import io.cucumber.plugin.ConcurrentEventListener; import io.cucumber.plugin.event.*; import io.qase.api.QaseClient; @@ -15,17 +18,23 @@ import io.qase.cucumber5.guice.module.Cucumber5Module; 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.Files; +import java.nio.file.Paths; +import java.util.*; +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 5-JVM"; - @Getter(lazy = true, value = AccessLevel.PRIVATE) private final QaseTestCaseListener qaseTestCaseListener = createQaseListener(); @@ -44,12 +53,48 @@ public void setEventPublisher(EventPublisher publisher) { } } - private void testCaseStarted(TestStepStarted testStepStarted) { - if (testStepStarted.getTestStep() instanceof PickleStepTestStep) { + private void testCaseStarted(TestStepStarted event) { + if (EXAMPLES.get(getHash(event.getTestCase().getUri(), (long) event.getTestCase().getLine())) == null) { + TestCase testCase = event.getTestCase(); + URI uri = testCase.getUri(); + Parser gherkinParser = new Parser<>(new AstBuilder()); + try { + GherkinDocument gherkinDocument = gherkinParser.parse(new String(Files.readAllBytes(Paths.get(this.getClass().getClassLoader() + .getResource(uri.toString().replace("classpath:", "")).toURI())))); + parseExamples(uri, gherkinDocument); + } catch (URISyntaxException | IOException e) { + log.error(e.getMessage()); + } + } + if (event.getTestStep() instanceof PickleStepTestStep) { StepStorage.startStep(); } } + private void parseExamples(URI uri, GherkinDocument gherkinDocument) { + Feature feature = gherkinDocument.getFeature(); + List children = feature.getChildren(); + for (ScenarioDefinition child : children) { + if (child instanceof ScenarioOutline) { + ScenarioOutline scenario = (ScenarioOutline) child; + for (Examples exampleItem : scenario.getExamples()) { + List headers = new ArrayList<>(); + exampleItem.getTableHeader().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, (long) tableRow.getLocation().getLine()), example); + } + } + } + } + } + private void testStepFinished(TestStepFinished testStepFinished) { if (testStepFinished.getTestStep() instanceof PickleStepTestStep) { PickleStepTestStep step = (PickleStepTestStep) testStepFinished.getTestStep(); @@ -96,12 +141,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 +168,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.getLine())); + resultCreate.param(params); } private StatusEnum convertStatus(Status status) { diff --git a/qase-cucumber5-jvm/src/test/java/io/qase/cucumber5/QaseEventListenerTests.java b/qase-cucumber5-jvm/src/test/java/io/qase/cucumber5/QaseEventListenerTests.java index d2830ce..52cca5c 100644 --- a/qase-cucumber5-jvm/src/test/java/io/qase/cucumber5/QaseEventListenerTests.java +++ b/qase-cucumber5-jvm/src/test/java/io/qase/cucumber5/QaseEventListenerTests.java @@ -154,6 +154,98 @@ 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" + "}"))); } diff --git a/qase-cucumber5-jvm/src/test/java/io/qase/cucumber5/Steps.java b/qase-cucumber5-jvm/src/test/java/io/qase/cucumber5/Steps.java index 37f5933..679592e 100644 --- a/qase-cucumber5-jvm/src/test/java/io/qase/cucumber5/Steps.java +++ b/qase-cucumber5-jvm/src/test/java/io/qase/cucumber5/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-cucumber5-jvm/src/test/resources/features/with_examples.feature b/qase-cucumber5-jvm/src/test/resources/features/with_examples.feature new file mode 100644 index 0000000..44e7b68 --- /dev/null +++ b/qase-cucumber5-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