diff --git a/build.gradle b/build.gradle index 929d455..f0b263f 100644 --- a/build.gradle +++ b/build.gradle @@ -37,11 +37,12 @@ compileJava.options.encoding = 'UTF-8' compileTestJava.options.encoding = 'UTF-8' repositories { + mavenLocal() mavenCentral() } dependencies { - api 'com.epam.reportportal:client-java:5.1.25' + api 'com.epam.reportportal:client-java:5.1.26' api "com.intuit.karate:karate-core:${project.karate_version}" implementation 'org.slf4j:slf4j-api:2.0.7' diff --git a/src/main/java/com/epam/reportportal/karate/ReportPortalPublisher.java b/src/main/java/com/epam/reportportal/karate/ReportPortalPublisher.java index 8fa568b..aec3ba7 100644 --- a/src/main/java/com/epam/reportportal/karate/ReportPortalPublisher.java +++ b/src/main/java/com/epam/reportportal/karate/ReportPortalPublisher.java @@ -20,6 +20,7 @@ import com.epam.reportportal.karate.enums.ItemStatusEnum; import com.epam.reportportal.listeners.ItemType; import com.epam.reportportal.listeners.ListenerParameters; +import com.epam.reportportal.listeners.LogLevel; import com.epam.reportportal.service.Launch; import com.epam.reportportal.service.ReportPortal; import com.epam.reportportal.service.item.TestCaseIdEntry; @@ -44,6 +45,7 @@ import javax.annotation.Nullable; import java.util.*; import java.util.function.Supplier; +import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -55,6 +57,8 @@ public class ReportPortalPublisher { public static final String SCENARIO_CODE_REFERENCE_PATTERN = "%s/[SCENARIO:%s]"; public static final String EXAMPLE_CODE_REFERENCE_PATTERN = "%s/[EXAMPLE:%s%s]"; + public static final String VARIABLE_PATTERN = + "(?:(?<=#\\()%1$s(?=\\)))|(?:(?<=[\\s=+-/*<>(]|^)%1$s(?=[\\s=+-/*<>)]|(?:\\r?\\n)|$))"; private static final Logger LOGGER = LoggerFactory.getLogger(ReportPortalPublisher.class); private final Map> featureIdMap = new HashMap<>(); @@ -151,12 +155,12 @@ public void finishLaunch() { */ @Nonnull protected String getCodeRef(@Nonnull Scenario scenario) { - if (scenario.getExampleIndex() < 0) { - return String.format(SCENARIO_CODE_REFERENCE_PATTERN, scenario.getFeature().getResource().getRelativePath(), - scenario.getName()); - } else { + if (scenario.isOutlineExample()) { return String.format(EXAMPLE_CODE_REFERENCE_PATTERN, scenario.getFeature().getResource().getRelativePath(), scenario.getName(), ReportPortalUtils.formatExampleKey(scenario.getExampleData())); + } else { + return String.format(SCENARIO_CODE_REFERENCE_PATTERN, scenario.getFeature().getResource().getRelativePath(), + scenario.getName()); } } @@ -192,13 +196,30 @@ protected StartTestItemRQ buildStartTestItemRq(@Nonnull String name, @Nonnull Da /** * Customize start step test item event/request * - * @param step Karate's Step class instance + * @param step Karate's Step class instance + * @param scenario Karate's Scenario class instance * @return request to ReportPortal */ - protected StartTestItemRQ buildStartStepRq(@Nonnull Step step) { + protected StartTestItemRQ buildStartStepRq(@Nonnull Step step, Scenario scenario) { String stepName = step.getPrefix() + " " + step.getText(); StartTestItemRQ rq = buildStartTestItemRq(stepName, getStepStartTime(stepStartTimeMap, stepId), ItemType.STEP); rq.setHasStats(false); + if (step.isOutline()) { + List parameters = scenario + .getExampleData() + .entrySet() + .stream() + .filter(e -> Pattern.compile(String.format(VARIABLE_PATTERN, e.getKey())).matcher(step.getText()).find()) + .map(e -> { + ParameterResource param = new ParameterResource(); + param.setKey(e.getKey()); + var value = ofNullable(e.getValue()).map(Object::toString).orElse(ParameterUtils.NULL_VALUE); + param.setValue(value); + return param; + }) + .collect(Collectors.toList()); + rq.setParameters(parameters); + } return rq; } @@ -353,9 +374,19 @@ public void finishScenario(ScenarioResult scenarioResult) { * @param scenarioResult scenario result */ public void startStep(StepResult stepResult, ScenarioResult scenarioResult) { - StartTestItemRQ rq = buildStartStepRq(stepResult.getStep()); - stepId = launch.get().startTestItem(scenarioIdMap.get(scenarioResult.getScenario().getName()), rq); - stepStartTimeMap.put(stepId, rq.getStartTime().getTime()); + StartTestItemRQ stepRq = buildStartStepRq(stepResult.getStep(), scenarioResult.getScenario()); + stepId = launch.get().startTestItem(scenarioIdMap.get(scenarioResult.getScenario().getName()), stepRq); + stepStartTimeMap.put(stepId, stepRq.getStartTime().getTime()); + ofNullable(stepRq.getParameters()) + .filter(params -> !params.isEmpty()) + .ifPresent(params -> ReportPortal.emitLog(stepId, id -> { + SaveLogRQ logRq = new SaveLogRQ(); + logRq.setLogTime(Calendar.getInstance().getTime()); + logRq.setItemUuid(id); + logRq.setLevel(LogLevel.INFO.name()); + logRq.setMessage("Parameters:\n\n" + ParameterUtils.formatParametersAsTable(params)); + return logRq; + })); } /** diff --git a/src/test/java/com/epam/reportportal/karate/parameters/ExamplesStepParametersTest.java b/src/test/java/com/epam/reportportal/karate/parameters/ExamplesStepParametersTest.java new file mode 100644 index 0000000..1378c89 --- /dev/null +++ b/src/test/java/com/epam/reportportal/karate/parameters/ExamplesStepParametersTest.java @@ -0,0 +1,81 @@ +package com.epam.reportportal.karate.parameters; + +import com.epam.reportportal.karate.utils.TestUtils; +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.ParameterResource; +import com.epam.ta.reportportal.ws.model.StartTestItemRQ; +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.Collection; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static com.epam.reportportal.karate.utils.TestUtils.*; +import static java.util.stream.Stream.ofNullable; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; +import static org.mockito.ArgumentMatchers.same; +import static org.mockito.Mockito.*; + +public class ExamplesStepParametersTest { + private final String featureId = CommonUtils.namedId("feature_"); + private final List exampleIds = Stream.generate(() -> CommonUtils.namedId("example_")).limit(2) + .collect(Collectors.toList()); + private final List>> stepIds = exampleIds.stream() + .map(e -> Pair.of(e, Stream.generate(() -> CommonUtils.namedId("step_")) + .limit(2).collect(Collectors.toList()))) + .collect(Collectors.toList()); + + private final ReportPortalClient client = mock(ReportPortalClient.class); + private final ReportPortal rp = ReportPortal.create(client, standardParameters(), testExecutor()); + + @BeforeEach + public void setupMock() { + mockLaunch(client, null, featureId, stepIds); + mockBatchLogging(client); + } + + private static Set toParameterStringList(List parameters) { + return ofNullable(parameters) + .flatMap(Collection::stream) + .map(p -> p.getKey() + ":" + p.getValue()) + .collect(Collectors.toSet()); + } + + @Test + public void test_examples_parameters_for_steps() { + var results = TestUtils.runAsReport(rp, "classpath:feature/examples.feature"); + assertThat(results.getFailCount(), equalTo(0)); + + ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(1)).startTestItem(captor.capture()); + verify(client, times(2)).startTestItem(same(featureId), captor.capture()); + ArgumentCaptor firstExampleCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(2)).startTestItem(same(exampleIds.get(0)), firstExampleCaptor.capture()); + ArgumentCaptor secondExampleCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(2)).startTestItem(same(exampleIds.get(1)), secondExampleCaptor.capture()); + + List firstSteps = firstExampleCaptor.getAllValues(); + Set parameterStrings = toParameterStringList(firstSteps.get(0).getParameters()); + assertThat(parameterStrings, hasSize(2)); + assertThat(parameterStrings, allOf(hasItem("vara:2"), hasItem("varb:2"))); + parameterStrings = toParameterStringList(firstSteps.get(1).getParameters()); + assertThat(parameterStrings, hasSize(1)); + assertThat(parameterStrings, hasItem("result:4")); + + List secondSteps = secondExampleCaptor.getAllValues(); + parameterStrings = toParameterStringList(secondSteps.get(0).getParameters()); + assertThat(parameterStrings, hasSize(2)); + assertThat(parameterStrings, allOf(hasItem("vara:1"), hasItem("varb:2"))); + parameterStrings = toParameterStringList(secondSteps.get(1).getParameters()); + assertThat(parameterStrings, hasSize(1)); + assertThat(parameterStrings, hasItem("result:3")); + } +} diff --git a/src/test/java/com/epam/reportportal/karate/parameters/NoParametersTest.java b/src/test/java/com/epam/reportportal/karate/parameters/NoParametersTest.java new file mode 100644 index 0000000..fa931ad --- /dev/null +++ b/src/test/java/com/epam/reportportal/karate/parameters/NoParametersTest.java @@ -0,0 +1,58 @@ +package com.epam.reportportal.karate.parameters; + +import com.epam.reportportal.karate.utils.TestUtils; +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 org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static com.epam.reportportal.karate.utils.TestUtils.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; +import static org.mockito.ArgumentMatchers.same; +import static org.mockito.Mockito.*; + +public class NoParametersTest { + private final String featureId = CommonUtils.namedId("feature_"); + private final String scenarioId = CommonUtils.namedId("scenario_"); + private final List stepIds = Stream.generate(() -> CommonUtils.namedId("step_")) + .limit(3).collect(Collectors.toList()); + + private final ReportPortalClient client = mock(ReportPortalClient.class); + private final ReportPortal rp = ReportPortal.create(client, standardParameters(), testExecutor()); + + @BeforeEach + public void setupMock() { + mockLaunch(client, null, featureId, scenarioId, stepIds); + mockBatchLogging(client); + } + + @Test + public void test_no_parameters_reporting() { + var results = TestUtils.runAsReport(rp, "classpath:feature/simple.feature"); + assertThat(results.getFailCount(), equalTo(0)); + + ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(client, times(1)).startTestItem(captor.capture()); + verify(client, times(1)).startTestItem(same(featureId), captor.capture()); + verify(client, times(3)).startTestItem(same(scenarioId), captor.capture()); + + List items = captor.getAllValues(); + assertThat(items, hasSize(5)); + + StartTestItemRQ featureRq = items.get(0); + StartTestItemRQ scenarioRq = items.get(1); + + assertThat(featureRq.getParameters(), nullValue()); + assertThat(scenarioRq.getParameters(), nullValue()); + + items.subList(2, items.size()).forEach(step -> assertThat(step.getParameters(), nullValue())); + } +}