From 4f59f7b1a3f6d6669ccdb0d755cbc9e0d7fbdaec Mon Sep 17 00:00:00 2001
From: Pavel Anihimovsky <47742067+pavelanihimovsky@users.noreply.github.com>
Date: Wed, 3 Jun 2020 18:33:26 +0300
Subject: [PATCH] Feature/cucumber4 plugin (#11)
* Implement adaptor for Cucumber 4
* Increase version
* Fix Sonar issue
---
README.md | 14 ++++
aquality-tracking-cucumber4-jvm/pom.xml | 63 +++++++++++++++++
.../AqualityTrackingCucumber4Jvm.java | 54 ++++++++++++++
.../cucumber4jvm/TestCaseNameParser.java | 70 +++++++++++++++++++
.../cucumber4jvm/TestCaseResultParser.java | 57 +++++++++++++++
aquality-tracking-cucumber5-jvm/pom.xml | 6 +-
.../AqualityTrackingCucumber5Jvm.java | 2 +-
.../cucumber5jvm/TestCaseNameParser.java | 26 +++----
aquality-tracking-integrations-core/pom.xml | 4 +-
.../core/http/AqualityHttpClient.java | 2 +-
.../integrations/core/models/Test.java | 1 +
.../core/utilities/FileUtils.java | 9 ++-
pom.xml | 3 +-
13 files changed, 284 insertions(+), 27 deletions(-)
create mode 100644 aquality-tracking-cucumber4-jvm/pom.xml
create mode 100644 aquality-tracking-cucumber4-jvm/src/main/java/aquality/tracking/integrations/cucumber4jvm/AqualityTrackingCucumber4Jvm.java
create mode 100644 aquality-tracking-cucumber4-jvm/src/main/java/aquality/tracking/integrations/cucumber4jvm/TestCaseNameParser.java
create mode 100644 aquality-tracking-cucumber4-jvm/src/main/java/aquality/tracking/integrations/cucumber4jvm/TestCaseResultParser.java
diff --git a/README.md b/README.md
index 14a5eba..5d4f8b5 100644
--- a/README.md
+++ b/README.md
@@ -40,6 +40,20 @@ To use this adaptor with Cucumber 5 you have to add the following dependency:
Also you have to add plugin `aquality.tracking.integrations.cucumber5jvm.AqualityTrackingCucumber5Jvm` to the Cucumber Test Runner.
+## Cucumber 4 [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.aquality-automation/aquality-tracking-cucumber4-jvm/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.aquality-automation/aquality-tracking-cucumber4-jvm)
+
+To use this adaptor with Cucumber 4 you have to add the following dependency:
+
+```xml
+
+ com.github.aquality-automation
+ aquality-tracking-cucumber4-jvm
+ $LATEST_VERSION
+
+```
+
+Also you have to add plugin `aquality.tracking.integrations.cucumber4jvm.AqualityTrackingCucumber4Jvm` to the Cucumber Test Runner.
+
#### How to increase version for all modules
```bash
diff --git a/aquality-tracking-cucumber4-jvm/pom.xml b/aquality-tracking-cucumber4-jvm/pom.xml
new file mode 100644
index 0000000..798e1fd
--- /dev/null
+++ b/aquality-tracking-cucumber4-jvm/pom.xml
@@ -0,0 +1,63 @@
+
+
+ 4.0.0
+
+ aquality-tracking-cucumber4-jvm
+ 1.2.0
+ jar
+
+
+ aquality-tracking-integrations
+ com.github.aquality-automation
+ 1.2.0
+
+
+ Aquality Tracking Cucumber 5 JVM
+ Aquality Tracking integration for Cucumber 5 JVM.
+ https://github.com/aquality-automation/aquality-tracking-integrations-java
+
+
+
+ io.cucumber
+ cucumber-java
+ 4.8.1
+
+
+
+ com.github.aquality-automation
+ aquality-tracking-integrations-core
+ 1.2.0
+
+
+
+ org.apache.commons
+ commons-lang3
+ 3.10
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+ 3.3.0
+
+
+
+ single
+
+ package
+
+
+ jar-with-dependencies
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/aquality-tracking-cucumber4-jvm/src/main/java/aquality/tracking/integrations/cucumber4jvm/AqualityTrackingCucumber4Jvm.java b/aquality-tracking-cucumber4-jvm/src/main/java/aquality/tracking/integrations/cucumber4jvm/AqualityTrackingCucumber4Jvm.java
new file mode 100644
index 0000000..f567aba
--- /dev/null
+++ b/aquality-tracking-cucumber4-jvm/src/main/java/aquality/tracking/integrations/cucumber4jvm/AqualityTrackingCucumber4Jvm.java
@@ -0,0 +1,54 @@
+package aquality.tracking.integrations.cucumber4jvm;
+
+import aquality.tracking.integrations.core.AqualityTrackingLifecycle;
+import cucumber.api.event.*;
+
+import java.util.UUID;
+
+import static java.lang.String.format;
+
+public class AqualityTrackingCucumber4Jvm implements ConcurrentEventListener {
+
+ private final AqualityTrackingLifecycle lifecycle;
+
+ public AqualityTrackingCucumber4Jvm() {
+ lifecycle = new AqualityTrackingLifecycle();
+ }
+
+ @Override
+ public void setEventPublisher(EventPublisher eventPublisher) {
+ if (lifecycle.isEnabled()) {
+ eventPublisher.registerHandlerFor(TestRunStarted.class, this::handleTestRunStartedEvent);
+ eventPublisher.registerHandlerFor(TestRunFinished.class, this::handleTestRunFinishedEvent);
+
+ eventPublisher.registerHandlerFor(TestCaseStarted.class, this::handleTestCaseStartedEvent);
+ eventPublisher.registerHandlerFor(TestCaseFinished.class, this::handleTestCaseFinishedEvent);
+
+ eventPublisher.registerHandlerFor(EmbedEvent.class, this::handleEmbedEvent);
+ }
+ }
+
+ private void handleTestRunStartedEvent(final TestRunStarted event) {
+ lifecycle.startTestRun();
+ }
+
+ private void handleTestRunFinishedEvent(final TestRunFinished event) {
+ lifecycle.finishTestRun();
+ }
+
+ private void handleTestCaseStartedEvent(final TestCaseStarted event) {
+ String testName = new TestCaseNameParser(event.getTestCase()).parse();
+ lifecycle.startTestExecution(testName);
+ }
+
+ private void handleTestCaseFinishedEvent(final TestCaseFinished event) {
+ TestCaseResultParser testCaseResultParser = new TestCaseResultParser(event.result);
+ TestCaseResultParser.TestCaseResult testCaseResult = testCaseResultParser.parse();
+ lifecycle.finishTestExecution(testCaseResult.getFinalResultId(), testCaseResult.getFailReason());
+ }
+
+ private void handleEmbedEvent(final EmbedEvent event) {
+ String fileName = format("%s_%s", UUID.randomUUID(), event.name);
+ lifecycle.addAttachment(fileName, event.data);
+ }
+}
diff --git a/aquality-tracking-cucumber4-jvm/src/main/java/aquality/tracking/integrations/cucumber4jvm/TestCaseNameParser.java b/aquality-tracking-cucumber4-jvm/src/main/java/aquality/tracking/integrations/cucumber4jvm/TestCaseNameParser.java
new file mode 100644
index 0000000..18f98b8
--- /dev/null
+++ b/aquality-tracking-cucumber4-jvm/src/main/java/aquality/tracking/integrations/cucumber4jvm/TestCaseNameParser.java
@@ -0,0 +1,70 @@
+package aquality.tracking.integrations.cucumber4jvm;
+
+import aquality.tracking.integrations.core.AqualityUncheckedException;
+import cucumber.api.TestCase;
+import gherkin.AstBuilder;
+import gherkin.Parser;
+import gherkin.TokenMatcher;
+import gherkin.ast.Feature;
+import gherkin.ast.GherkinDocument;
+import gherkin.ast.ScenarioOutline;
+import gherkin.ast.TableRow;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import static aquality.tracking.integrations.core.utilities.FileUtils.getFileSource;
+import static java.lang.String.format;
+
+class TestCaseNameParser {
+
+ private final TestCase testCase;
+
+ TestCaseNameParser(TestCase testCase) {
+ this.testCase = testCase;
+ }
+
+ public String parse() {
+ Feature currentFeature = getCurrentFeature();
+ String scenarioName = getScenarioName(currentFeature, testCase.getName());
+ return format("%s: %s", currentFeature.getName(), scenarioName);
+ }
+
+ private Feature getCurrentFeature() {
+ Parser parser = new Parser<>(new AstBuilder());
+ TokenMatcher matcher = new TokenMatcher();
+ GherkinDocument gherkinDocument;
+ try {
+ String relativePathToFeatureFile = new URI(testCase.getUri()).getSchemeSpecificPart();
+ Path pathToFeatureFile = Paths.get(System.getProperty("user.dir"), relativePathToFeatureFile);
+
+ gherkinDocument = parser.parse(getFileSource(pathToFeatureFile), matcher);
+ } catch (URISyntaxException e) {
+ throw new AqualityUncheckedException(format("Failed to find feature file with URI: %s", testCase.getUri()), e);
+ }
+ return gherkinDocument.getFeature();
+ }
+
+ private String getScenarioName(final Feature feature, final String testCaseName) {
+ List examplesTableRows = feature.getChildren().stream()
+ .filter(child -> child.getName().equals(testCaseName))
+ .filter(child -> child instanceof ScenarioOutline)
+ .map(node -> ((ScenarioOutline) node).getExamples().get(0))
+ .flatMap(examples -> examples.getTableBody().stream())
+ .collect(Collectors.toList());
+
+ int tableRowIndex = IntStream.range(0, examplesTableRows.size())
+ .filter(i -> examplesTableRows.get(i).getLocation().getLine() == testCase.getLine())
+ .findFirst()
+ .orElse(-1);
+
+ return tableRowIndex == -1
+ ? testCaseName
+ : format("%s: %d", testCaseName, tableRowIndex);
+ }
+}
diff --git a/aquality-tracking-cucumber4-jvm/src/main/java/aquality/tracking/integrations/cucumber4jvm/TestCaseResultParser.java b/aquality-tracking-cucumber4-jvm/src/main/java/aquality/tracking/integrations/cucumber4jvm/TestCaseResultParser.java
new file mode 100644
index 0000000..498567d
--- /dev/null
+++ b/aquality-tracking-cucumber4-jvm/src/main/java/aquality/tracking/integrations/cucumber4jvm/TestCaseResultParser.java
@@ -0,0 +1,57 @@
+package aquality.tracking.integrations.cucumber4jvm;
+
+import aquality.tracking.integrations.core.FinalResultId;
+import cucumber.api.Result;
+import lombok.Data;
+import org.apache.commons.lang3.exception.ExceptionUtils;
+
+import static java.lang.String.format;
+
+class TestCaseResultParser {
+
+ private final Result result;
+
+ TestCaseResultParser(Result result) {
+ this.result = result;
+ }
+
+ TestCaseResult parse() {
+ TestCaseResult testCaseResult = new TestCaseResult();
+ switch (result.getStatus()) {
+ case PASSED:
+ testCaseResult.setFinalResultId(FinalResultId.PASSED);
+ break;
+ case FAILED:
+ testCaseResult.setFinalResultId(FinalResultId.FAILED);
+ testCaseResult.setFailReason(formatErrorMessage(result.getError()));
+ break;
+ case PENDING:
+ testCaseResult.setFinalResultId(FinalResultId.PENDING);
+ testCaseResult.setFailReason(getShortErrorMessage(result.getError()));
+ break;
+ case SKIPPED:
+ testCaseResult.setFinalResultId(FinalResultId.PENDING);
+ testCaseResult.setFailReason("Test skipped");
+ break;
+ default:
+ testCaseResult.setFinalResultId(FinalResultId.NOT_EXECUTED);
+ }
+ return testCaseResult;
+ }
+
+ private String formatErrorMessage(final Throwable error) {
+ final String message = getShortErrorMessage(error);
+ final String stackTrace = ExceptionUtils.getStackTrace(error);
+ return format("Message:%n%s%n%nStack Trace:%n%s", message, stackTrace);
+ }
+
+ private String getShortErrorMessage(final Throwable error) {
+ return error.getMessage().split("\n")[0];
+ }
+
+ @Data
+ static class TestCaseResult {
+ private int finalResultId;
+ private String failReason;
+ }
+}
diff --git a/aquality-tracking-cucumber5-jvm/pom.xml b/aquality-tracking-cucumber5-jvm/pom.xml
index e9e8291..275b93f 100644
--- a/aquality-tracking-cucumber5-jvm/pom.xml
+++ b/aquality-tracking-cucumber5-jvm/pom.xml
@@ -5,13 +5,13 @@
4.0.0
aquality-tracking-cucumber5-jvm
- 1.1.0
+ 1.2.0
jar
aquality-tracking-integrations
com.github.aquality-automation
- 1.1.0
+ 1.2.0
Aquality Tracking Cucumber 5 JVM
@@ -28,7 +28,7 @@
com.github.aquality-automation
aquality-tracking-integrations-core
- 1.1.0
+ 1.2.0
diff --git a/aquality-tracking-cucumber5-jvm/src/main/java/aquality/tracking/integrations/cucumber5jvm/AqualityTrackingCucumber5Jvm.java b/aquality-tracking-cucumber5-jvm/src/main/java/aquality/tracking/integrations/cucumber5jvm/AqualityTrackingCucumber5Jvm.java
index 4e3aeef..acfd8cf 100644
--- a/aquality-tracking-cucumber5-jvm/src/main/java/aquality/tracking/integrations/cucumber5jvm/AqualityTrackingCucumber5Jvm.java
+++ b/aquality-tracking-cucumber5-jvm/src/main/java/aquality/tracking/integrations/cucumber5jvm/AqualityTrackingCucumber5Jvm.java
@@ -36,7 +36,7 @@ private void handleTestRunFinishedEvent(final TestRunFinished event) {
}
private void handleTestCaseStartedEvent(final TestCaseStarted event) {
- String testName = new TestCaseNameParser(event.getTestCase()).getScenarioName();
+ String testName = new TestCaseNameParser(event.getTestCase()).parse();
lifecycle.startTestExecution(testName);
}
diff --git a/aquality-tracking-cucumber5-jvm/src/main/java/aquality/tracking/integrations/cucumber5jvm/TestCaseNameParser.java b/aquality-tracking-cucumber5-jvm/src/main/java/aquality/tracking/integrations/cucumber5jvm/TestCaseNameParser.java
index c57d9a8..5f23019 100644
--- a/aquality-tracking-cucumber5-jvm/src/main/java/aquality/tracking/integrations/cucumber5jvm/TestCaseNameParser.java
+++ b/aquality-tracking-cucumber5-jvm/src/main/java/aquality/tracking/integrations/cucumber5jvm/TestCaseNameParser.java
@@ -18,22 +18,15 @@
class TestCaseNameParser {
- private static final String SCENARIO_OUTLINE_KEYWORD = "Scenario Outline";
- private static final String SCENARIO_TEMPLATE_KEYWORD = "Scenario Template";
-
private final TestCase testCase;
TestCaseNameParser(TestCase testCase) {
this.testCase = testCase;
}
- public String getScenarioName() {
+ public String parse() {
Feature currentFeature = getCurrentFeature();
- String scenarioName = testCase.getName();
- String scenarioKeyword = testCase.getKeyword();
- if (scenarioKeyword.equals(SCENARIO_OUTLINE_KEYWORD) || scenarioKeyword.equals(SCENARIO_TEMPLATE_KEYWORD)) {
- scenarioName = getScenarioOutlineName(currentFeature, scenarioName);
- }
+ String scenarioName = getScenarioName(currentFeature, testCase.getName());
return format("%s: %s", currentFeature.getName(), scenarioName);
}
@@ -44,11 +37,11 @@ private Feature getCurrentFeature() {
return gherkinDocument.getFeature();
}
- private String getScenarioOutlineName(final Feature feature, final String scenarioName) {
+ private String getScenarioName(final Feature feature, final String testCaseName) {
List examplesTableRows = feature.getChildren().stream()
- .filter(child -> child.getName().equals(scenarioName))
- .map(node -> (ScenarioOutline) node)
- .map(outline -> outline.getExamples().get(0))
+ .filter(child -> child.getName().equals(testCaseName))
+ .filter(child -> child instanceof ScenarioOutline)
+ .map(node -> ((ScenarioOutline) node).getExamples().get(0))
.flatMap(examples -> examples.getTableBody().stream())
.collect(Collectors.toList());
@@ -57,9 +50,8 @@ private String getScenarioOutlineName(final Feature feature, final String scenar
.findFirst()
.orElse(-1);
- final String exampleLine = tableRowIndex == -1
- ? "EXAMPLE_LINE_NOT_FOUND"
- : String.valueOf(tableRowIndex);
- return format("%s: %s", scenarioName, exampleLine);
+ return tableRowIndex == -1
+ ? testCaseName
+ : format("%s: %d", testCaseName, tableRowIndex);
}
}
diff --git a/aquality-tracking-integrations-core/pom.xml b/aquality-tracking-integrations-core/pom.xml
index baeba0f..93c3eec 100644
--- a/aquality-tracking-integrations-core/pom.xml
+++ b/aquality-tracking-integrations-core/pom.xml
@@ -5,13 +5,13 @@
4.0.0
aquality-tracking-integrations-core
- 1.1.0
+ 1.2.0
jar
aquality-tracking-integrations
com.github.aquality-automation
- 1.1.0
+ 1.2.0
Aquality Tracking integrations core
diff --git a/aquality-tracking-integrations-core/src/main/java/aquality/tracking/integrations/core/http/AqualityHttpClient.java b/aquality-tracking-integrations-core/src/main/java/aquality/tracking/integrations/core/http/AqualityHttpClient.java
index 72c3bc6..50a7fde 100644
--- a/aquality-tracking-integrations-core/src/main/java/aquality/tracking/integrations/core/http/AqualityHttpClient.java
+++ b/aquality-tracking-integrations-core/src/main/java/aquality/tracking/integrations/core/http/AqualityHttpClient.java
@@ -44,7 +44,7 @@ private List getDefaultHeaders() {
List headers = new ArrayList<>();
headers.add(getBasicAuthHeader());
headers.add(new BasicHeader(HttpHeaders.ACCEPT, APPLICATION_JSON.getMimeType()));
- headers.add(new BasicHeader(HttpHeaders.CONTENT_TYPE, WILDCARD.getMimeType()));
+ headers.add(new BasicHeader(HttpHeaders.ACCEPT, WILDCARD.getMimeType()));
return headers;
}
diff --git a/aquality-tracking-integrations-core/src/main/java/aquality/tracking/integrations/core/models/Test.java b/aquality-tracking-integrations-core/src/main/java/aquality/tracking/integrations/core/models/Test.java
index 3af3c6d..fd9cd8f 100644
--- a/aquality-tracking-integrations-core/src/main/java/aquality/tracking/integrations/core/models/Test.java
+++ b/aquality-tracking-integrations-core/src/main/java/aquality/tracking/integrations/core/models/Test.java
@@ -9,6 +9,7 @@
public class Test {
private Integer id;
private String name;
+ private String body;
@JsonProperty("project_id")
private Integer projectId;
private List suites;
diff --git a/aquality-tracking-integrations-core/src/main/java/aquality/tracking/integrations/core/utilities/FileUtils.java b/aquality-tracking-integrations-core/src/main/java/aquality/tracking/integrations/core/utilities/FileUtils.java
index 659a56c..77f90e9 100644
--- a/aquality-tracking-integrations-core/src/main/java/aquality/tracking/integrations/core/utilities/FileUtils.java
+++ b/aquality-tracking-integrations-core/src/main/java/aquality/tracking/integrations/core/utilities/FileUtils.java
@@ -5,6 +5,7 @@
import java.io.*;
import java.net.URI;
import java.nio.file.Files;
+import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -32,10 +33,14 @@ public static String readResourceFile(final String filename) {
}
public static String getFileSource(final URI uri) {
- try (Stream lines = Files.lines(Paths.get(uri))) {
+ return getFileSource(Paths.get(uri));
+ }
+
+ public static String getFileSource(final Path filePath) {
+ try (Stream lines = Files.lines(filePath)) {
return lines.collect(Collectors.joining(System.lineSeparator()));
} catch (IOException e) {
- throw new AqualityUncheckedException(format("File %s not found.", uri), e);
+ throw new AqualityUncheckedException(format("File %s not found.", filePath), e);
}
}
diff --git a/pom.xml b/pom.xml
index 3891b9b..651c85c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,7 +7,7 @@
com.github.aquality-automation
aquality-tracking-integrations
pom
- 1.1.0
+ 1.2.0
Aquality Tracking integrations Libraries
Aquality Tracking integration libraries for JVM-based test frameworks.
@@ -21,6 +21,7 @@
aquality-tracking-integrations-core
aquality-tracking-cucumber5-jvm
+ aquality-tracking-cucumber4-jvm