diff --git a/CHANGELOG.md b/CHANGELOG.md index a496b50..a784526 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog ## [Unreleased] +### Fixed +- A bug when ambiguous item cases a Null Pointer Exception +- Incorrect item type settings +### Added +- Nested steps support ## [5.0.0-BETA-13] ### Added diff --git a/README.md b/README.md index 288c1f6..0a6e7f3 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,42 @@ -# Cucumber3 Agent for ReportPortal - [ ![Download](https://api.bintray.com/packages/epam/reportportal/agent-java-cucumber3/images/download.svg) ](https://bintray.com/epam/reportportal/agent-java-cucumber3/_latestVersion) - -[![Join Slack chat!](https://reportportal-slack-auto.herokuapp.com/badge.svg)](https://reportportal-slack-auto.herokuapp.com) -[![stackoverflow](https://img.shields.io/badge/reportportal-stackoverflow-orange.svg?style=flat)](http://stackoverflow.com/questions/tagged/reportportal) -[![UserVoice](https://img.shields.io/badge/uservoice-vote%20ideas-orange.svg?style=flat)](https://rpp.uservoice.com/forums/247117-report-portal) -[![Build with Love](https://img.shields.io/badge/build%20with-❤%EF%B8%8F%E2%80%8D-lightgrey.svg)](http://reportportal.io?style=flat) - - -### Installation - -Add to POM.xml - -**dependency** - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - - - false - - bintray-epam-reportportal - bintray - http://dl.bintray.com/epam/reportportal - - - - - - com.epam.reportportal - agent-java-cucumber3 - 0.0.1-beta - pom - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -### Install Reporter, Configuration - -See readme for Cucumber Agent 2 for details on installation and configuration (as this (3rd) version of agent is a copy of the 2nd version with minor chagnes in dependencies) - https://github.com/reportportal/agent-java-cucumber2 - - +# Cucumber3 Agent for ReportPortal + [ ![Download](https://api.bintray.com/packages/epam/reportportal/agent-java-cucumber3/images/download.svg) ](https://bintray.com/epam/reportportal/agent-java-cucumber3/_latestVersion) + +![CI Build](https://github.com/reportportal/agent-java-cucumber3/workflows/CI%20Build/badge.svg) +[![Join Slack chat!](https://reportportal-slack-auto.herokuapp.com/badge.svg)](https://reportportal-slack-auto.herokuapp.com) +[![stackoverflow](https://img.shields.io/badge/reportportal-stackoverflow-orange.svg?style=flat)](http://stackoverflow.com/questions/tagged/reportportal) +[![UserVoice](https://img.shields.io/badge/uservoice-vote%20ideas-orange.svg?style=flat)](https://rpp.uservoice.com/forums/247117-report-portal) +[![Build with Love](https://img.shields.io/badge/build%20with-❤%EF%B8%8F%E2%80%8D-lightgrey.svg)](http://reportportal.io?style=flat) + + +### Installation + +Add to POM.xml + +**dependency** + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + + false + + bintray-epam-reportportal + bintray + http://dl.bintray.com/epam/reportportal + + + + + + com.epam.reportportal + agent-java-cucumber3 + 0.0.1-beta + pom + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +### Install Reporter, Configuration + +See readme for Cucumber Agent 2 for details on installation and configuration (as this (3rd) version of agent is a copy of the 2nd version with minor chagnes in dependencies) - https://github.com/reportportal/agent-java-cucumber2 + + diff --git a/build.gradle b/build.gradle index 57ee0ac..cf0f7fd 100644 --- a/build.gradle +++ b/build.gradle @@ -47,7 +47,7 @@ publishing { } dependencies { - api 'com.epam.reportportal:client-java:5.0.6' + api 'com.epam.reportportal:client-java:5.0.7' api 'com.epam.reportportal:commons-model:5.0.0' api 'com.google.code.findbugs:jsr305:3.0.2' @@ -55,6 +55,7 @@ dependencies { testImplementation('com.github.reportportal:agent-java-test-utils:ddcf50ee20') + testImplementation 'org.aspectj:aspectjweaver:1.9.2' testImplementation 'org.hamcrest:hamcrest-core:2.2' testImplementation 'org.mockito:mockito-core:3.3.3' testImplementation 'ch.qos.logback:logback-classic:1.2.3' @@ -72,9 +73,16 @@ dependencies { } test { + outputs.upToDateWhen { return false } useJUnitPlatform() + maxParallelForks(5) // it's forks - separate JVMs, should not interfere each other + doFirst { + def weaver = configurations.testRuntimeClasspath.find { it.name.contains("aspectjweaver") } + jvmArgs += "-javaagent:$weaver" + } } + wrapper { gradleVersion = '5.4.1' } diff --git a/src/main/java/com/epam/reportportal/cucumber/AbstractReporter.java b/src/main/java/com/epam/reportportal/cucumber/AbstractReporter.java index 3bb8c52..307c6a3 100644 --- a/src/main/java/com/epam/reportportal/cucumber/AbstractReporter.java +++ b/src/main/java/com/epam/reportportal/cucumber/AbstractReporter.java @@ -68,7 +68,7 @@ public abstract class AbstractReporter implements Formatter { private final Map, RunningContext.ScenarioContext> currentScenarioContextMap = new ConcurrentHashMap<>(); - private final Map threadCurrentScenarioContextMap = new ConcurrentHashMap<>(); + private final ThreadLocal currentScenarioContext = new ThreadLocal<>(); // There is no event for recognizing end of feature in Cucumber. // This map is used to record the last scenario time and its feature uri. @@ -134,18 +134,18 @@ protected void afterLaunch() { * Start Cucumber scenario */ protected void beforeScenario(RunningContext.FeatureContext currentFeatureContext, - RunningContext.ScenarioContext currentScenarioContext, String scenarioName) { + RunningContext.ScenarioContext context, String scenarioName) { String description = getDescription(currentFeatureContext.getUri()); - String codeRef = getCodeRef(currentFeatureContext.getUri(), currentScenarioContext.getLine()); + String codeRef = getCodeRef(currentFeatureContext.getUri(), context.getLine()); Maybe id = Utils.startNonLeafNode(launch.get(), currentFeatureContext.getFeatureId(), scenarioName, description, codeRef, - currentScenarioContext.getAttributes(), + context.getAttributes(), getScenarioTestItemType() ); - currentScenarioContext.setId(id); + context.setId(id); } /** @@ -153,16 +153,17 @@ protected void beforeScenario(RunningContext.FeatureContext currentFeatureContex * Put scenario end time in a map to check last scenario end time per feature */ protected void afterScenario(TestCaseFinished event) { - RunningContext.ScenarioContext currentScenarioContext = getCurrentScenarioContext(); + RunningContext.ScenarioContext context = getCurrentScenarioContext(); for (Map.Entry, RunningContext.ScenarioContext> scenarioContext : currentScenarioContextMap.entrySet()) { - if (scenarioContext.getValue().getLine() == currentScenarioContext.getLine()) { + if (scenarioContext.getValue().getLine() == context.getLine()) { currentScenarioContextMap.remove(scenarioContext.getKey()); - Date endTime = Utils.finishTestItem(launch.get(), currentScenarioContext.getId(), event.result.getStatus()); + Date endTime = Utils.finishTestItem(launch.get(), context.getId(), event.result.getStatus()); String featureURI = scenarioContext.getKey().getValue(); featureEndTime.put(featureURI, endTime); break; } } + currentScenarioContext.set(null); } /** @@ -297,7 +298,7 @@ protected boolean isBefore(TestStep step) { protected abstract Maybe getRootItemId(); protected RunningContext.ScenarioContext getCurrentScenarioContext() { - return threadCurrentScenarioContextMap.get(Thread.currentThread().getId()); + return currentScenarioContext.get(); } private RunningContext.FeatureContext createFeatureContext(TestCase testCase) { @@ -381,23 +382,23 @@ private void handleStartOfTestCase(TestCaseStarted event) { throw new IllegalStateException("Scenario URI does not match Feature URI."); } - RunningContext.ScenarioContext scenarioContext = currentFeatureContext.getScenarioContext(testCase); - String scenarioName = Utils.buildNodeName(scenarioContext.getKeyword(), + RunningContext.ScenarioContext context = currentFeatureContext.getScenarioContext(testCase); + String scenarioName = Utils.buildNodeName(context.getKeyword(), AbstractReporter.COLON_INFIX, - scenarioContext.getName(), - scenarioContext.getOutlineIteration() + context.getName(), + context.getOutlineIteration() ); Pair scenarioNameFeatureURI = Pair.of(testCase.getScenarioDesignation(), currentFeatureContext.getUri()); - RunningContext.ScenarioContext currentScenarioContext = currentScenarioContextMap.get(scenarioNameFeatureURI); + RunningContext.ScenarioContext scenarioContext = currentScenarioContextMap.get(scenarioNameFeatureURI); - if (currentScenarioContext == null) { - currentScenarioContext = currentFeatureContext.getScenarioContext(testCase); - currentScenarioContextMap.put(scenarioNameFeatureURI, currentScenarioContext); - threadCurrentScenarioContextMap.put(Thread.currentThread().getId(), currentScenarioContext); + if (scenarioContext == null) { + scenarioContext = currentFeatureContext.getScenarioContext(testCase); + currentScenarioContextMap.put(scenarioNameFeatureURI, scenarioContext); + currentScenarioContext.set(scenarioContext); } - beforeScenario(currentFeatureContext, currentScenarioContext, scenarioName); + beforeScenario(currentFeatureContext, scenarioContext, scenarioName); } private void handleTestStepStarted(TestStepStarted event) { diff --git a/src/main/java/com/epam/reportportal/cucumber/RunningContext.java b/src/main/java/com/epam/reportportal/cucumber/RunningContext.java index dfc2b43..bbd6517 100644 --- a/src/main/java/com/epam/reportportal/cucumber/RunningContext.java +++ b/src/main/java/com/epam/reportportal/cucumber/RunningContext.java @@ -17,6 +17,7 @@ import com.epam.ta.reportportal.ws.model.attribute.ItemAttributesRQ; import cucumber.api.PickleStepTestStep; +import cucumber.api.Result; import cucumber.api.TestCase; import cucumber.api.TestStep; import cucumber.api.event.TestSourceRead; @@ -154,6 +155,9 @@ static class ScenarioContext { private final Map scenarioLocationMap = new HashMap<>(); private Set attributes = new HashSet<>(); + private Maybe currentStepId; + private Maybe hookStepId; + private Result.Type hookStatus; private Maybe id = null; private Background background; private ScenarioDefinition scenario; @@ -284,5 +288,29 @@ boolean hasBackground() { String getOutlineIteration() { return outlineIteration; } + + public Maybe getCurrentStepId() { + return currentStepId; + } + + public void setCurrentStepId(Maybe currentStepId) { + this.currentStepId = currentStepId; + } + + public Maybe getHookStepId() { + return hookStepId; + } + + public void setHookStepId(Maybe hookStepId) { + this.hookStepId = hookStepId; + } + + public Result.Type getHookStatus() { + return hookStatus; + } + + public void setHookStatus(Result.Type hookStatus) { + this.hookStatus = hookStatus; + } } } diff --git a/src/main/java/com/epam/reportportal/cucumber/ScenarioReporter.java b/src/main/java/com/epam/reportportal/cucumber/ScenarioReporter.java index 608f0a6..3155242 100644 --- a/src/main/java/com/epam/reportportal/cucumber/ScenarioReporter.java +++ b/src/main/java/com/epam/reportportal/cucumber/ScenarioReporter.java @@ -15,19 +15,19 @@ */ package com.epam.reportportal.cucumber; +import com.epam.reportportal.service.Launch; import com.epam.ta.reportportal.ws.model.StartTestItemRQ; import cucumber.api.HookType; import cucumber.api.Result; import cucumber.api.TestStep; import gherkin.ast.Step; import io.reactivex.Maybe; +import org.apache.commons.lang3.tuple.Pair; import rp.com.google.common.base.Supplier; import rp.com.google.common.base.Suppliers; import java.util.Calendar; -import static cucumber.api.Result.Type.PASSED; - /** * Cucumber reporter for ReportPortal that reports scenarios as test methods. *

