Skip to content

Commit

Permalink
cucumber 7 parameterization support
Browse files Browse the repository at this point in the history
  • Loading branch information
savkk committed Oct 25, 2023
1 parent cca5e9c commit 5812b14
Show file tree
Hide file tree
Showing 25 changed files with 209 additions and 35 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Expand Up @@ -7,7 +7,7 @@
<groupId>io.qase</groupId>
<artifactId>qase-java</artifactId>
<packaging>pom</packaging>
<version>3.1.1</version>
<version>3.2.0</version>
<modules>
<module>qase-api</module>
<module>qase-testng</module>
Expand Down
2 changes: 1 addition & 1 deletion qase-api/README.md
Expand Up @@ -8,7 +8,7 @@ Add the following dependency and repository to your pom.xml:
<dependency>
<groupId>io.qase</groupId>
<artifactId>qase-api</artifactId>
<version>3.1.1</version>
<version>3.2.0</version>
</dependency>

```
Expand Down
2 changes: 1 addition & 1 deletion qase-api/pom.xml
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>qase-java</artifactId>
<groupId>io.qase</groupId>
<version>3.1.1</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
5 changes: 5 additions & 0 deletions 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;
Expand All @@ -20,4 +21,8 @@ public static Long getCaseId(List<String> tags) {
}
return null;
}

public static int getHash(URI uri, Long line) {
return (uri.toString() + line).hashCode();
}
}
2 changes: 1 addition & 1 deletion qase-cucumber3-jvm/README.md
Expand Up @@ -42,7 +42,7 @@ Add the following dependency and repository to your pom.xml:
<dependency>
<groupId>io.qase</groupId>
<artifactId>qase-cucumber3-jvm</artifactId>
<version>3.1.1</version>
<version>3.2.0</version>
</dependency>
</dependencies>
<build>
Expand Down
2 changes: 1 addition & 1 deletion qase-cucumber3-jvm/pom.xml
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>qase-java</artifactId>
<groupId>io.qase</groupId>
<version>3.1.1</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
2 changes: 1 addition & 1 deletion qase-cucumber4-jvm/README.md
Expand Up @@ -42,7 +42,7 @@ Add the following dependency and repository to your pom.xml:
<dependency>
<groupId>io.qase</groupId>
<artifactId>qase-cucumber4-jvm</artifactId>
<version>3.1.1</version>
<version>3.2.0</version>
</dependency>
</dependencies>
<build>
Expand Down
2 changes: 1 addition & 1 deletion qase-cucumber4-jvm/pom.xml
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>qase-java</artifactId>
<groupId>io.qase</groupId>
<version>3.1.1</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
2 changes: 1 addition & 1 deletion qase-cucumber5-jvm/README.md
Expand Up @@ -42,7 +42,7 @@ Add the following dependency and repository to your pom.xml:
<dependency>
<groupId>io.qase</groupId>
<artifactId>qase-cucumber5-jvm</artifactId>
<version>3.1.1</version>
<version>3.2.0</version>
</dependency>
</dependencies>
<build>
Expand Down
2 changes: 1 addition & 1 deletion qase-cucumber5-jvm/pom.xml
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>qase-java</artifactId>
<groupId>io.qase</groupId>
<version>3.1.1</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
2 changes: 1 addition & 1 deletion qase-cucumber6-jvm/README.md
Expand Up @@ -42,7 +42,7 @@ Add the following dependency and repository to your pom.xml:
<dependency>
<groupId>io.qase</groupId>
<artifactId>qase-cucumber6-jvm</artifactId>
<version>3.1.1</version>
<version>3.2.0</version>
</dependency>
</dependencies>
<build>
Expand Down
2 changes: 1 addition & 1 deletion qase-cucumber6-jvm/pom.xml
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>qase-java</artifactId>
<groupId>io.qase</groupId>
<version>3.1.1</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
2 changes: 1 addition & 1 deletion qase-cucumber7-jvm/README.md
Expand Up @@ -42,7 +42,7 @@ Add the following dependency and repository to your pom.xml:
<dependency>
<groupId>io.qase</groupId>
<artifactId>qase-cucumber7-jvm</artifactId>
<version>3.1.1</version>
<version>3.2.0</version>
</dependency>
</dependencies>
<build>
Expand Down
2 changes: 1 addition & 1 deletion qase-cucumber7-jvm/pom.xml
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>qase-java</artifactId>
<groupId>io.qase</groupId>
<version>3.1.1</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
@@ -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;
Expand All @@ -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<Integer, Map<String, String>> EXAMPLES = new HashMap<>();
private static final String REPORTER_NAME = "Cucumber 7-JVM";

@Getter(lazy = true, value = AccessLevel.PRIVATE)
private final QaseTestCaseListener qaseTestCaseListener = createQaseListener();

Expand All @@ -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<String> headers = new ArrayList<>();
exampleItem.getTableHeader()
.ifPresent(headerCell ->
headerCell.getCells().forEach(h -> headers.add(h.getValue())));
List<TableRow> tableBody = exampleItem.getTableBody();
for (TableRow tableRow : tableBody) {
List<TableCell> cells = tableRow.getCells();
HashMap<String, String> 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();
}
Expand Down Expand Up @@ -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<Envelope> envelopes = gherkinParser.parse(path);
envelopes.forEach(e -> parseExamples(uri, e));
} catch (IOException | URISyntaxException e) {
log.error(e.getMessage());
}
}
getQaseTestCaseListener().onTestCaseStarted();
}

Expand All @@ -96,12 +150,13 @@ private void testCaseFinished(TestCaseFinished event) {
}

private void setupResultItem(ResultCreate resultCreate, TestCaseFinished event) {
List<String> tags = event.getTestCase().getTags();
TestCase testCase = event.getTestCase();
List<String> 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());
Expand All @@ -122,6 +177,8 @@ private void setupResultItem(ResultCreate resultCreate, TestCaseFinished event)
.stacktrace(stacktrace)
.steps(steps.isEmpty() ? null : steps)
.defect(isDefect);
Map<String, String> params = EXAMPLES.get(getHash(testCase.getUri(), (long) testCase.getLocation().getLine()));
resultCreate.param(params);
}

private StatusEnum convertStatus(Status status) {
Expand Down
Expand Up @@ -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());

Expand Down Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions qase-cucumber7-jvm/src/test/java/io/qase/cucumber7/Steps.java
Expand Up @@ -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);
Expand Down

0 comments on commit 5812b14

Please sign in to comment.