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