@@ -50,10 +50,9 @@ * @author Vitaliy Tsvihun */ public class ScenarioReporter extends AbstractReporter { - private static final String SEPARATOR = "-------------------------"; - private static final String EMPTY_SUFFIX = ""; - private static final String INFO = "INFO"; - private static final String STEP_ = "STEP "; + private static final String RP_STORY_TYPE = "SUITE"; + private static final String RP_TEST_TYPE = "STORY"; + private static final String RP_STEP_TYPE = "STEP"; protected Supplier> rootSuiteId; @@ -65,48 +64,59 @@ protected void beforeLaunch() { @Override protected void beforeStep(TestStep testStep) { - RunningContext.ScenarioContext currentScenarioContext = getCurrentScenarioContext(); - Step step = currentScenarioContext.getStep(testStep); - int lineInFeaturefile = step.getLocation().getLine(); - String decoratedStepName = lineInFeaturefile + decorateMessage(Utils.buildNodeName(currentScenarioContext.getStepPrefix(), - step.getKeyword(), - Utils.getStepName(testStep), - EMPTY_SUFFIX - )); - String multilineArg = Utils.buildMultilineArgument(testStep); - Utils.sendLog(decoratedStepName + multilineArg, INFO, null); + RunningContext.ScenarioContext context = getCurrentScenarioContext(); + Step step = context.getStep(testStep); + StartTestItemRQ rq = Utils.buildStartStepRequest(context.getStepPrefix(), testStep, step, false); + context.setCurrentStepId(launch.get().startTestItem(context.getId(), rq)); } @Override protected void afterStep(Result result) { - if (!result.is(PASSED)) { - reportResult(result, decorateMessage(STEP_ + result.getStatus().toString().toUpperCase())); - } + reportResult(result, null); + RunningContext.ScenarioContext context = getCurrentScenarioContext(); + Launch myLaunch = launch.get(); + Utils.finishTestItem(myLaunch, context.getCurrentStepId(), result.getStatus()); + context.setCurrentStepId(null); + myLaunch.getStepReporter().finishPreviousStep(); } @Override protected void beforeHooks(HookType hookType) { - // noop + StartTestItemRQ rq = new StartTestItemRQ(); + rq.setHasStats(false); + Pair typeName = Utils.getHookTypeAndName(hookType); + rq.setType(typeName.getKey()); + rq.setName(typeName.getValue()); + rq.setStartTime(Calendar.getInstance().getTime()); + + RunningContext.ScenarioContext context = getCurrentScenarioContext(); + context.setHookStepId(launch.get().startTestItem(getCurrentScenarioContext().getId(), rq)); + context.setHookStatus(Result.Type.PASSED); } @Override protected void afterHooks(Boolean isBefore) { - // noop + RunningContext.ScenarioContext context = getCurrentScenarioContext(); + Launch myLaunch = launch.get(); + Utils.finishTestItem(myLaunch, context.getHookStepId(), context.getHookStatus()); + context.setHookStepId(null); + myLaunch.getStepReporter().finishPreviousStep(); } @Override protected void hookFinished(TestStep step, Result result, Boolean isBefore) { - reportResult(result, (isBefore ? "@Before" : "@After") + "\n" + step.getCodeLocation()); + reportResult(result, (isBefore ? "Before" : "After") + " hook: " + step.getCodeLocation()); + getCurrentScenarioContext().setHookStatus(result.getStatus()); } @Override protected String getFeatureTestItemType() { - return "TEST"; + return RP_TEST_TYPE; } @Override protected String getScenarioTestItemType() { - return "STEP"; + return RP_STEP_TYPE; } @Override @@ -136,18 +146,8 @@ protected void startRootItem() { StartTestItemRQ rq = new StartTestItemRQ(); rq.setName("Root User Story"); rq.setStartTime(Calendar.getInstance().getTime()); - rq.setType("STORY"); + rq.setType(RP_STORY_TYPE); return launch.get().startTestItem(rq); }); } - - /** - * Add separators to log item to distinguish from real log messages - * - * @param message to decorate - * @return decorated message - */ - private String decorateMessage(String message) { - return ScenarioReporter.SEPARATOR + message + ScenarioReporter.SEPARATOR; - } } diff --git a/src/main/java/com/epam/reportportal/cucumber/StepReporter.java b/src/main/java/com/epam/reportportal/cucumber/StepReporter.java index ec4e21e..8d5c5d6 100644 --- a/src/main/java/com/epam/reportportal/cucumber/StepReporter.java +++ b/src/main/java/com/epam/reportportal/cucumber/StepReporter.java @@ -15,14 +15,16 @@ */ package com.epam.reportportal.cucumber; +import com.epam.reportportal.service.Launch; import com.epam.ta.reportportal.ws.model.StartTestItemRQ; -import cucumber.api.*; +import cucumber.api.HookType; +import cucumber.api.Result; +import cucumber.api.TestStep; import gherkin.ast.Step; import io.reactivex.Maybe; +import org.apache.commons.lang3.tuple.Pair; import java.util.Calendar; -import java.util.Collections; -import java.util.List; /** * Cucumber reporter for ReportPortal that reports individual steps as test @@ -45,16 +47,11 @@ * @author Vitaliy Tsvihun */ public class StepReporter extends AbstractReporter { - - protected Maybe currentStepId; - protected Maybe hookStepId; - protected Result.Type hookStatus; + private static final String RP_STORY_TYPE = "STORY"; + private static final String RP_TEST_TYPE = "SCENARIO"; public StepReporter() { super(); - currentStepId = null; - hookStepId = null; - hookStatus = null; } @Override @@ -66,79 +63,55 @@ protected Maybe getRootItemId() { protected void beforeStep(TestStep testStep) { RunningContext.ScenarioContext context = getCurrentScenarioContext(); Step step = context.getStep(testStep); - StartTestItemRQ rq = new StartTestItemRQ(); - rq.setName(Utils.buildNodeName(context.getStepPrefix(), step.getKeyword(), Utils.getStepName(testStep), " ")); - rq.setDescription(Utils.buildMultilineArgument(testStep)); - rq.setStartTime(Calendar.getInstance().getTime()); - rq.setType("STEP"); - List arguments = testStep instanceof PickleStepTestStep ? - ((PickleStepTestStep) testStep).getDefinitionArgument() : - Collections.emptyList(); - rq.setParameters(Utils.getParameters(arguments, step.getText())); - String codeRef = Utils.getCodeRef(testStep); - rq.setCodeRef(codeRef); - rq.setTestCaseId(Utils.getTestCaseId(testStep, codeRef).getId()); - rq.setAttributes(Utils.getAttributes(testStep)); - currentStepId = launch.get().startTestItem(context.getId(), rq); + StartTestItemRQ rq = Utils.buildStartStepRequest(context.getStepPrefix(), testStep, step, true); + context.setCurrentStepId(launch.get().startTestItem(context.getId(), rq)); } @Override protected void afterStep(Result result) { reportResult(result, null); - Utils.finishTestItem(launch.get(), currentStepId, result.getStatus()); - currentStepId = null; + RunningContext.ScenarioContext context = getCurrentScenarioContext(); + Launch myLaunch = launch.get(); + Utils.finishTestItem(myLaunch, context.getCurrentStepId(), result.getStatus()); + context.setCurrentStepId(null); + myLaunch.getStepReporter().finishPreviousStep(); } @Override protected void beforeHooks(HookType hookType) { StartTestItemRQ rq = new StartTestItemRQ(); - String name = null; - String type = null; - switch (hookType) { - case Before: - name = "Before hooks"; - type = "BEFORE_TEST"; - break; - case After: - name = "After hooks"; - type = "AFTER_TEST"; - break; - case AfterStep: - name = "After step"; - type = "AFTER_METHOD"; - break; - case BeforeStep: - name = "Before step"; - type = "BEFORE_METHOD"; - break; - } - rq.setName(name); + Pair typeName = Utils.getHookTypeAndName(hookType); + rq.setType(typeName.getKey()); + rq.setName(typeName.getValue()); rq.setStartTime(Calendar.getInstance().getTime()); - rq.setType(type); - hookStepId = launch.get().startTestItem(getCurrentScenarioContext().getId(), rq); - hookStatus = Result.Type.PASSED; + RunningContext.ScenarioContext context = getCurrentScenarioContext(); + context.setHookStepId(launch.get().startTestItem(getCurrentScenarioContext().getId(), rq)); + context.setHookStatus(Result.Type.PASSED); } @Override protected void afterHooks(Boolean isBefore) { - Utils.finishTestItem(launch.get(), hookStepId, hookStatus); - hookStepId = null; + RunningContext.ScenarioContext context = getCurrentScenarioContext(); + Launch myLaunch = launch.get(); + Utils.finishTestItem(myLaunch, context.getHookStepId(), context.getHookStatus()); + context.setHookStepId(null); + myLaunch.getStepReporter().finishPreviousStep(); } @Override protected void hookFinished(TestStep step, Result result, Boolean isBefore) { reportResult(result, (isBefore ? "Before" : "After") + " hook: " + step.getCodeLocation()); - hookStatus = result.getStatus(); + getCurrentScenarioContext().setHookStatus(result.getStatus()); } @Override protected String getFeatureTestItemType() { - return "SUITE"; + return RP_STORY_TYPE; } @Override protected String getScenarioTestItemType() { - return "SCENARIO"; + return RP_TEST_TYPE; } } diff --git a/src/main/java/com/epam/reportportal/cucumber/Utils.java b/src/main/java/com/epam/reportportal/cucumber/Utils.java index c788061..0bf124e 100644 --- a/src/main/java/com/epam/reportportal/cucumber/Utils.java +++ b/src/main/java/com/epam/reportportal/cucumber/Utils.java @@ -29,15 +29,15 @@ import com.epam.ta.reportportal.ws.model.attribute.ItemAttributesRQ; import com.epam.ta.reportportal.ws.model.log.SaveLogRQ; import com.epam.ta.reportportal.ws.model.log.SaveLogRQ.File; -import cucumber.api.HookTestStep; -import cucumber.api.PickleStepTestStep; -import cucumber.api.Result; -import cucumber.api.TestStep; +import cucumber.api.*; import cucumber.runtime.StepDefinitionMatch; +import gherkin.ast.Step; import gherkin.ast.Tag; +import gherkin.pickles.Argument; import gherkin.pickles.*; import io.reactivex.Maybe; import io.reactivex.annotations.Nullable; +import org.apache.commons.lang3.tuple.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import rp.com.google.common.base.Function; @@ -287,11 +287,8 @@ public static Set getAttributes(TestStep testStep) { @Nullable static String getCodeRef(TestStep testStep) { - Field definitionMatchField = getDefinitionMatchField(testStep); - if (definitionMatchField != null) { - try { StepDefinitionMatch stepDefinitionMatch = (StepDefinitionMatch) definitionMatchField.get(testStep); Field stepDefinitionField = stepDefinitionMatch.getClass().getDeclaredField(STEP_DEFINITION_FIELD_NAME); @@ -304,11 +301,9 @@ static String getCodeRef(TestStep testStep) { } catch (NoSuchFieldException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { return null; } - } else { return null; } - } static List getParameters(List arguments, String text) { @@ -400,4 +395,46 @@ public static String getDescription(@Nonnull String uri) { public static String getCodeRef(@Nonnull String uri, int line) { return uri + ":" + line; } + + public static StartTestItemRQ buildStartStepRequest(String stepPrefix, TestStep testStep, Step step, boolean hasStats) { + StartTestItemRQ rq = new StartTestItemRQ(); + rq.setHasStats(hasStats); + rq.setName(Utils.buildNodeName(stepPrefix, step.getKeyword(), Utils.getStepName(testStep), "")); + rq.setDescription(Utils.buildMultilineArgument(testStep)); + rq.setStartTime(Calendar.getInstance().getTime()); + rq.setType("STEP"); + List arguments = testStep instanceof PickleStepTestStep ? + ((PickleStepTestStep) testStep).getDefinitionArgument() : + Collections.emptyList(); + rq.setParameters(Utils.getParameters(arguments, step.getText())); + String codeRef = Utils.getCodeRef(testStep); + rq.setCodeRef(codeRef); + rq.setTestCaseId(ofNullable(Utils.getTestCaseId(testStep, codeRef)).map(TestCaseIdEntry::getId).orElse(null)); + rq.setAttributes(Utils.getAttributes(testStep)); + return rq; + } + + public static Pair getHookTypeAndName(HookType hookType) { + String name = null; + String type = null; + switch (hookType) { + case Before: + name = "Before hooks"; + type = "BEFORE_TEST"; + break; + case After: + name = "After hooks"; + type = "AFTER_TEST"; + break; + case AfterStep: + name = "After step"; + type = "AFTER_METHOD"; + break; + case BeforeStep: + name = "Before step"; + type = "BEFORE_METHOD"; + break; + } + return Pair.of(type, name); + } } diff --git a/src/test/java/com/epam/reportportal/cucumber/AmbiguousScenarioTest.java b/src/test/java/com/epam/reportportal/cucumber/AmbiguousScenarioTest.java new file mode 100644 index 0000000..04341f8 --- /dev/null +++ b/src/test/java/com/epam/reportportal/cucumber/AmbiguousScenarioTest.java @@ -0,0 +1,119 @@ +package com.epam.reportportal.cucumber; + +import com.epam.reportportal.cucumber.integration.TestScenarioReporter; +import com.epam.reportportal.cucumber.integration.TestStepReporter; +import com.epam.reportportal.cucumber.integration.util.TestUtils; +import com.epam.reportportal.listeners.ListenerParameters; +import com.epam.reportportal.service.ReportPortal; +import com.epam.reportportal.service.ReportPortalClient; +import com.epam.reportportal.util.test.CommonUtils; +import com.epam.ta.reportportal.ws.model.FinishTestItemRQ; +import com.epam.ta.reportportal.ws.model.StartTestItemRQ; +import cucumber.api.CucumberOptions; +import cucumber.api.testng.AbstractTestNGCucumberTests; +import org.apache.commons.lang3.tuple.Pair; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; + +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; +import static org.mockito.ArgumentMatchers.same; +import static org.mockito.Mockito.*; + +public class AmbiguousScenarioTest { + @CucumberOptions(features = "src/test/resources/features/AmbiguousTest.feature", glue = { + "com.epam.reportportal.cucumber.integration.feature" }, plugin = { "pretty", + "com.epam.reportportal.cucumber.integration.TestStepReporter" }) + public static class SimpleTestStepReporter extends AbstractTestNGCucumberTests { + + } + + @CucumberOptions(features = "src/test/resources/features/AmbiguousTest.feature", glue = { + "com.epam.reportportal.cucumber.integration.feature" }, plugin = { "pretty", + "com.epam.reportportal.cucumber.integration.TestScenarioReporter" }) + public static class SimpleTestScenarioReporter extends AbstractTestNGCucumberTests { + + } + + private final String launchId = CommonUtils.namedId("launch_"); + private final String suiteId = CommonUtils.namedId("suite_"); + private final String testId = CommonUtils.namedId("test_"); + private final List stepIds = Stream.generate(() -> CommonUtils.namedId("step_")).limit(1).collect(Collectors.toList()); + private final List nestedStepIds = Stream.generate(() -> CommonUtils.namedId("step_")).limit(1).collect(Collectors.toList()); + private final List> nestedSteps = nestedStepIds.stream() + .map(s -> Pair.of(stepIds.get(0), s)) + .collect(Collectors.toList()); + + private final ListenerParameters params = TestUtils.standardParameters(); + private final ReportPortalClient client = mock(ReportPortalClient.class); + private final ExecutorService executorService = Executors.newSingleThreadExecutor(); + private final ReportPortal reportPortal = ReportPortal.create(client, params, executorService); + + @BeforeEach + public void setup() { + TestUtils.mockLaunch(client, launchId, suiteId, testId, stepIds); + TestScenarioReporter.RP.set(reportPortal); + TestStepReporter.RP.set(reportPortal); + } + + public static void verifyRequest(StartTestItemRQ rq, String type, boolean hasStats) { + assertThat(rq.getType(), allOf(notNullValue(), equalTo(type))); + assertThat(rq.getStartTime(), notNullValue()); + assertThat(rq.getName(), notNullValue()); + assertThat(rq.isHasStats(), equalTo(hasStats)); + } + + @Test + public void verify_step_reporter_ambiguous_item() { + TestUtils.runTests(SimpleTestStepReporter.class); + + ArgumentCaptor stepCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(1)).startTestItem(same(testId), stepCaptor.capture()); + + StartTestItemRQ rq = stepCaptor.getValue(); + assertThat(rq.getType(), equalTo("STEP")); + + ArgumentCaptor stepFinishCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); + verify(client, times(1)).finishTestItem(same(stepIds.get(0)), stepFinishCaptor.capture()); + + FinishTestItemRQ finishRq = stepFinishCaptor.getValue(); + assertThat(finishRq.getStatus(), equalTo("SKIPPED")); + + ArgumentCaptor testFinishCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); + verify(client, times(1)).finishTestItem(same(testId), testFinishCaptor.capture()); + + finishRq = testFinishCaptor.getValue(); + assertThat(finishRq.getStatus(), equalTo("SKIPPED")); + } + + @Test + public void verify_scenario_reporter_ambiguous_item() { + TestUtils.mockNestedSteps(client, nestedSteps); + TestUtils.runTests(SimpleTestScenarioReporter.class); + + ArgumentCaptor stepCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(1)).startTestItem(same(stepIds.get(0)), stepCaptor.capture()); + + StartTestItemRQ rq = stepCaptor.getValue(); + assertThat(rq.getType(), equalTo("STEP")); + + ArgumentCaptor stepFinishCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); + verify(client, times(1)).finishTestItem(same(nestedStepIds.get(0)), stepFinishCaptor.capture()); + + FinishTestItemRQ finishRq = stepFinishCaptor.getValue(); + assertThat(finishRq.getStatus(), equalTo("SKIPPED")); + + ArgumentCaptor testFinishCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); + verify(client, times(1)).finishTestItem(same(stepIds.get(0)), testFinishCaptor.capture()); + + finishRq = testFinishCaptor.getValue(); + assertThat(finishRq.getStatus(), equalTo("SKIPPED")); + } +} diff --git a/src/test/java/com/epam/reportportal/cucumber/AttributeReportingTest.java b/src/test/java/com/epam/reportportal/cucumber/AttributeReportingTest.java new file mode 100644 index 0000000..67aabc8 --- /dev/null +++ b/src/test/java/com/epam/reportportal/cucumber/AttributeReportingTest.java @@ -0,0 +1,129 @@ +package com.epam.reportportal.cucumber; + +import com.epam.reportportal.cucumber.integration.TestScenarioReporter; +import com.epam.reportportal.cucumber.integration.TestStepReporter; +import com.epam.reportportal.cucumber.integration.util.TestUtils; +import com.epam.reportportal.listeners.ListenerParameters; +import com.epam.reportportal.service.ReportPortal; +import com.epam.reportportal.service.ReportPortalClient; +import com.epam.reportportal.util.test.CommonUtils; +import com.epam.ta.reportportal.ws.model.StartTestItemRQ; +import com.epam.ta.reportportal.ws.model.attribute.ItemAttributesRQ; +import cucumber.api.CucumberOptions; +import cucumber.api.testng.AbstractTestNGCucumberTests; +import org.apache.commons.lang3.tuple.Pair; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; + +import java.util.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; +import static org.mockito.ArgumentMatchers.same; +import static org.mockito.Mockito.*; + +public class AttributeReportingTest { + @CucumberOptions(features = "src/test/resources/features/belly.feature", glue = { + "com.epam.reportportal.cucumber.integration.feature" }, plugin = { "pretty", + "com.epam.reportportal.cucumber.integration.TestStepReporter" }) + public static class SimpleTestStepReporter extends AbstractTestNGCucumberTests { + + } + + @CucumberOptions(features = "src/test/resources/features/belly.feature", glue = { + "com.epam.reportportal.cucumber.integration.feature" }, plugin = { "pretty", + "com.epam.reportportal.cucumber.integration.TestScenarioReporter" }) + public static class SimpleTestScenarioReporter extends AbstractTestNGCucumberTests { + + } + + private final String launchId = CommonUtils.namedId("launch_"); + private final String suiteId = CommonUtils.namedId("suite_"); + private final String testId = CommonUtils.namedId("test_"); + private final List stepIds = Stream.generate(() -> CommonUtils.namedId("step_")).limit(3).collect(Collectors.toList()); + private final List nestedStepIds = Stream.generate(() -> CommonUtils.namedId("step_")).limit(3).collect(Collectors.toList()); + private final List> nestedSteps = nestedStepIds.stream() + .map(s -> Pair.of(stepIds.get(0), s)) + .collect(Collectors.toList()); + + private final ListenerParameters params = TestUtils.standardParameters(); + private final ReportPortalClient client = mock(ReportPortalClient.class); + private final ExecutorService executorService = Executors.newSingleThreadExecutor(); + private final ReportPortal reportPortal = ReportPortal.create(client, params, executorService); + + @BeforeEach + public void setup() { + TestUtils.mockLaunch(client, launchId, suiteId, testId, stepIds); + TestScenarioReporter.RP.set(reportPortal); + TestStepReporter.RP.set(reportPortal); + } + + private static void verifyAttributes(Collection attributes, Collection> values) { + assertThat(attributes, hasSize(values.size())); + Set> attributePairs = attributes.stream() + .map(a -> Pair.of(a.getKey(), a.getValue())) + .collect(Collectors.toSet()); + values.forEach(v -> assertThat(attributePairs, hasItem(v))); + } + + private static void verifyAnnotationAttributes(List testSteps) { + Set stepAttributes = testSteps.get(0).getAttributes(); + verifyAttributes(stepAttributes, Collections.singleton(Pair.of("key", "value"))); + + stepAttributes = testSteps.get(1).getAttributes(); + verifyAttributes( + stepAttributes, + new HashSet<>(Arrays.asList(Pair.of("key1", "value1"), Pair.of("key2", "value2"), Pair.of("k1", "v"), Pair.of("k2", "v"))) + ); + + stepAttributes = testSteps.get(2).getAttributes(); + verifyAttributes(stepAttributes, new HashSet<>(Arrays.asList(Pair.of(null, "v1"), Pair.of(null, "v2")))); + } + + @Test + public void verify_step_reporter_attributes() { + TestUtils.runTests(SimpleTestStepReporter.class); + + ArgumentCaptor suiteCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(1)).startTestItem(suiteCaptor.capture()); + + assertThat(suiteCaptor.getValue().getAttributes(), anyOf(emptyIterable(), nullValue())); + + ArgumentCaptor testCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(1)).startTestItem(same(suiteId), testCaptor.capture()); + verifyAttributes(testCaptor.getValue().getAttributes(), Collections.singleton(Pair.of(null, "@ok"))); + + ArgumentCaptor stepCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(3)).startTestItem(same(testId), stepCaptor.capture()); + + verifyAnnotationAttributes(stepCaptor.getAllValues()); + } + + @Test + public void verify_scenario_reporter_attributes() { + TestUtils.mockNestedSteps(client, nestedSteps); + TestUtils.runTests(SimpleTestScenarioReporter.class); + + ArgumentCaptor mainSuiteCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(1)).startTestItem(mainSuiteCaptor.capture()); + assertThat(mainSuiteCaptor.getValue().getAttributes(), anyOf(emptyIterable(), nullValue())); + + ArgumentCaptor suiteCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(1)).startTestItem(same(suiteId), suiteCaptor.capture()); + assertThat(mainSuiteCaptor.getValue().getAttributes(), anyOf(emptyIterable(), nullValue())); + + ArgumentCaptor testCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(1)).startTestItem(same(testId), testCaptor.capture()); + verifyAttributes(testCaptor.getValue().getAttributes(), Collections.singleton(Pair.of(null, "@ok"))); + + ArgumentCaptor stepCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(3)).startTestItem(same(stepIds.get(0)), stepCaptor.capture()); + + verifyAnnotationAttributes(stepCaptor.getAllValues()); + } +} diff --git a/src/test/java/com/epam/reportportal/cucumber/CodeRefTest.java b/src/test/java/com/epam/reportportal/cucumber/CodeRefTest.java index 47a6f0b..0b389b6 100644 --- a/src/test/java/com/epam/reportportal/cucumber/CodeRefTest.java +++ b/src/test/java/com/epam/reportportal/cucumber/CodeRefTest.java @@ -25,8 +25,6 @@ import java.util.stream.Stream; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.endsWith; -import static org.hamcrest.Matchers.startsWith; import static org.hamcrest.Matchers.*; import static org.mockito.Mockito.any; import static org.mockito.Mockito.*; @@ -94,12 +92,8 @@ public void verify_code_reference_scenario_reporter() { StartTestItemRQ feature = items.get(0); StartTestItemRQ scenario = items.get(1); - assertThat(feature.getCodeRef(), - allOf(notNullValue(), equalTo(FEATURE_CODE_REFERENCES)) - ); - assertThat(scenario.getCodeRef(), - allOf(notNullValue(), equalTo(SCENARIO_CODE_REFERENCES)) - ); + assertThat(feature.getCodeRef(), allOf(notNullValue(), equalTo(FEATURE_CODE_REFERENCES))); + assertThat(scenario.getCodeRef(), allOf(notNullValue(), equalTo(SCENARIO_CODE_REFERENCES))); } private static final List STEP_CODE_REFERENCE = Arrays.asList( @@ -122,16 +116,15 @@ public void verify_code_reference_step_reporter() { StartTestItemRQ scenario = items.get(0); List steps = items.subList(1, items.size()); - assertThat(scenario.getCodeRef(), - allOf(notNullValue(), equalTo(SCENARIO_CODE_REFERENCES)) - ); + assertThat(scenario.getCodeRef(), allOf(notNullValue(), equalTo(SCENARIO_CODE_REFERENCES))); IntStream.range(0, STEP_CODE_REFERENCE.size()) .forEach(i -> assertThat(steps.get(i).getCodeRef(), allOf(notNullValue(), equalTo(STEP_CODE_REFERENCE.get(i))))); } private static final List TWO_FEATURES_CODE_REFERENCES = Arrays.asList("src/test/resources/features/TwoScenarioInOne.feature:3", - "src/test/resources/features/TwoScenarioInOne.feature:7"); + "src/test/resources/features/TwoScenarioInOne.feature:7" + ); private static final List TWO_STEPS_CODE_REFERENCE = Arrays.asList( "com.epam.reportportal.cucumber.integration.feature.EmptySteps.i_have_empty_step", @@ -152,9 +145,8 @@ public void verify_code_reference_two_features_step_reporter() { List suites = items.subList(0, 2); List steps = items.subList(2, items.size()); - IntStream.range(0, TWO_FEATURES_CODE_REFERENCES.size()).forEach(i -> assertThat(suites.get(i).getCodeRef(), allOf(notNullValue(), - equalTo(TWO_FEATURES_CODE_REFERENCES.get(i)) - ))); + IntStream.range(0, TWO_FEATURES_CODE_REFERENCES.size()) + .forEach(i -> assertThat(suites.get(i).getCodeRef(), allOf(notNullValue(), equalTo(TWO_FEATURES_CODE_REFERENCES.get(i))))); IntStream.range(0, TWO_STEPS_CODE_REFERENCE.size()) .forEach(i -> assertThat(steps.get(i).getCodeRef(), allOf(notNullValue(), equalTo(TWO_STEPS_CODE_REFERENCE.get(i))))); diff --git a/src/test/java/com/epam/reportportal/cucumber/HooksTest.java b/src/test/java/com/epam/reportportal/cucumber/HooksTest.java new file mode 100644 index 0000000..c8a27bf --- /dev/null +++ b/src/test/java/com/epam/reportportal/cucumber/HooksTest.java @@ -0,0 +1,89 @@ +package com.epam.reportportal.cucumber; + +import com.epam.reportportal.cucumber.integration.TestScenarioReporter; +import com.epam.reportportal.cucumber.integration.TestStepReporter; +import com.epam.reportportal.cucumber.integration.util.TestUtils; +import com.epam.reportportal.listeners.ListenerParameters; +import com.epam.reportportal.restendpoint.http.MultiPartRequest; +import com.epam.reportportal.service.ReportPortal; +import com.epam.reportportal.service.ReportPortalClient; +import com.epam.reportportal.util.test.CommonUtils; +import cucumber.api.CucumberOptions; +import cucumber.api.testng.AbstractTestNGCucumberTests; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.mockito.Mockito.*; + +/** + * TODO: finish the test + */ +public class HooksTest { + + @CucumberOptions(features = "src/test/resources/features/DummyScenario.feature", glue = { + "com.epam.reportportal.cucumber.integration.hooks" }, plugin = { "pretty", + "com.epam.reportportal.cucumber.integration.TestStepReporter" }) + public static class MyStepReporter extends AbstractTestNGCucumberTests { + + } + + @CucumberOptions(features = "src/test/resources/features/DummyScenario.feature", glue = { + "com.epam.reportportal.cucumber.integration.feature" }, plugin = { "pretty", + "com.epam.reportportal.cucumber.integration.TestStepReporter" }) + public static class MyStepReporter2 extends AbstractTestNGCucumberTests { + + } + + private final String launchId = CommonUtils.namedId("launch_"); + private final String suiteId = CommonUtils.namedId("suite_"); + private final String testId = CommonUtils.namedId("test_"); + private final List stepIds = Stream.generate(() -> CommonUtils.namedId("step_")).limit(3).collect(Collectors.toList()); + + private final ListenerParameters params = TestUtils.standardParameters(); + private final ReportPortalClient client = mock(ReportPortalClient.class); + private final ExecutorService executorService = Executors.newSingleThreadExecutor(); + private final ReportPortal reportPortal = ReportPortal.create(client, params, executorService); + + @BeforeEach + public void setup() { + TestUtils.mockLaunch(client, launchId, suiteId, testId, stepIds); + TestUtils.mockLogging(client); + TestScenarioReporter.RP.set(reportPortal); + TestStepReporter.RP.set(reportPortal); + } + + @AfterEach + public void tearDown() { + CommonUtils.shutdownExecutorService(executorService); + } + + @Test + public void verify_before_after_reported_in_steps() { + TestUtils.runTests(MyStepReporter.class); + + verify(client, times(1)).startTestItem(any()); + verify(client, times(1)).startTestItem(same(suiteId), any()); + verify(client, times(8)).startTestItem(same(testId), any()); + verify(client, times(14)).log(any(MultiPartRequest.class)); + } + + @Test + public void verify_before_after_not_reported_in_steps() { + TestUtils.runTests(MyStepReporter2.class); + + verify(client, times(1)).startTestItem(any()); + verify(client, times(1)).startTestItem(same(suiteId), any()); + verify(client, times(2)).startTestItem(same(testId), any()); + verify(client, times(2)).log(any(MultiPartRequest.class)); + + } +} + + diff --git a/src/test/java/com/epam/reportportal/cucumber/LaunchLoggingContextTest.java b/src/test/java/com/epam/reportportal/cucumber/LaunchLoggingContextTest.java index 9ee6dc7..06a67ea 100644 --- a/src/test/java/com/epam/reportportal/cucumber/LaunchLoggingContextTest.java +++ b/src/test/java/com/epam/reportportal/cucumber/LaunchLoggingContextTest.java @@ -5,6 +5,7 @@ import com.epam.reportportal.service.ReportPortal; import org.junit.jupiter.api.Test; import org.mockito.Mock; + import static org.mockito.Mockito.*; /** diff --git a/src/test/java/com/epam/reportportal/cucumber/ManualStepReporterTest.java b/src/test/java/com/epam/reportportal/cucumber/ManualStepReporterTest.java new file mode 100644 index 0000000..80cfb12 --- /dev/null +++ b/src/test/java/com/epam/reportportal/cucumber/ManualStepReporterTest.java @@ -0,0 +1,218 @@ +package com.epam.reportportal.cucumber; + +import com.epam.reportportal.cucumber.integration.TestScenarioReporter; +import com.epam.reportportal.cucumber.integration.TestStepReporter; +import com.epam.reportportal.cucumber.integration.feature.ManualStepReporterSteps; +import com.epam.reportportal.cucumber.integration.util.TestUtils; +import com.epam.reportportal.listeners.ListenerParameters; +import com.epam.reportportal.restendpoint.http.MultiPartRequest; +import com.epam.reportportal.service.ReportPortal; +import com.epam.reportportal.service.ReportPortalClient; +import com.epam.reportportal.util.test.CommonUtils; +import com.epam.ta.reportportal.ws.model.FinishTestItemRQ; +import com.epam.ta.reportportal.ws.model.StartTestItemRQ; +import com.epam.ta.reportportal.ws.model.log.SaveLogRQ; +import cucumber.api.CucumberOptions; +import cucumber.api.testng.AbstractTestNGCucumberTests; +import org.apache.commons.lang3.tuple.Pair; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; + +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; +import static org.mockito.ArgumentMatchers.same; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.*; + +public class ManualStepReporterTest { + @CucumberOptions(features = "src/test/resources/features/ManualStepReporter.feature", glue = { + "com.epam.reportportal.cucumber.integration.feature" }, plugin = { "pretty", + "com.epam.reportportal.cucumber.integration.TestStepReporter" }) + public static class SimpleTestStepReporter extends AbstractTestNGCucumberTests { + + } + + @CucumberOptions(features = "src/test/resources/features/ManualStepReporter.feature", glue = { + "com.epam.reportportal.cucumber.integration.feature" }, plugin = { "pretty", + "com.epam.reportportal.cucumber.integration.TestScenarioReporter" }) + public static class SimpleTestScenarioReporter extends AbstractTestNGCucumberTests { + + } + + private final String launchId = CommonUtils.namedId("launch_"); + private final String suiteId = CommonUtils.namedId("suite_"); + private final String testId = CommonUtils.namedId("test_"); + private final List stepIds = Stream.generate(() -> CommonUtils.namedId("step_")).limit(2).collect(Collectors.toList()); + + // Step reporter + private final List stepNestedStepIds = Stream.generate(() -> CommonUtils.namedId("step_")) + .limit(3) + .collect(Collectors.toList()); + private final List> stepNestedSteps = Stream.concat( + Stream.of(Pair.of(stepIds.get(0), stepNestedStepIds.get(0))), + stepNestedStepIds.stream().skip(1).map(s -> Pair.of(stepIds.get(1), s)) + ).collect(Collectors.toList()); + + // Scenario reporter + private final List scenarioNestedStepIds = Stream.generate(() -> CommonUtils.namedId("step_")) + .limit(2) + .collect(Collectors.toList()); + private final List> scenarioNestedSteps = scenarioNestedStepIds.stream() + .map(s -> Pair.of(stepIds.get(0), s)) + .collect(Collectors.toList()); + private final List scenarioSecondNestedStepIds = Stream.generate(() -> CommonUtils.namedId("step_")) + .limit(3) + .collect(Collectors.toList()); + private final List> scenarioSecondNestedSteps = Stream.concat( + Stream.of(Pair.of(scenarioNestedStepIds.get(0), scenarioSecondNestedStepIds.get(0))), + scenarioSecondNestedStepIds.stream().skip(1).map(s -> Pair.of(scenarioNestedStepIds.get(1), s)) + ).collect(Collectors.toList()); + + private final ListenerParameters params = TestUtils.standardParameters(); + private final ReportPortalClient client = mock(ReportPortalClient.class); + private final ExecutorService executorService = Executors.newSingleThreadExecutor(); + private final ReportPortal reportPortal = ReportPortal.create(client, params, executorService); + + @BeforeEach + public void setup() { + TestUtils.mockLaunch(client, launchId, suiteId, testId, stepIds); + TestUtils.mockLogging(client); + TestScenarioReporter.RP.set(reportPortal); + TestStepReporter.RP.set(reportPortal); + } + + private static void verifyStepStart(StartTestItemRQ step, String stepName) { + assertThat(step.getName(), equalTo(stepName)); + assertThat(step.isHasStats(), equalTo(Boolean.FALSE)); + assertThat(step.getType(), equalTo("STEP")); + } + + private static void verifyLogEntry(SaveLogRQ firstStepLog, String stepId, String duringSecondNestedStepLog) { + assertThat(firstStepLog.getItemUuid(), equalTo(stepId)); + assertThat(firstStepLog.getMessage(), containsString(duringSecondNestedStepLog)); + assertThat(firstStepLog.getFile(), nullValue()); + } + + @Test + @SuppressWarnings("unchecked") + public void verify_step_reporter_steps_integrity() { + TestUtils.mockNestedSteps(client, stepNestedSteps); + TestUtils.runTests(SimpleTestStepReporter.class); + + verify(client, times(2)).startTestItem(same(testId), any()); + ArgumentCaptor firstStepCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(1)).startTestItem(same(stepIds.get(0)), firstStepCaptor.capture()); + ArgumentCaptor logCaptor = ArgumentCaptor.forClass(MultiPartRequest.class); + verify(client, times(5)).log(logCaptor.capture()); + StartTestItemRQ firstStep = firstStepCaptor.getValue(); + List logs = logCaptor.getAllValues() + .stream() + .flatMap(l -> l.getSerializedRQs().stream()) + .flatMap(l -> ((List) l.getRequest()).stream()) + .collect(Collectors.toList()); + SaveLogRQ firstStepLog = logs.get(0); + + verifyStepStart(firstStep, ManualStepReporterSteps.FIRST_NAME); + verifyLogEntry(firstStepLog, stepNestedStepIds.get(0), ManualStepReporterSteps.FIRST_NESTED_STEP_LOG); + + ArgumentCaptor secondStepCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(2)).startTestItem(same(stepIds.get(1)), secondStepCaptor.capture()); + List secondSteps = secondStepCaptor.getAllValues(); + List secondStepLogs = logs.subList(1, logs.size()); + + StartTestItemRQ secondStep = secondSteps.get(0); + verifyStepStart(secondStep, ManualStepReporterSteps.SECOND_NAME); + verifyLogEntry(secondStepLogs.get(0), stepNestedStepIds.get(1), ManualStepReporterSteps.DURING_SECOND_NESTED_STEP_LOG); + verifyLogEntry(secondStepLogs.get(1), stepNestedStepIds.get(1), ManualStepReporterSteps.SECOND_NESTED_STEP_LOG); + + StartTestItemRQ thirdStep = secondSteps.get(1); + verifyStepStart(thirdStep, ManualStepReporterSteps.THIRD_NAME); + + SaveLogRQ pugLog = secondStepLogs.get(2); + assertThat(pugLog.getItemUuid(), equalTo(stepNestedStepIds.get(2))); + assertThat(pugLog.getMessage(), emptyString()); + assertThat(pugLog.getFile(), notNullValue()); + + verifyLogEntry(secondStepLogs.get(3), stepNestedStepIds.get(2), ManualStepReporterSteps.THIRD_NESTED_STEP_LOG); + + ArgumentCaptor finishIdCaptor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor finishRqCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); + verify(client, times(7)).finishTestItem(finishIdCaptor.capture(), finishRqCaptor.capture()); + List finishIds = finishIdCaptor.getAllValues(); + List finishRqs = finishRqCaptor.getAllValues(); + List nestedStepFinishes = IntStream.range(0, finishIds.size()) + .filter(i -> stepNestedStepIds.contains(finishIds.get(i))) + .mapToObj(finishRqs::get) + .collect(Collectors.toList()); + + assertThat(nestedStepFinishes.get(0).getStatus(), equalTo("PASSED")); + assertThat(nestedStepFinishes.get(1).getStatus(), equalTo("PASSED")); + assertThat(nestedStepFinishes.get(2).getStatus(), equalTo("FAILED")); + } + + @Test + @SuppressWarnings("unchecked") + public void verify_scenario_reporter_steps_integrity() { + TestUtils.mockNestedSteps(client, scenarioNestedSteps); + TestUtils.mockNestedSteps(client, scenarioSecondNestedSteps); + TestUtils.runTests(SimpleTestScenarioReporter.class); + + verify(client, times(2)).startTestItem(same(stepIds.get(0)), any()); + ArgumentCaptor firstStepCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(1)).startTestItem(same(scenarioNestedStepIds.get(0)), firstStepCaptor.capture()); + ArgumentCaptor logCaptor = ArgumentCaptor.forClass(MultiPartRequest.class); + verify(client, times(5)).log(logCaptor.capture()); + StartTestItemRQ firstStep = firstStepCaptor.getValue(); + List logs = logCaptor.getAllValues() + .stream() + .flatMap(l -> l.getSerializedRQs().stream()) + .flatMap(l -> ((List) l.getRequest()).stream()) + .collect(Collectors.toList()); + + SaveLogRQ firstStepLog = logs.get(0); + verifyStepStart(firstStep, ManualStepReporterSteps.FIRST_NAME); + verifyLogEntry(firstStepLog, scenarioSecondNestedStepIds.get(0), ManualStepReporterSteps.FIRST_NESTED_STEP_LOG); + + ArgumentCaptor secondStepCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(2)).startTestItem(same(scenarioNestedStepIds.get(1)), secondStepCaptor.capture()); + List secondSteps = secondStepCaptor.getAllValues(); + List secondStepLogs = logs.subList(1, logs.size()); + + StartTestItemRQ secondStep = secondSteps.get(0); + verifyStepStart(secondStep, ManualStepReporterSteps.SECOND_NAME); + verifyLogEntry(secondStepLogs.get(0), scenarioSecondNestedStepIds.get(1), ManualStepReporterSteps.DURING_SECOND_NESTED_STEP_LOG); + verifyLogEntry(secondStepLogs.get(1), scenarioSecondNestedStepIds.get(1), ManualStepReporterSteps.SECOND_NESTED_STEP_LOG); + + StartTestItemRQ thirdStep = secondSteps.get(1); + verifyStepStart(thirdStep, ManualStepReporterSteps.THIRD_NAME); + + SaveLogRQ pugLog = secondStepLogs.get(2); + assertThat(pugLog.getItemUuid(), equalTo(scenarioSecondNestedStepIds.get(2))); + assertThat(pugLog.getMessage(), emptyString()); + assertThat(pugLog.getFile(), notNullValue()); + + verifyLogEntry(secondStepLogs.get(3), scenarioSecondNestedStepIds.get(2), ManualStepReporterSteps.THIRD_NESTED_STEP_LOG); + + ArgumentCaptor finishIdCaptor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor finishRqCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); + verify(client, times(8)).finishTestItem(finishIdCaptor.capture(), finishRqCaptor.capture()); + List finishIds = finishIdCaptor.getAllValues(); + List finishRqs = finishRqCaptor.getAllValues(); + List nestedStepFinishes = IntStream.range(0, finishIds.size()) + .filter(i -> scenarioSecondNestedStepIds.contains(finishIds.get(i))) + .mapToObj(finishRqs::get) + .collect(Collectors.toList()); + + assertThat(nestedStepFinishes.get(0).getStatus(), equalTo("PASSED")); + assertThat(nestedStepFinishes.get(1).getStatus(), equalTo("PASSED")); + assertThat(nestedStepFinishes.get(2).getStatus(), equalTo("FAILED")); + } +} diff --git a/src/test/java/com/epam/reportportal/cucumber/NestedStepsScenarioReporterTest.java b/src/test/java/com/epam/reportportal/cucumber/NestedStepsScenarioReporterTest.java new file mode 100644 index 0000000..bd3833c --- /dev/null +++ b/src/test/java/com/epam/reportportal/cucumber/NestedStepsScenarioReporterTest.java @@ -0,0 +1,149 @@ +package com.epam.reportportal.cucumber; + +import com.epam.reportportal.cucumber.integration.TestScenarioReporter; +import com.epam.reportportal.cucumber.integration.TestStepReporter; +import com.epam.reportportal.cucumber.integration.util.TestUtils; +import com.epam.reportportal.listeners.ListenerParameters; +import com.epam.reportportal.service.ReportPortal; +import com.epam.reportportal.service.ReportPortalClient; +import com.epam.reportportal.util.test.CommonUtils; +import com.epam.ta.reportportal.ws.model.StartTestItemRQ; +import com.epam.ta.reportportal.ws.model.attribute.ItemAttributesRQ; +import cucumber.api.CucumberOptions; +import cucumber.api.testng.AbstractTestNGCucumberTests; +import org.apache.commons.lang3.tuple.Pair; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; + +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; +import static org.mockito.Mockito.*; + +public class NestedStepsScenarioReporterTest { + + @CucumberOptions(features = "src/test/resources/features/NestedStepsFeature.feature", glue = { + "com.epam.reportportal.cucumber.integration.feature" }, plugin = { "pretty", + "com.epam.reportportal.cucumber.integration.TestScenarioReporter" }) + public static class NestedStepsScenarioReporter extends AbstractTestNGCucumberTests { + + } + + private final String launchId = CommonUtils.namedId("launch_"); + private final String suiteId = CommonUtils.namedId("suite_"); + private final String testId = CommonUtils.namedId("test_"); + private final String stepId = CommonUtils.namedId("step_"); + private final List nestedStepIds = Stream.generate(() -> CommonUtils.namedId("nested_step_")) + .limit(2) + .collect(Collectors.toList()); + private final List nestedNestedStepIds = Stream.generate(() -> CommonUtils.namedId("double_nested_step_")) + .limit(3) + .collect(Collectors.toList()); + private final String nestedNestedNestedStepId = CommonUtils.namedId("triple_nested_step_"); + private final List> firstLevelNestedStepIds = nestedStepIds.stream() + .map(s -> Pair.of(stepId, s)) + .collect(Collectors.toList()); + + private final List> secondLevelNestedStepIds = Stream.concat(Stream.of(Pair.of(nestedStepIds.get(0), + nestedNestedStepIds.get(0) + )), + nestedNestedStepIds.stream().skip(1).map(i -> Pair.of(nestedStepIds.get(1), i)) + ).collect(Collectors.toList()); + + private final ListenerParameters params = TestUtils.standardParameters(); + private final ReportPortalClient client = mock(ReportPortalClient.class); + private final ExecutorService executorService = Executors.newSingleThreadExecutor(); + private final ReportPortal reportPortal = ReportPortal.create(client, params, executorService); + + @BeforeEach + public void setup() { + TestUtils.mockLaunch(client, launchId, suiteId, testId, stepId); + TestUtils.mockNestedSteps(client, firstLevelNestedStepIds); + TestUtils.mockNestedSteps(client, secondLevelNestedStepIds); + TestUtils.mockNestedSteps(client, Pair.of(nestedNestedStepIds.get(0), nestedNestedNestedStepId)); + TestScenarioReporter.RP.set(reportPortal); + TestStepReporter.RP.set(reportPortal); + } + + @AfterEach + public void tearDown() { + CommonUtils.shutdownExecutorService(executorService); + } + + public static final List FIRST_LEVEL_NAMES = Arrays.asList("Given I have a step", "When I have one more step"); + + public static final List SECOND_LEVEL_NAMES = Arrays.asList("A step inside step", + "A step with parameters", + "A step with attributes" + ); + + @Test + public void test_scenario_reporter_nested_steps() { + TestUtils.runTests(NestedStepsScenarioReporter.class); + + ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(1)).startTestItem(captor.capture()); + verify(client, times(1)).startTestItem(same(suiteId), captor.capture()); + verify(client, times(1)).startTestItem(same(testId), captor.capture()); + List parentItems = captor.getAllValues(); + parentItems.forEach(i -> assertThat(i.isHasStats(), anyOf(equalTo(Boolean.TRUE)))); + + ArgumentCaptor firstLevelCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(2)).startTestItem(same(stepId), firstLevelCaptor.capture()); + + List firstLevelRqs = firstLevelCaptor.getAllValues(); + IntStream.range(0, firstLevelRqs.size()).forEach(i -> { + StartTestItemRQ rq = firstLevelRqs.get(i); + assertThat(rq.isHasStats(), equalTo(Boolean.FALSE)); + assertThat(rq.getName(), equalTo(FIRST_LEVEL_NAMES.get(i))); + }); + + ArgumentCaptor secondLevelCaptor1 = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(1)).startTestItem(same(nestedStepIds.get(0)), secondLevelCaptor1.capture()); + + StartTestItemRQ secondLevelRq1 = secondLevelCaptor1.getValue(); + assertThat(secondLevelRq1.getName(), equalTo(SECOND_LEVEL_NAMES.get(0))); + assertThat(secondLevelRq1.isHasStats(), equalTo(Boolean.FALSE)); + + ArgumentCaptor secondLevelCaptor2 = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(2)).startTestItem(same(nestedStepIds.get(1)), secondLevelCaptor2.capture()); + + List secondLevelRqs2 = secondLevelCaptor2.getAllValues(); + IntStream.range(1, SECOND_LEVEL_NAMES.size()).forEach(i -> { + assertThat(secondLevelRqs2.get(i - 1).getName(), equalTo(SECOND_LEVEL_NAMES.get(i))); + assertThat(secondLevelRqs2.get(i - 1).isHasStats(), equalTo(Boolean.FALSE)); + }); + + StartTestItemRQ stepWithAttributes = secondLevelRqs2.get(1); + Set attributes = stepWithAttributes.getAttributes(); + assertThat(attributes, allOf(notNullValue(), hasSize(2))); + List> kvAttributes = attributes.stream() + .map(a -> Pair.of(a.getKey(), a.getValue())) + .collect(Collectors.toList()); + List> keyAndValueList = kvAttributes.stream().filter(kv -> kv.getKey() != null).collect(Collectors.toList()); + assertThat(keyAndValueList, hasSize(1)); + assertThat(keyAndValueList.get(0).getKey(), equalTo("key")); + assertThat(keyAndValueList.get(0).getValue(), equalTo("value")); + + List> tagList = kvAttributes.stream().filter(kv -> kv.getKey() == null).collect(Collectors.toList()); + assertThat(tagList, hasSize(1)); + assertThat(tagList.get(0).getValue(), equalTo("tag")); + + ArgumentCaptor thirdLevelCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(1)).startTestItem(same(nestedNestedStepIds.get(0)), thirdLevelCaptor.capture()); + + StartTestItemRQ thirdLevelRq = thirdLevelCaptor.getValue(); + assertThat(thirdLevelRq.getName(), equalTo("A step inside nested step")); + assertThat(thirdLevelRq.isHasStats(), equalTo(Boolean.FALSE)); + } +} diff --git a/src/test/java/com/epam/reportportal/cucumber/NestedStepsStepReporterTest.java b/src/test/java/com/epam/reportportal/cucumber/NestedStepsStepReporterTest.java new file mode 100644 index 0000000..49a0e9f --- /dev/null +++ b/src/test/java/com/epam/reportportal/cucumber/NestedStepsStepReporterTest.java @@ -0,0 +1,147 @@ +package com.epam.reportportal.cucumber; + +import com.epam.reportportal.cucumber.integration.TestScenarioReporter; +import com.epam.reportportal.cucumber.integration.TestStepReporter; +import com.epam.reportportal.cucumber.integration.util.TestUtils; +import com.epam.reportportal.listeners.ListenerParameters; +import com.epam.reportportal.service.ReportPortal; +import com.epam.reportportal.service.ReportPortalClient; +import com.epam.reportportal.util.test.CommonUtils; +import com.epam.ta.reportportal.ws.model.StartTestItemRQ; +import com.epam.ta.reportportal.ws.model.attribute.ItemAttributesRQ; +import cucumber.api.CucumberOptions; +import cucumber.api.testng.AbstractTestNGCucumberTests; +import org.apache.commons.lang3.tuple.Pair; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; + +import java.util.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; +import static org.mockito.Mockito.*; + +public class NestedStepsStepReporterTest { + + @CucumberOptions(features = "src/test/resources/features/NestedStepsFeature.feature", glue = { + "com.epam.reportportal.cucumber.integration.feature" }, plugin = { "pretty", + "com.epam.reportportal.cucumber.integration.TestStepReporter" }) + public static class NestedStepsStepReporter extends AbstractTestNGCucumberTests { + + } + + private final String launchId = CommonUtils.namedId("launch_"); + private final String suiteId = CommonUtils.namedId("suite_"); + private final String testId = CommonUtils.namedId("test_"); + private final List stepIds = Stream.generate(() -> CommonUtils.namedId("step_")).limit(2).collect(Collectors.toList()); + private final List nestedStepIds = Stream.generate(() -> CommonUtils.namedId("nested_step_")) + .limit(3) + .collect(Collectors.toList()); + private final String nestedNestedStepId = CommonUtils.namedId("double_nested_step_"); + private final List> firstLevelNestedStepIds = Stream.concat(Stream.of(Pair.of(stepIds.get(0), + nestedStepIds.get(0) + )), nestedStepIds.stream().skip(1).map(i -> Pair.of(stepIds.get(1), i))) + .collect(Collectors.toList()); + + private final ListenerParameters params = TestUtils.standardParameters(); + private final ReportPortalClient client = mock(ReportPortalClient.class); + private final ExecutorService executorService = Executors.newSingleThreadExecutor(); + private final ReportPortal reportPortal = ReportPortal.create(client, params, executorService); + + @BeforeEach + public void setup() { + TestUtils.mockLaunch(client, launchId, suiteId, testId, stepIds); + TestUtils.mockNestedSteps(client, firstLevelNestedStepIds); + TestUtils.mockNestedSteps(client, Pair.of(nestedStepIds.get(0), nestedNestedStepId)); + TestScenarioReporter.RP.set(reportPortal); + TestStepReporter.RP.set(reportPortal); + } + + @AfterEach + public void tearDown() { + CommonUtils.shutdownExecutorService(executorService); + } + + public static final List FIRST_LEVEL_NAMES = Arrays.asList("A step inside step", + "A step with parameters", + "A step with attributes" + ); + + @Test + public void test_step_reporter_nested_steps() { + TestUtils.runTests(NestedStepsStepReporter.class); + + ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(1)).startTestItem(captor.capture()); + verify(client, times(1)).startTestItem(same(suiteId), captor.capture()); + verify(client, times(2)).startTestItem(same(testId), captor.capture()); + List parentItems = captor.getAllValues(); + parentItems.forEach(i -> assertThat(i.isHasStats(), anyOf(equalTo(Boolean.TRUE)))); + + ArgumentCaptor parentIdCapture = ArgumentCaptor.forClass(String.class); + ArgumentCaptor itemRequestCapture = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(1 + 2 + 3 + 1)).startTestItem(parentIdCapture.capture(), itemRequestCapture.capture()); + + List parentIdList = parentIdCapture.getAllValues(); + List itemRequestList = itemRequestCapture.getAllValues(); + + Map> firstLevelRequests = IntStream.range(0, parentIdList.size()) + .filter(i -> stepIds.contains(parentIdList.get(i))) + .mapToObj(i -> Pair.of(parentIdList.get(i), itemRequestList.get(i))) + .collect(Collectors.groupingBy(Pair::getKey, Collectors.mapping(Pair::getValue, Collectors.toList()))); + assertThat(firstLevelRequests.keySet(), hasSize(2)); + Iterator>> entryIterator = firstLevelRequests.entrySet().iterator(); + Map.Entry> firstPair = entryIterator.next(); + Map.Entry> secondPair = entryIterator.next(); + + if (firstPair.getValue().size() > secondPair.getValue().size()) { + Map.Entry> tmp = firstPair; + firstPair = secondPair; + secondPair = tmp; + } + + StartTestItemRQ firstLevelRq1 = firstPair.getValue().get(0); + assertThat(firstLevelRq1.getName(), equalTo(FIRST_LEVEL_NAMES.get(0))); + assertThat(firstLevelRq1.isHasStats(), equalTo(Boolean.FALSE)); + + List firstLevelRqs2 = secondPair.getValue(); + IntStream.range(1, FIRST_LEVEL_NAMES.size()).forEach(i -> { + assertThat(firstLevelRqs2.get(i - 1).getName(), equalTo(FIRST_LEVEL_NAMES.get(i))); + assertThat(firstLevelRqs2.get(i - 1).isHasStats(), equalTo(Boolean.FALSE)); + }); + + StartTestItemRQ stepWithAttributes = firstLevelRqs2.get(1); + Set attributes = stepWithAttributes.getAttributes(); + assertThat(attributes, allOf(notNullValue(), hasSize(2))); + List> kvAttributes = attributes.stream() + .map(a -> Pair.of(a.getKey(), a.getValue())) + .collect(Collectors.toList()); + List> keyAndValueList = kvAttributes.stream().filter(kv -> kv.getKey() != null).collect(Collectors.toList()); + assertThat(keyAndValueList, hasSize(1)); + assertThat(keyAndValueList.get(0).getKey(), equalTo("key")); + assertThat(keyAndValueList.get(0).getValue(), equalTo("value")); + + List> tagList = kvAttributes.stream().filter(kv -> kv.getKey() == null).collect(Collectors.toList()); + assertThat(tagList, hasSize(1)); + assertThat(tagList.get(0).getValue(), equalTo("tag")); + + Map> secondLevelSteps = IntStream.range(0, parentIdList.size()) + .filter(i -> nestedStepIds.contains(parentIdList.get(i))) + .mapToObj(i -> Pair.of(parentIdList.get(i), itemRequestList.get(i))) + .collect(Collectors.groupingBy(Pair::getKey, Collectors.mapping(Pair::getValue, Collectors.toList()))); + assertThat(secondLevelSteps.entrySet(), hasSize(1)); + List secondLevelRqs = secondLevelSteps.values().iterator().next(); + assertThat(secondLevelRqs, hasSize(1)); + + StartTestItemRQ secondLevelRq = secondLevelRqs.get(0); + assertThat(secondLevelRq.getName(), equalTo("A step inside nested step")); + assertThat(secondLevelRq.isHasStats(), equalTo(Boolean.FALSE)); + } +} diff --git a/src/test/java/com/epam/reportportal/cucumber/ParameterScenarioReporterTest.java b/src/test/java/com/epam/reportportal/cucumber/ParameterScenarioReporterTest.java new file mode 100644 index 0000000..97dcfbc --- /dev/null +++ b/src/test/java/com/epam/reportportal/cucumber/ParameterScenarioReporterTest.java @@ -0,0 +1,95 @@ +package com.epam.reportportal.cucumber; + +import com.epam.reportportal.cucumber.integration.TestScenarioReporter; +import com.epam.reportportal.cucumber.integration.TestStepReporter; +import com.epam.reportportal.cucumber.integration.util.TestUtils; +import com.epam.reportportal.listeners.ListenerParameters; +import com.epam.reportportal.service.ReportPortal; +import com.epam.reportportal.service.ReportPortalClient; +import com.epam.reportportal.util.test.CommonUtils; +import com.epam.ta.reportportal.ws.model.StartTestItemRQ; +import cucumber.api.CucumberOptions; +import cucumber.api.testng.AbstractTestNGCucumberTests; +import org.apache.commons.lang3.tuple.Pair; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; + +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.Mockito.*; + +/** + * @author Ihar Kahadouski + */ +public class ParameterScenarioReporterTest { + + @CucumberOptions(features = "src/test/resources/features/OneSimpleAndOneScenarioOutline.feature", glue = { + "com.epam.reportportal.cucumber.integration.feature" }, plugin = { "pretty", + "com.epam.reportportal.cucumber.integration.TestScenarioReporter" }) + public static class OneSimpleAndOneScenarioOutlineScenarioReporter extends AbstractTestNGCucumberTests { + + } + + private final String launchId = CommonUtils.namedId("launch_"); + private final String suiteId = CommonUtils.namedId("suite_"); + private final String testId = CommonUtils.namedId("test_"); + private final List stepIds = Stream.generate(() -> CommonUtils.namedId("step_")).limit(2).collect(Collectors.toList()); + + private final List nestedStepIds = Stream.generate(() -> CommonUtils.namedId("nested_step_")) + .limit(9) + .collect(Collectors.toList()); + + private final List> nestedStepMap = Stream.concat( + IntStream.range(0, 4).mapToObj(i -> Pair.of(stepIds.get(0), nestedStepIds.get(i))), + IntStream.range(4, 9).mapToObj(i -> Pair.of(stepIds.get(1), nestedStepIds.get(i))) + ).collect(Collectors.toList()); + + private final ReportPortalClient client = mock(ReportPortalClient.class); + private final ListenerParameters parameters = TestUtils.standardParameters(); + private final ExecutorService executorService = Executors.newSingleThreadExecutor(); + private final ReportPortal reportPortal = ReportPortal.create(client, parameters, executorService); + + @BeforeEach + public void initLaunch() { + TestUtils.mockLaunch(client, launchId, suiteId, testId, stepIds); + TestUtils.mockNestedSteps(client, nestedStepMap); + TestScenarioReporter.RP.set(reportPortal); + TestStepReporter.RP.set(reportPortal); + } + + public static final List> PARAMETERS = Arrays.asList(Pair.of("str", "\"first\""), Pair.of("parameters", 123)); + + public static final List STEP_NAMES = Arrays.asList( + String.format("When I have parameter %s", PARAMETERS.get(0).getValue()), + String.format("Then I emit number %s on level info", PARAMETERS.get(1).getValue().toString()) + ); + + @Test + public void verify_agent_creates_correct_step_names() { + TestUtils.runTests(OneSimpleAndOneScenarioOutlineScenarioReporter.class); + + verify(client, times(1)).startTestItem(any()); + verify(client, times(1)).startTestItem(same(suiteId), any()); + verify(client, times(2)).startTestItem(same(testId), any()); + ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(3)).startTestItem(same(stepIds.get(1)), captor.capture()); + + List items = captor.getAllValues() + .stream() + .filter(e -> e.getName().startsWith("When") || e.getName().startsWith("Then")) + .collect(Collectors.toList()); + IntStream.range(0, items.size()).forEach(i -> { + StartTestItemRQ step = items.get(i); + assertThat(step.getName(), equalTo(STEP_NAMES.get(i))); + }); + } +} diff --git a/src/test/java/com/epam/reportportal/cucumber/ParameterTest.java b/src/test/java/com/epam/reportportal/cucumber/ParameterStepReporterTest.java similarity index 77% rename from src/test/java/com/epam/reportportal/cucumber/ParameterTest.java rename to src/test/java/com/epam/reportportal/cucumber/ParameterStepReporterTest.java index 7d02fdb..43f15a9 100644 --- a/src/test/java/com/epam/reportportal/cucumber/ParameterTest.java +++ b/src/test/java/com/epam/reportportal/cucumber/ParameterStepReporterTest.java @@ -33,7 +33,7 @@ /** * @author Ihar Kahadouski */ -public class ParameterTest { +public class ParameterStepReporterTest { @CucumberOptions(features = "src/test/resources/features/BasicScenarioOutlineParameters.feature", glue = { "com.epam.reportportal.cucumber.integration.feature" }, plugin = { "pretty", @@ -56,8 +56,8 @@ public static class RunTwoOutlineParametersTestStepReporter extends AbstractTest .map(id -> Pair.of(id, Stream.generate(() -> CommonUtils.namedId("step_")).limit(3).collect(Collectors.toList()))) .collect(Collectors.toList()); - private final ListenerParameters parameters = TestUtils.standardParameters(); private final ReportPortalClient client = mock(ReportPortalClient.class); + private final ListenerParameters parameters = TestUtils.standardParameters(); private final ExecutorService executorService = Executors.newSingleThreadExecutor(); private final ReportPortal reportPortal = ReportPortal.create(client, parameters, executorService); @@ -69,9 +69,21 @@ public void initLaunch() { } public static final List> PARAMETERS = Arrays.asList( - Pair.of("str", "\"first\""), Pair.of("parameters", 123), - Pair.of("str", "\"second\""), Pair.of("parameters", 12345), - Pair.of("str", "\"third\""), Pair.of("parameters", 12345678) + Pair.of("str", "\"first\""), + Pair.of("parameters", 123), + Pair.of("str", "\"second\""), + Pair.of("parameters", 12345), + Pair.of("str", "\"third\""), + Pair.of("parameters", 12345678) + ); + + public static final List STEP_NAMES = Arrays.asList( + String.format("When I have parameter %s", PARAMETERS.get(0).getValue()), + String.format("Then I emit number %s on level info", PARAMETERS.get(1).getValue().toString()), + String.format("When I have parameter %s", PARAMETERS.get(2).getValue()), + String.format("Then I emit number %s on level info", PARAMETERS.get(3).getValue().toString()), + String.format("When I have parameter %s", PARAMETERS.get(4).getValue()), + String.format("Then I emit number %s on level info", PARAMETERS.get(5).getValue().toString()) ); @Test @@ -86,12 +98,15 @@ public void verify_agent_retrieves_parameters_from_request() { verify(client, times(3)).startTestItem(same(testIds.get(2)), captor.capture()); List items = captor.getAllValues(); - List filteredItems = IntStream.range(0, items.size()) - .filter(i -> i % 3 != 0) - .mapToObj(items::get) + List filteredItems = items.stream() + .filter(i -> "STEP".equals(i.getType()) && !i.getName().startsWith("Given")) .collect(Collectors.toList()); IntStream.range(0, filteredItems.size()).mapToObj(i -> Pair.of(i, filteredItems.get(i))).forEach(e -> { - assertThat(e.getValue().getParameters(), allOf(notNullValue(), hasSize(1))); + StartTestItemRQ step = e.getValue(); + assertThat(step, notNullValue()); + String expectedName = STEP_NAMES.get(e.getKey()); + assertThat(step.getName(), equalTo(expectedName)); + assertThat(step.getParameters(), allOf(notNullValue(), hasSize(1))); ParameterResource param = e.getValue().getParameters().get(0); Pair expectedParam = PARAMETERS.get(e.getKey()); @@ -112,13 +127,11 @@ public void verify_agent_retrieves_two_parameters_from_request() { verify(client, times(3)).startTestItem(same(testIds.get(2)), captor.capture()); List items = captor.getAllValues(); - List twoParameterItems = IntStream.range(0, items.size()) - .filter(i -> i % 3 == 0) - .mapToObj(items::get) + List twoParameterItems = items.stream() + .filter(i -> "STEP".equals(i.getType()) && i.getName().startsWith("Given")) .collect(Collectors.toList()); - List oneParameterItems = IntStream.range(0, items.size()) - .filter(i -> i % 3 == 2) - .mapToObj(items::get) + List oneParameterItems = items.stream() + .filter(i -> "STEP".equals(i.getType()) && i.getName().startsWith("Then")) .collect(Collectors.toList()); twoParameterItems.forEach(i -> assertThat(i.getParameters(), allOf(notNullValue(), hasSize(2)))); oneParameterItems.forEach(i -> assertThat(i.getParameters(), allOf(notNullValue(), hasSize(1)))); diff --git a/src/test/java/com/epam/reportportal/cucumber/SimpleVerificationTest.java b/src/test/java/com/epam/reportportal/cucumber/SimpleVerificationTest.java new file mode 100644 index 0000000..f4fadcd --- /dev/null +++ b/src/test/java/com/epam/reportportal/cucumber/SimpleVerificationTest.java @@ -0,0 +1,112 @@ +package com.epam.reportportal.cucumber; + +import com.epam.reportportal.cucumber.integration.TestScenarioReporter; +import com.epam.reportportal.cucumber.integration.TestStepReporter; +import com.epam.reportportal.cucumber.integration.util.TestUtils; +import com.epam.reportportal.listeners.ListenerParameters; +import com.epam.reportportal.service.ReportPortal; +import com.epam.reportportal.service.ReportPortalClient; +import com.epam.reportportal.util.test.CommonUtils; +import com.epam.ta.reportportal.ws.model.StartTestItemRQ; +import cucumber.api.CucumberOptions; +import cucumber.api.testng.AbstractTestNGCucumberTests; +import org.apache.commons.lang3.tuple.Pair; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; + +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; +import static org.mockito.ArgumentMatchers.same; +import static org.mockito.Mockito.*; + +public class SimpleVerificationTest { + @CucumberOptions(features = "src/test/resources/features/belly.feature", glue = { + "com.epam.reportportal.cucumber.integration.feature" }, plugin = { "pretty", + "com.epam.reportportal.cucumber.integration.TestStepReporter" }) + public static class SimpleTestStepReporter extends AbstractTestNGCucumberTests { + + } + + @CucumberOptions(features = "src/test/resources/features/belly.feature", glue = { + "com.epam.reportportal.cucumber.integration.feature" }, plugin = { "pretty", + "com.epam.reportportal.cucumber.integration.TestScenarioReporter" }) + public static class SimpleTestScenarioReporter extends AbstractTestNGCucumberTests { + + } + + private final String launchId = CommonUtils.namedId("launch_"); + private final String suiteId = CommonUtils.namedId("suite_"); + private final String testId = CommonUtils.namedId("test_"); + private final List stepIds = Stream.generate(() -> CommonUtils.namedId("step_")).limit(3).collect(Collectors.toList()); + private final List nestedStepIds = Stream.generate(() -> CommonUtils.namedId("step_")).limit(3).collect(Collectors.toList()); + private final List> nestedSteps = nestedStepIds.stream() + .map(s -> Pair.of(stepIds.get(0), s)) + .collect(Collectors.toList()); + + private final ListenerParameters params = TestUtils.standardParameters(); + private final ReportPortalClient client = mock(ReportPortalClient.class); + private final ExecutorService executorService = Executors.newSingleThreadExecutor(); + private final ReportPortal reportPortal = ReportPortal.create(client, params, executorService); + + @BeforeEach + public void setup() { + TestUtils.mockLaunch(client, launchId, suiteId, testId, stepIds); + TestScenarioReporter.RP.set(reportPortal); + TestStepReporter.RP.set(reportPortal); + } + + public static void verifyRequest(StartTestItemRQ rq, String type, boolean hasStats) { + assertThat(rq.getType(), allOf(notNullValue(), equalTo(type))); + assertThat(rq.getStartTime(), notNullValue()); + assertThat(rq.getName(), notNullValue()); + assertThat(rq.isHasStats(), equalTo(hasStats)); + } + + @Test + public void verify_step_reporter_steps_integrity() { + TestUtils.runTests(SimpleTestStepReporter.class); + + ArgumentCaptor suiteCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(1)).startTestItem(suiteCaptor.capture()); + verifyRequest(suiteCaptor.getValue(), "STORY", true); + + ArgumentCaptor testCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(1)).startTestItem(same(suiteId), testCaptor.capture()); + verifyRequest(testCaptor.getValue(), "SCENARIO", true); + + ArgumentCaptor stepCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(3)).startTestItem(same(testId), stepCaptor.capture()); + + stepCaptor.getAllValues().forEach(rq -> verifyRequest(rq, "STEP", true)); + } + + @Test + public void verify_scenario_reporter_steps_integrity() { + TestUtils.mockNestedSteps(client, nestedSteps); + TestUtils.runTests(SimpleTestScenarioReporter.class); + + ArgumentCaptor mainSuiteCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(1)).startTestItem(mainSuiteCaptor.capture()); + verifyRequest(mainSuiteCaptor.getValue(), "SUITE", true); + + ArgumentCaptor suiteCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(1)).startTestItem(same(suiteId), suiteCaptor.capture()); + verifyRequest(suiteCaptor.getValue(), "STORY", true); + + ArgumentCaptor testCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(1)).startTestItem(same(testId), testCaptor.capture()); + verifyRequest(testCaptor.getValue(), "STEP", true); + + ArgumentCaptor stepCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(3)).startTestItem(same(stepIds.get(0)), stepCaptor.capture()); + + stepCaptor.getAllValues().forEach(rq -> verifyRequest(rq, "STEP", false)); + } +} diff --git a/src/test/java/com/epam/reportportal/cucumber/TestCaseIdTest.java b/src/test/java/com/epam/reportportal/cucumber/TestCaseIdTest.java index 3c7dd3c..125f349 100644 --- a/src/test/java/com/epam/reportportal/cucumber/TestCaseIdTest.java +++ b/src/test/java/com/epam/reportportal/cucumber/TestCaseIdTest.java @@ -2,6 +2,7 @@ import com.epam.reportportal.cucumber.integration.TestScenarioReporter; import com.epam.reportportal.cucumber.integration.TestStepReporter; +import com.epam.reportportal.cucumber.integration.feature.TestCaseIdOnMethodSteps; import com.epam.reportportal.cucumber.integration.util.TestUtils; import com.epam.reportportal.listeners.ListenerParameters; import com.epam.reportportal.service.ReportPortal; @@ -25,9 +26,6 @@ import static org.hamcrest.Matchers.equalTo; import static org.mockito.Mockito.*; -/** - * TODO: finish the test - */ public class TestCaseIdTest { @CucumberOptions(features = "src/test/resources/features/belly.feature", glue = { @@ -44,6 +42,13 @@ public static class RunBellyTestStepReporter extends AbstractTestNGCucumberTests } + @CucumberOptions(features = "src/test/resources/features/TestCaseIdOnAMethod.feature", glue = { + "com.epam.reportportal.cucumber.integration.feature" }, plugin = { "pretty", + "com.epam.reportportal.cucumber.integration.TestStepReporter" }) + public static class StepDefStepReporter extends AbstractTestNGCucumberTests { + + } + private final String launchId = CommonUtils.namedId("launch_"); private final String suiteId = CommonUtils.namedId("suite_"); private final String testId = CommonUtils.namedId("test_"); @@ -100,5 +105,15 @@ public void shouldSendCaseIdWhenParametrizedStepReporter() { equalTo("com.epam.reportportal.cucumber.integration.feature.BellyStepdefs.my_belly_should_growl[]") ); } + + @Test + public void verify_test_case_id_bypassed_through_annotation_on_a_stepdef() { + TestUtils.runTests(StepDefStepReporter.class); + ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(1)).startTestItem(same(testId), captor.capture()); + + StartTestItemRQ step = captor.getValue(); + assertThat(step.getTestCaseId(), equalTo(TestCaseIdOnMethodSteps.TEST_CASE_ID)); + } } diff --git a/src/test/java/com/epam/reportportal/cucumber/integration/feature/AmbiguousSteps.java b/src/test/java/com/epam/reportportal/cucumber/integration/feature/AmbiguousSteps.java new file mode 100644 index 0000000..4838730 --- /dev/null +++ b/src/test/java/com/epam/reportportal/cucumber/integration/feature/AmbiguousSteps.java @@ -0,0 +1,19 @@ +package com.epam.reportportal.cucumber.integration.feature; + +import cucumber.api.java.en.Given; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AmbiguousSteps { + private static final Logger LOGGER = LoggerFactory.getLogger(AmbiguousSteps.class); + + @Given("I have an ambiguous step (\\w+)") + public void i_have_an_ambiguous_step(String param) { + LOGGER.info("Inside 'I have an ambiguous step', parameter: " + param); + } + + @Given("I have an ambiguous step two") + public void i_have_an_ambiguous_step_two() { + LOGGER.info("Inside 'I have an ambiguous step two'"); + } +} diff --git a/src/test/java/com/epam/reportportal/cucumber/integration/feature/EmptySteps.java b/src/test/java/com/epam/reportportal/cucumber/integration/feature/EmptySteps.java index 65b8c32..93117b7 100644 --- a/src/test/java/com/epam/reportportal/cucumber/integration/feature/EmptySteps.java +++ b/src/test/java/com/epam/reportportal/cucumber/integration/feature/EmptySteps.java @@ -2,6 +2,7 @@ import cucumber.api.java.en.Given; import cucumber.api.java.en.Then; +import cucumber.api.java.en.When; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -17,4 +18,9 @@ public void i_have_empty_step() { public void i_have_another_empty_step() { LOGGER.info("Inside 'I have another empty step'"); } + + @When("I have one more empty step") + public void i_have_one_more_empty_step() { + LOGGER.info("I have one more empty step'"); + } } diff --git a/src/test/java/com/epam/reportportal/cucumber/integration/feature/ManualStepReporterSteps.java b/src/test/java/com/epam/reportportal/cucumber/integration/feature/ManualStepReporterSteps.java new file mode 100644 index 0000000..38683aa --- /dev/null +++ b/src/test/java/com/epam/reportportal/cucumber/integration/feature/ManualStepReporterSteps.java @@ -0,0 +1,46 @@ +package com.epam.reportportal.cucumber.integration.feature; + +import com.epam.reportportal.listeners.ItemStatus; +import com.epam.reportportal.service.Launch; +import com.epam.reportportal.service.step.StepReporter; +import com.epam.reportportal.util.test.CommonUtils; +import cucumber.api.java.en.Given; +import cucumber.api.java.en.Then; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; + +public class ManualStepReporterSteps { + private static final Logger LOGGER = LoggerFactory.getLogger(ManualStepReporterSteps.class); + public static final String FIRST_NAME = "I am the first nested step"; + public static final String SECOND_NAME = "I am the second nested step"; + public static final String THIRD_NAME = "I am the third nested step"; + public static final String FIRST_NESTED_STEP_LOG = "Inside first nested step"; + public static final String SECOND_NESTED_STEP_LOG = "Inside second nested step"; + public static final String THIRD_NESTED_STEP_LOG = "Third error log of the second step"; + public static final String DURING_SECOND_NESTED_STEP_LOG = "A log entry during the first nested step report"; + + @Given("A step with a manual step") + public void i_have_a_step_with_a_manual_step() throws InterruptedException { + StepReporter stepReporter = Launch.currentLaunch().getStepReporter(); + + stepReporter.sendStep(FIRST_NAME); + Thread.sleep(CommonUtils.MINIMAL_TEST_PAUSE); + LOGGER.info(FIRST_NESTED_STEP_LOG); + } + + @Then("A step with two manual steps") + public void i_have_a_step_with_two_manual_steps() throws InterruptedException { + StepReporter stepReporter = Launch.currentLaunch().getStepReporter(); + + stepReporter.sendStep(SECOND_NAME, DURING_SECOND_NESTED_STEP_LOG); + Thread.sleep(CommonUtils.MINIMAL_TEST_PAUSE); + LOGGER.info(SECOND_NESTED_STEP_LOG); + + stepReporter.sendStep(ItemStatus.FAILED, THIRD_NAME, new File("pug/unlucky.jpg")); + Thread.sleep(CommonUtils.MINIMAL_TEST_PAUSE); + LOGGER.error(THIRD_NESTED_STEP_LOG); + } + +} diff --git a/src/test/java/com/epam/reportportal/cucumber/integration/feature/NestedSteps.java b/src/test/java/com/epam/reportportal/cucumber/integration/feature/NestedSteps.java new file mode 100644 index 0000000..f15ec55 --- /dev/null +++ b/src/test/java/com/epam/reportportal/cucumber/integration/feature/NestedSteps.java @@ -0,0 +1,60 @@ +package com.epam.reportportal.cucumber.integration.feature; + +import com.epam.reportportal.annotations.Step; +import com.epam.reportportal.annotations.attribute.Attribute; +import com.epam.reportportal.annotations.attribute.AttributeValue; +import com.epam.reportportal.annotations.attribute.Attributes; +import com.epam.reportportal.util.test.CommonUtils; +import cucumber.api.java.en.Given; +import cucumber.api.java.en.When; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NestedSteps { + private static final Logger LOGGER = LoggerFactory.getLogger(NestedSteps.class); + + public static final long PARAM1 = 7L; + + public static final String PARAM2 = "second param"; + + @Given("I have a step") + public void i_have_empty_step() throws InterruptedException { + LOGGER.info("Inside 'I have a step'"); + Thread.sleep(CommonUtils.MINIMAL_TEST_PAUSE); + and_a_step_inside_step(); + } + + @Step("A step inside step") + public void and_a_step_inside_step() throws InterruptedException { + LOGGER.info("Inside 'and_a_step_inside_nested_step'"); + Thread.sleep(CommonUtils.MINIMAL_TEST_PAUSE); + and_a_step_inside_nested_step(); + } + + @Step("A step inside nested step") + public void and_a_step_inside_nested_step() { + LOGGER.info("Inside 'and_a_step_inside_nested_step'"); + } + + @When("I have one more step") + public void i_have_one_more_step() throws InterruptedException { + LOGGER.info("Inside 'I have one more step'"); + Thread.sleep(CommonUtils.MINIMAL_TEST_PAUSE); + with_a_step_with_parameters(PARAM1, PARAM2); + Thread.sleep(CommonUtils.MINIMAL_TEST_PAUSE); + with_a_step_with_attributes(); + } + + @Step("A step with parameters") + public void with_a_step_with_parameters(long one, String two) throws InterruptedException { + LOGGER.info("Inside 'with_a_step_with_parameters': '" + one + "'; '" + two + "'"); + Thread.sleep(CommonUtils.MINIMAL_TEST_PAUSE); + } + + @Step("A step with attributes") + @Attributes(attributes = @Attribute(key = "key", value = "value"), attributeValues = @AttributeValue("tag")) + public void with_a_step_with_attributes() throws InterruptedException { + LOGGER.info("Inside 'with_a_step_with_attributes'"); + Thread.sleep(CommonUtils.MINIMAL_TEST_PAUSE); + } +} diff --git a/src/test/java/com/epam/reportportal/cucumber/integration/feature/ReportsTestWithParameters.java b/src/test/java/com/epam/reportportal/cucumber/integration/feature/ReportsTestWithParameters.java index 2b92174..17d4131 100644 --- a/src/test/java/com/epam/reportportal/cucumber/integration/feature/ReportsTestWithParameters.java +++ b/src/test/java/com/epam/reportportal/cucumber/integration/feature/ReportsTestWithParameters.java @@ -20,6 +20,11 @@ public void iHaveParameterStr(String str) { LOGGER.info("String parameter {}", str); } + @When("I have a docstring parameter:") + public void iHaveParameterDocstring(String str) { + iHaveParameterStr(str); + } + @Then("I emit number {int} on level info") public void infoLevel(int parameters) { LOGGER.info("Test with parameters: " + parameters); diff --git a/src/test/java/com/epam/reportportal/cucumber/integration/feature/TestCaseIdOnMethodSteps.java b/src/test/java/com/epam/reportportal/cucumber/integration/feature/TestCaseIdOnMethodSteps.java new file mode 100644 index 0000000..b93405b --- /dev/null +++ b/src/test/java/com/epam/reportportal/cucumber/integration/feature/TestCaseIdOnMethodSteps.java @@ -0,0 +1,18 @@ +package com.epam.reportportal.cucumber.integration.feature; + +import com.epam.reportportal.annotations.TestCaseId; +import cucumber.api.java.en.Given; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TestCaseIdOnMethodSteps { + private static final Logger LOGGER = LoggerFactory.getLogger(TestCaseIdOnMethodSteps.class); + public static final String TEST_CASE_ID = "My test case id"; + + + @Given("I have a test case ID on a step definition method") + @TestCaseId(TEST_CASE_ID) + public void i_have_a_test_case_id_on_a_stepdef_method() { + LOGGER.info("Inside 'i_have_a_test_case_id_on_a_stepdef_method' method"); + } +} diff --git a/src/test/java/com/epam/reportportal/cucumber/integration/hooks/EmptySteps.java b/src/test/java/com/epam/reportportal/cucumber/integration/hooks/EmptySteps.java new file mode 100644 index 0000000..bb11c32 --- /dev/null +++ b/src/test/java/com/epam/reportportal/cucumber/integration/hooks/EmptySteps.java @@ -0,0 +1,44 @@ +package com.epam.reportportal.cucumber.integration.hooks; + +import cucumber.api.java.After; +import cucumber.api.java.AfterStep; +import cucumber.api.java.Before; +import cucumber.api.java.BeforeStep; +import cucumber.api.java.en.Given; +import cucumber.api.java.en.Then; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class EmptySteps { + private static final Logger LOGGER = LoggerFactory.getLogger(EmptySteps.class); + + @Before + public void my_before_hook() { + LOGGER.info("Inside 'my_before_hook'"); + } + + @BeforeStep + public void my_before_step_hook() { + LOGGER.info("Inside 'my_before_step_hook'"); + } + + @AfterStep + public void my_after_step_hook() { + LOGGER.info("Inside 'my_after_step_hook'"); + } + + @Given("I have empty step") + public void i_have_empty_step() { + LOGGER.info("Inside 'I have empty step'"); + } + + @Then("I have another empty step") + public void i_have_another_empty_step() { + LOGGER.info("Inside 'I have another empty step'"); + } + + @After + public void my_after_hook() { + LOGGER.info("Inside 'my_after_hook'"); + } +} diff --git a/src/test/java/com/epam/reportportal/cucumber/integration/service/Belly.java b/src/test/java/com/epam/reportportal/cucumber/integration/service/Belly.java index 36bbb8f..79733a2 100644 --- a/src/test/java/com/epam/reportportal/cucumber/integration/service/Belly.java +++ b/src/test/java/com/epam/reportportal/cucumber/integration/service/Belly.java @@ -1,24 +1,24 @@ package com.epam.reportportal.cucumber.integration.service; public class Belly { - + private int satiation = 0; - - public void eat(int cukes) { - satiation += cukes; - } - - public void wait(int hours) { - if ((hours > 0) && (satiation > 0)) { - int utilized = 60 * hours; - if (utilized > satiation) { - utilized = satiation; - } - satiation -= utilized; - } - } - - public boolean growl() { - return satiation <= 0; - } + + public void eat(int cukes) { + satiation += cukes; + } + + public void wait(int hours) { + if ((hours > 0) && (satiation > 0)) { + int utilized = 60 * hours; + if (utilized > satiation) { + utilized = satiation; + } + satiation -= utilized; + } + } + + public boolean growl() { + return satiation <= 0; + } } diff --git a/src/test/java/com/epam/reportportal/cucumber/integration/util/TestUtils.java b/src/test/java/com/epam/reportportal/cucumber/integration/util/TestUtils.java index 9851a20..e9f1d39 100644 --- a/src/test/java/com/epam/reportportal/cucumber/integration/util/TestUtils.java +++ b/src/test/java/com/epam/reportportal/cucumber/integration/util/TestUtils.java @@ -80,8 +80,10 @@ public static void mockLaunch(ReportPortalClient client, String launchUuid, Stri Maybe suiteMaybe = createMaybe(new ItemCreatedRS(suiteUuid, suiteUuid)); when(client.startTestItem(any())).thenReturn(suiteMaybe); - List> testResponses = testSteps.stream().map(Pair::getKey) - .map(uuid -> createMaybe(new ItemCreatedRS(uuid, uuid))).collect(Collectors.toList()); + List> testResponses = testSteps.stream() + .map(Pair::getKey) + .map(uuid -> createMaybe(new ItemCreatedRS(uuid, uuid))) + .collect(Collectors.toList()); Maybe first = testResponses.get(0); Maybe[] other = testResponses.subList(1, testResponses.size()).toArray(new Maybe[0]); @@ -89,8 +91,10 @@ public static void mockLaunch(ReportPortalClient client, String launchUuid, Stri testSteps.forEach(test -> { String testClassUuid = test.getKey(); - List> stepResponses = - test.getValue().stream().map(uuid -> createMaybe(new ItemCreatedRS(uuid, uuid))).collect(Collectors.toList()); + List> stepResponses = test.getValue() + .stream() + .map(uuid -> createMaybe(new ItemCreatedRS(uuid, uuid))) + .collect(Collectors.toList()); Maybe myFirst = stepResponses.get(0); Maybe[] myOther = stepResponses.subList(1, stepResponses.size()).toArray(new Maybe[0]); diff --git a/src/test/resources/features/AmbiguousTest.feature b/src/test/resources/features/AmbiguousTest.feature new file mode 100644 index 0000000..7075ba0 --- /dev/null +++ b/src/test/resources/features/AmbiguousTest.feature @@ -0,0 +1,4 @@ +Feature: Ambiguous test feature + + Scenario: Test ambiguous step + Given I have an ambiguous step two diff --git a/src/test/resources/features/BackgroundScenario.feature b/src/test/resources/features/BackgroundScenario.feature new file mode 100644 index 0000000..c67e488 --- /dev/null +++ b/src/test/resources/features/BackgroundScenario.feature @@ -0,0 +1,10 @@ +Feature: Test scenario with a background + + Background: Init our scenario + Given I have empty step + + Scenario: The first scenario + Then I have another empty step + + Scenario: The second scenario + Then I have one more empty step diff --git a/src/test/resources/features/BasicDocStringParameters.feature b/src/test/resources/features/BasicDocStringParameters.feature new file mode 100644 index 0000000..6a55e09 --- /dev/null +++ b/src/test/resources/features/BasicDocStringParameters.feature @@ -0,0 +1,9 @@ +Feature: Basic test with a docstring parameter + + Scenario: Test with a docstring parameter + Given It is test with parameters + When I have a docstring parameter: + """ + My very long parameter + With some new lines + """ diff --git a/src/test/resources/features/DummyScenario.feature b/src/test/resources/features/DummyScenario.feature new file mode 100644 index 0000000..b102125 --- /dev/null +++ b/src/test/resources/features/DummyScenario.feature @@ -0,0 +1,5 @@ +Feature: Test dummy scenario + + Scenario: The scenario + Given I have empty step + Then I have another empty step diff --git a/src/test/resources/features/ManualStepReporter.feature b/src/test/resources/features/ManualStepReporter.feature new file mode 100644 index 0000000..bc6ca1d --- /dev/null +++ b/src/test/resources/features/ManualStepReporter.feature @@ -0,0 +1,5 @@ +Feature: Manual StepReporter + + Scenario: Test manual StepReporter + Given A step with a manual step + Then A step with two manual steps diff --git a/src/test/resources/features/NestedStepsFeature.feature b/src/test/resources/features/NestedStepsFeature.feature new file mode 100644 index 0000000..7d8f303 --- /dev/null +++ b/src/test/resources/features/NestedStepsFeature.feature @@ -0,0 +1,4 @@ +Feature: Test scenario with nested steps + Scenario: Nested steps scenario + Given I have a step + When I have one more step diff --git a/src/test/resources/features/OneSimpleAndOneScenarioOutline.feature b/src/test/resources/features/OneSimpleAndOneScenarioOutline.feature new file mode 100644 index 0000000..dff2deb --- /dev/null +++ b/src/test/resources/features/OneSimpleAndOneScenarioOutline.feature @@ -0,0 +1,14 @@ +Feature: Basic test with parameters + + Scenario: The scenario + Given I have empty step + Then I have another empty step + + Scenario Outline: Test with different parameters + Given It is test with parameters + When I have parameter + Then I emit number on level info + + Examples: + | str | parameters | + | "first" | 123 | \ No newline at end of file diff --git a/src/test/resources/features/TestCaseIdOnAMethod.feature b/src/test/resources/features/TestCaseIdOnAMethod.feature new file mode 100644 index 0000000..9088a51 --- /dev/null +++ b/src/test/resources/features/TestCaseIdOnAMethod.feature @@ -0,0 +1,4 @@ +Feature: Test Case ID on a method feature + + Scenario: Test Case ID + Given I have a test case ID on a step definition method diff --git a/src/test/resources/pug/unlucky.jpg b/src/test/resources/pug/unlucky.jpg new file mode 100644 index 0000000..91e8af0 Binary files /dev/null and b/src/test/resources/pug/unlucky.jpg differ