From ddb4ddce28f244ed3b455c5a13c0e27b9346eac9 Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Fri, 24 Apr 2026 00:15:38 +0300 Subject: [PATCH 01/19] Update CHANGELOG.md --- CHANGELOG.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc6a612..b5b6d05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,13 @@ # Changelog -### Changed -- Client version updated to [5.4.14](https://github.com/reportportal/client-java/releases/tag/5.4.14), by @HardNorth -- Karate dependency version updated to `1.5.2`, by @HardNorth -### Removed -- Java 11-16 support, by @HardNorth ## [Unreleased] ## [5.4.0] ### Changed -- Client version updated to [5.4.13](https://github.com/reportportal/client-java/releases/tag/5.4.13), by @HardNorth +- Client version updated to [5.4.14](https://github.com/reportportal/client-java/releases/tag/5.4.14), by @HardNorth +- Karate dependency version updated to `1.5.2`, by @HardNorth +### Removed +- Java 11-16 support, by @HardNorth ## [5.3.7] ### Changed From 8ad374766db2d0868444b80c90377fa191788767 Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Fri, 24 Apr 2026 09:53:47 +0300 Subject: [PATCH 02/19] Update Karate and minor version --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- README.md | 2 +- README_TEMPLATE.md | 2 +- build.gradle | 4 +- gradle.properties | 6 +- .../karate/KarateReportPortalRunner.java | 88 ---- .../karate/ReportPortalPublisher.java | 438 ------------------ ...k.java => ReportPortalResultListener.java} | 268 +++++------ .../karate/ReportPortalUtils.java | 81 +--- .../epam/reportportal/karate/KarateTest.java | 37 -- .../karate/ReportPortalPublisherTest.java | 101 ---- .../attributes/DifferentAttributesTest.java | 10 +- .../attributes/LaunchAttributesTest.java | 10 +- .../karate/attributes/NoAttributesTest.java | 10 +- .../attributes/SystemAttributesTest.java | 10 +- .../background/BackgroundExamplesTest.java | 12 +- .../karate/background/BackgroundTest.java | 12 +- .../background/BackgroundTwoStepsTest.java | 12 +- ...lTheSameFeatureWithParametersHookTest.java | 6 +- .../call/CallWithParametersHookTest.java | 6 +- .../call/CallWithParametersPublisherTest.java | 6 +- .../karate/coderef/ExamplesCodeRefTest.java | 10 +- .../karate/coderef/ScenarioCodeRefTest.java | 10 +- .../description/DescriptionExamplesTest.java | 10 +- .../description/LaunchDescriptionTest.java | 10 +- .../NoDescriptionExamplesTest.java | 10 +- .../karate/description/NoDescriptionTest.java | 10 +- .../description/NoLaunchDescriptionTest.java | 10 +- .../ScenarioDescriptionErrorLogTest.java | 10 +- ...rrorLogWithDescriptionAndExamplesTest.java | 10 +- ...escriptionErrorLogWithDescriptionTest.java | 10 +- ...ioDescriptionErrorLogWithExamplesTest.java | 10 +- .../description/SimpleDescriptionTest.java | 12 +- .../karate/id/ExamplesTestCaseIdTest.java | 10 +- .../karate/id/ScenarioTestCaseIdTest.java | 10 +- .../launch/LaunchRequiredFieldsTest.java | 10 +- .../karate/logging/EmbedLoggingTest.java | 10 +- .../logging/HttpRequestLoggingTest.java | 10 +- .../logging/SimpleFailureLoggingTest.java | 10 +- .../karate/name/NoFeatureNameTest.java | 10 +- .../karate/name/SimpleItemNameTest.java | 10 +- .../ExamplesScenarioParametersTest.java | 10 +- .../ExamplesStepParametersTest.java | 12 +- .../karate/parameters/NoParametersTest.java | 10 +- .../parameters/NullValueExamplesTest.java | 10 +- .../parameters/TableParametersTest.java | 10 +- .../karate/retry/RetryFailedTest.java | 87 ---- .../karate/status/OneExampleFailedTest.java | 10 +- .../OneExampleWithBackgroundFailedTest.java | 10 +- .../karate/status/SimpleAllPassedTest.java | 10 +- .../status/SimpleOneStepFailedTest.java | 10 +- .../karate/tags/SimpleTagInclusionTest.java | 10 +- .../karate/timing/SimpleTimingTest.java | 10 +- .../karate/utils/ReflectUtils.java | 35 -- .../reportportal/karate/utils/TestUtils.java | 33 +- 56 files changed, 374 insertions(+), 1220 deletions(-) delete mode 100644 src/main/java/com/epam/reportportal/karate/KarateReportPortalRunner.java delete mode 100644 src/main/java/com/epam/reportportal/karate/ReportPortalPublisher.java rename src/main/java/com/epam/reportportal/karate/{ReportPortalHook.java => ReportPortalResultListener.java} (60%) delete mode 100644 src/test/java/com/epam/reportportal/karate/KarateTest.java delete mode 100644 src/test/java/com/epam/reportportal/karate/ReportPortalPublisherTest.java delete mode 100644 src/test/java/com/epam/reportportal/karate/retry/RetryFailedTest.java delete mode 100644 src/test/java/com/epam/reportportal/karate/utils/ReflectUtils.java diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e0dbb13..204edf1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,6 +33,6 @@ jobs: build: uses: reportportal/.github/.github/workflows/agent-java-ci.yml@main with: - java-version: '17' + java-version: '21' secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3e7a14e..219908c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,7 +28,7 @@ jobs: release: uses: reportportal/.github/.github/workflows/agent-java-release.yml@main with: - java-version: '17' + java-version: '21' secrets: GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} diff --git a/README.md b/README.md index ee9e06c..77edbbe 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ test results in this case, the test project should use by `ReportPortalHook` cla E.G.: ```java -import com.epam.reportportal.karate.ReportPortalHook; +import com.epam.reportportal.karate.ReportPortalResultListener; import com.intuit.karate.Results; import com.intuit.karate.Runner; import org.junit.jupiter.api.Assertions; diff --git a/README_TEMPLATE.md b/README_TEMPLATE.md index 13c4f66..650d3e1 100644 --- a/README_TEMPLATE.md +++ b/README_TEMPLATE.md @@ -102,7 +102,7 @@ test results in this case, the test project should use by `ReportPortalHook` cla E.G.: ```java -import com.epam.reportportal.karate.ReportPortalHook; +import com.epam.reportportal.karate.ReportPortalResultListener; import com.intuit.karate.Results; import com.intuit.karate.Runner; import org.junit.jupiter.api.Assertions; diff --git a/build.gradle b/build.gradle index 614fca9..a836345 100644 --- a/build.gradle +++ b/build.gradle @@ -30,8 +30,8 @@ project.ext.limits = [ 'class' : 83 ] -sourceCompatibility = JavaVersion.VERSION_17 -targetCompatibility = JavaVersion.VERSION_17 +sourceCompatibility = JavaVersion.VERSION_21 +targetCompatibility = JavaVersion.VERSION_21 compileJava.options.encoding = 'UTF-8' compileTestJava.options.encoding = 'UTF-8' diff --git a/gradle.properties b/gradle.properties index 12c6018..a198ead 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,8 +1,8 @@ name=agent-java-karate -version=5.4.1-SNAPSHOT -description=EPAM ReportPortal. Karate test framework [1.3.1, 1.5.2] adapter +version=5.5.0-SNAPSHOT +description=EPAM ReportPortal. Karate test framework [2.0.0, ) adapter gradle_version=8.2 -karate_version=1.5.2 +karate_version=2.0.4 junit_version=5.10.1 mockito_version=5.4.0 test_utils_version=0.1.0 diff --git a/src/main/java/com/epam/reportportal/karate/KarateReportPortalRunner.java b/src/main/java/com/epam/reportportal/karate/KarateReportPortalRunner.java deleted file mode 100644 index 3a6f7a3..0000000 --- a/src/main/java/com/epam/reportportal/karate/KarateReportPortalRunner.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2024 EPAM Systems - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.epam.reportportal.karate; - -import com.epam.reportportal.service.ReportPortal; -import com.intuit.karate.Results; -import com.intuit.karate.Runner; - -/** - * Karate runner with ReportPortal integration - */ -public class KarateReportPortalRunner { - - /** - * Create a new builder for the Karate runner with ReportPortal integration - * - * @param paths paths to feature files - * @param type of the builder - * @return a new builder - */ - public static > Builder path(String... paths) { - Builder builder = new Builder<>(); - return builder.path(paths); - } - - /** - * Builder for the Karate runner with ReportPortal integration - * - * @param type of the builder - */ - public static class Builder> extends Runner.Builder { - private ReportPortal rp; - - /** - * Create a new builder - */ - public Builder() { - super(); - } - - /** - * Set the ReportPortal instance to use - * - * @param reportPortal the ReportPortal instance - * @return the builder - */ - public Builder withReportPortal(ReportPortal reportPortal) { - rp = reportPortal; - return this; - } - - /** - * Run the tests in parallel - * - * @param threadCount number of threads to use - * @return the results of the tests - */ - @Override - public Results parallel(int threadCount) { - if (rp == null) { - rp = ReportPortal.builder().build(); - } - ReportPortalPublisher reporter = new ReportPortalPublisher(rp); - reporter.startLaunch(); - Results results = super.parallel(threadCount); - results.getFeatureResults().forEach(f -> { - reporter.startFeature(f); - reporter.finishFeature(f); - }); - reporter.finishLaunch(); - return results; - } - } -} diff --git a/src/main/java/com/epam/reportportal/karate/ReportPortalPublisher.java b/src/main/java/com/epam/reportportal/karate/ReportPortalPublisher.java deleted file mode 100644 index a623e43..0000000 --- a/src/main/java/com/epam/reportportal/karate/ReportPortalPublisher.java +++ /dev/null @@ -1,438 +0,0 @@ -/* - * Copyright 2024 EPAM Systems - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.epam.reportportal.karate; - -import com.epam.reportportal.listeners.ItemStatus; -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.utils.MemoizingSupplier; -import com.epam.reportportal.utils.StatusEvaluation; -import com.epam.ta.reportportal.ws.model.FinishExecutionRQ; -import com.epam.ta.reportportal.ws.model.FinishTestItemRQ; -import com.epam.ta.reportportal.ws.model.StartTestItemRQ; -import com.epam.ta.reportportal.ws.model.launch.StartLaunchRQ; -import com.intuit.karate.core.*; -import io.reactivex.Maybe; -import jakarta.annotation.Nonnull; -import jakarta.annotation.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.time.Instant; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Supplier; - -import static com.epam.reportportal.karate.ReportPortalUtils.*; -import static com.epam.reportportal.utils.ParameterUtils.formatParametersAsTable; -import static com.epam.reportportal.utils.formatting.MarkdownUtils.formatDataTable; -import static java.util.Optional.ofNullable; -import static org.apache.commons.lang3.StringUtils.isNotBlank; - -/** - * ReportPortal test results publisher for Karate. This class publish results after test pass. - */ -public class ReportPortalPublisher { - private static final Logger LOGGER = LoggerFactory.getLogger(ReportPortalPublisher.class); - protected final MemoizingSupplier launch; - private final Map> featureIdMap = new HashMap<>(); - private final Map> scenarioIdMap = new HashMap<>(); - private final Map stepStartTimeMap = new HashMap<>(); - private Maybe backgroundId; - private ItemStatus backgroundStatus; - private Maybe stepId; - private Thread shutDownHook; - - public ReportPortalPublisher(ReportPortal reportPortal) { - launch = new MemoizingSupplier<>(() -> { - ListenerParameters params = reportPortal.getParameters(); - StartLaunchRQ rq = buildStartLaunchRq(params); - Launch newLaunch = reportPortal.newLaunch(rq); - shutDownHook = registerShutdownHook(this::finishLaunch); - return newLaunch; - }); - } - - public ReportPortalPublisher(Supplier launchSupplier) { - launch = new MemoizingSupplier<>(launchSupplier); - } - - /** - * Customize start launch event/request - * - * @param parameters Launch configuration parameters - * @return request to ReportPortal - */ - protected StartLaunchRQ buildStartLaunchRq(ListenerParameters parameters) { - return ReportPortalUtils.buildStartLaunchRq(parameters); - } - - /** - * Start sending Launch data to ReportPortal. - */ - public void startLaunch() { - //noinspection ReactiveStreamsUnusedPublisher - launch.get().start(); - } - - /** - * Customize start Launch finish event/request. - * - * @param parameters Launch configuration parameters - * @return request to ReportPortal - */ - @Nonnull - protected FinishExecutionRQ buildFinishLaunchRq(@Nonnull ListenerParameters parameters) { - return ReportPortalUtils.buildFinishLaunchRq(parameters); - } - - /** - * Finish sending Launch data to ReportPortal. - */ - public void finishLaunch() { - ReportPortalUtils.doFinishLaunch(launch.get(), buildFinishLaunchRq(launch.get().getParameters()), shutDownHook); - } - - /** - * Build ReportPortal request for start Feature event. - * - * @param featureResult Karate's FeatureResult object instance - * @return request to ReportPortal - */ - @Nonnull - protected StartTestItemRQ buildStartFeatureRq(@Nonnull FeatureResult featureResult) { - return ReportPortalUtils.buildStartFeatureRq(featureResult.getFeature()); - } - - /** - * Start sending Feature data to ReportPortal. - * - * @param featureResult feature result - */ - public void startFeature(@Nonnull FeatureResult featureResult) { - StartTestItemRQ rq = buildStartFeatureRq(featureResult); - Maybe featureId = launch.get().startTestItem(rq); - featureIdMap.put(featureResult.getCallNameForReport(), featureId); - } - - /** - * Build ReportPortal request for finish Feature event. - * - * @param featureResult Karate's FeatureResult object instance - * @return request to ReportPortal - */ - @Nonnull - protected FinishTestItemRQ buildFinishFeatureRq(@Nonnull FeatureResult featureResult) { - return buildFinishTestItemRq(Instant.now(), featureResult.isFailed() ? ItemStatus.FAILED : ItemStatus.PASSED); - } - - /** - * Finish sending Feature data to ReportPortal. - * - * @param featureResult feature result - */ - public void finishFeature(FeatureResult featureResult) { - if (!featureIdMap.containsKey(featureResult.getCallNameForReport())) { - LOGGER.error("ERROR: Trying to finish unspecified feature."); - } - - for (ScenarioResult scenarioResult : featureResult.getScenarioResults()) { - startScenario(scenarioResult, featureResult); - List stepResults = scenarioResult.getStepResults(); - - for (StepResult stepResult : stepResults) { - startStep(stepResult, scenarioResult); - sendStepResults(stepResult); - finishStep(stepResult, scenarioResult); - } - - finishScenario(scenarioResult); - } - - FinishTestItemRQ rq = buildFinishFeatureRq(featureResult); - //noinspection ReactiveStreamsUnusedPublisher - launch.get().finishTestItem(featureIdMap.remove(featureResult.getCallNameForReport()), rq); - } - - /** - * Build ReportPortal request for start Scenario event. - * - * @param scenarioResult Karate's ScenarioResult object instance - * @return request to ReportPortal - */ - @Nonnull - protected StartTestItemRQ buildStartScenarioRq(@Nonnull ScenarioResult scenarioResult) { - return ReportPortalUtils.buildStartScenarioRq(scenarioResult); - } - - /** - * Start sending Scenario data to ReportPortal. - * - * @param scenarioResult scenario result - * @param featureResult feature result - */ - public void startScenario(ScenarioResult scenarioResult, FeatureResult featureResult) { - StartTestItemRQ rq = buildStartScenarioRq(scenarioResult); - - Maybe scenarioId = launch.get().startTestItem(featureIdMap.get(featureResult.getCallNameForReport()), rq); - scenarioIdMap.put(scenarioResult.getScenario().getName(), scenarioId); - } - - /** - * Build ReportPortal request for finish Scenario event. - * - * @param scenarioResult Karate's ScenarioResult object instance - * @return request to ReportPortal - */ - @Nonnull - protected FinishTestItemRQ buildFinishScenarioRq(@Nonnull ScenarioResult scenarioResult) { - return ReportPortalUtils.buildFinishScenarioRq(scenarioResult); - } - - /** - * Finish sending Scenario data to ReportPortal. - * - * @param scenarioResult scenario result - */ - public void finishScenario(ScenarioResult scenarioResult) { - if (!scenarioIdMap.containsKey(scenarioResult.getScenario().getName())) { - LOGGER.error("ERROR: Trying to finish unspecified scenario."); - } - - FinishTestItemRQ rq = buildFinishScenarioRq(scenarioResult); - Maybe removedScenarioId = scenarioIdMap.remove(scenarioResult.getScenario().getName()); - stepStartTimeMap.remove(scenarioResult.getScenario().getUniqueId()); - //noinspection ReactiveStreamsUnusedPublisher - launch.get().finishTestItem(removedScenarioId, rq); - finishBackground(null, scenarioResult); - } - - /** - * Build ReportPortal request for start Background event. - * - * @param stepResult Karate's StepResult object instance - * @param scenarioResult Karate's ScenarioResult object instance - * @return request to ReportPortal - */ - @Nonnull - @SuppressWarnings("unused") - protected StartTestItemRQ buildStartBackgroundRq(@Nonnull StepResult stepResult, @Nonnull ScenarioResult scenarioResult) { - return ReportPortalUtils.buildStartBackgroundRq(stepResult.getStep(), scenarioResult.getScenario()); - } - - /** - * Start sending Background data to ReportPortal. - * - * @param stepResult Karate's StepResult object instance - * @param scenarioResult Karate's ScenarioResult object instance - */ - public void startBackground(@Nonnull StepResult stepResult, @Nonnull ScenarioResult scenarioResult) { - backgroundId = ofNullable(backgroundId).orElseGet(() -> { - StartTestItemRQ backgroundRq = buildStartBackgroundRq(stepResult, scenarioResult); - return launch.get().startTestItem(scenarioIdMap.get(scenarioResult.getScenario().getName()), backgroundRq); - }); - } - - /** - * Build ReportPortal request for finish Background event. - * - * @param stepResult Karate's StepResult object instance - * @param scenarioResult Karate's ScenarioResult object instance - * @return request to ReportPortal - */ - @Nonnull - @SuppressWarnings("unused") - protected FinishTestItemRQ buildFinishBackgroundRq(@Nullable StepResult stepResult, @Nonnull ScenarioResult scenarioResult) { - return buildFinishTestItemRq(Instant.now(), backgroundStatus); - - } - - /** - * Finish sending Scenario data to ReportPortal. - * - * @param stepResult step result - * @param scenarioResult scenario result - */ - public void finishBackground(@Nullable StepResult stepResult, @Nonnull ScenarioResult scenarioResult) { - Maybe myBackgroundId = backgroundId; - backgroundId = null; - ofNullable(myBackgroundId).ifPresent(id -> { - FinishTestItemRQ finishRq = buildFinishBackgroundRq(stepResult, scenarioResult); - //noinspection ReactiveStreamsUnusedPublisher - launch.get().finishTestItem(id, finishRq); - }); - } - - /** - * Get step start time. To keep the steps order in case previous step startTime == current step startTime or - * previous step startTime > current step startTime. - * - * @param scenarioUniqueId Karate's Scenario Unique ID - * @return step new startTime in Instant format. - */ - @Nonnull - private Instant getStepStartTime(@Nullable String scenarioUniqueId) { - return ReportPortalUtils.getStepStartTime(scenarioUniqueId, stepStartTimeMap, launch.get().useMicroseconds()); - } - - /** - * Customize start Step test item event/request. - * - * @param stepResult Karate's StepResult class instance - * @param scenarioResult Karate's ScenarioResult class instance - * @return request to ReportPortal - */ - @Nonnull - protected StartTestItemRQ buildStartStepRq(@Nonnull StepResult stepResult, @Nonnull ScenarioResult scenarioResult) { - StartTestItemRQ rq = ReportPortalUtils.buildStartStepRq(stepResult.getStep(), scenarioResult.getScenario()); - Instant startTime = getStepStartTime(scenarioResult.getScenario().getUniqueId()); - rq.setStartTime(startTime); - return rq; - } - - /** - * Start sending Step data to ReportPortal. - * - * @param stepResult step result - * @param scenarioResult scenario result - */ - public void startStep(StepResult stepResult, ScenarioResult scenarioResult) { - Step step = stepResult.getStep(); - boolean background = step.isBackground(); - if (background) { - startBackground(stepResult, scenarioResult); - } - - StartTestItemRQ stepRq = buildStartStepRq(stepResult, scenarioResult); - stepId = launch.get() - .startTestItem( - background && backgroundId != null ? backgroundId : scenarioIdMap.get(scenarioResult.getScenario().getName()), - stepRq - ); - ofNullable(stepRq.getParameters()).filter(params -> !params.isEmpty()) - .ifPresent(params -> sendLog(stepId, String.format(PARAMETERS_PATTERN, formatParametersAsTable(params)), LogLevel.INFO)); - ofNullable(step.getTable()).ifPresent(table -> sendLog(stepId, "Table:\n\n" + formatDataTable(table.getRows()), LogLevel.INFO)); - String docString = step.getDocString(); - if (isNotBlank(docString)) { - sendLog(stepId, "Docstring:\n\n" + asMarkdownCode(step.getDocString()), LogLevel.INFO); - } - } - - /** - * Build ReportPortal request for finish Step event. - * - * @param stepResult Karate's StepResult class instance - * @param scenarioResult Karate's ScenarioResult class instance - * @return request to ReportPortal - */ - @Nonnull - @SuppressWarnings("unused") - protected FinishTestItemRQ buildFinishStepRq(@Nonnull StepResult stepResult, @Nonnull ScenarioResult scenarioResult) { - return buildFinishTestItemRq(Instant.now(), getStepStatus(stepResult.getResult().getStatus())); - } - - @SuppressWarnings("unused") - private void saveBackgroundStatus(@Nonnull StepResult stepResult, @Nonnull ScenarioResult scenarioResult) { - backgroundStatus = StatusEvaluation.evaluateStatus(backgroundStatus, getStepStatus(stepResult.getResult().getStatus())); - } - - /** - * Finish sending Step data to ReportPortal. - * - * @param stepResult Karate's StepResult class instance - * @param scenarioResult Karate's ScenarioResult class instance - */ - public void finishStep(StepResult stepResult, ScenarioResult scenarioResult) { - Step step = stepResult.getStep(); - boolean background = step.isBackground(); - if (!background) { - finishBackground(stepResult, scenarioResult); - } - - if (stepId == null) { - LOGGER.error("ERROR: Trying to finish unspecified step."); - return; - } - - FinishTestItemRQ rq = buildFinishStepRq(stepResult, scenarioResult); - if (background) { - saveBackgroundStatus(stepResult, scenarioResult); - } - //noinspection ReactiveStreamsUnusedPublisher - launch.get().finishTestItem(stepId, rq); - } - - /** - * Send Step logs to ReportPortal. - * - * @param itemId item ID future - * @param message log message to send - * @param level log level - */ - protected void sendLog(Maybe itemId, String message, LogLevel level) { - ReportPortalUtils.sendLog(itemId, message, level); - } - - /** - * Embed an attachment to ReportPortal. - * - * @param itemId item ID future - * @param embed Karate's Embed object - */ - protected void embedAttachment(Maybe itemId, Embed embed) { - ReportPortalUtils.embedAttachment(itemId, embed); - } - - /** - * Embed an attachment to ReportPortal. - * - * @param itemId item ID future - * @param embeddedEntities a list of Karate's Embed object - */ - protected void embedAttachments(@Nonnull Maybe itemId, @Nullable List embeddedEntities) { - ofNullable(embeddedEntities).ifPresent(embeds -> embeds.forEach(embed -> embedAttachment(itemId, embed))); - } - - /** - * Send Step execution results to ReportPortal. - * - * @param stepResult step execution results - */ - public void sendStepResults(StepResult stepResult) { - Step step = stepResult.getStep(); - Result result = stepResult.getResult(); - String stepLog = stepResult.getStepLog(); - if (isNotBlank(stepLog)) { - sendLog(stepId, stepLog, LogLevel.DEBUG); - } - - embedAttachments(stepId, stepResult.getEmbeds()); - - if (result.isFailed()) { - String fullErrorMessage = step.getPrefix() + " " + step.getText(); - String errorMessage = result.getErrorMessage(); - if (isNotBlank(errorMessage)) { - fullErrorMessage = fullErrorMessage + "\n" + errorMessage; - - } - sendLog(stepId, fullErrorMessage, LogLevel.ERROR); - } - } -} diff --git a/src/main/java/com/epam/reportportal/karate/ReportPortalHook.java b/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java similarity index 60% rename from src/main/java/com/epam/reportportal/karate/ReportPortalHook.java rename to src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java index a269a45..ab716d0 100644 --- a/src/main/java/com/epam/reportportal/karate/ReportPortalHook.java +++ b/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java @@ -25,17 +25,15 @@ import com.epam.reportportal.service.ReportPortal; import com.epam.reportportal.utils.MemoizingSupplier; import com.epam.reportportal.utils.StatusEvaluation; -import com.epam.reportportal.utils.formatting.MarkdownUtils; -import com.epam.reportportal.utils.reflect.Accessible; import com.epam.ta.reportportal.ws.model.FinishExecutionRQ; import com.epam.ta.reportportal.ws.model.FinishTestItemRQ; import com.epam.ta.reportportal.ws.model.StartTestItemRQ; import com.epam.ta.reportportal.ws.model.launch.StartLaunchRQ; -import com.intuit.karate.RuntimeHook; -import com.intuit.karate.Suite; -import com.intuit.karate.core.*; -import com.intuit.karate.http.HttpRequest; -import com.intuit.karate.http.Response; +import io.karatelabs.core.*; +import io.karatelabs.gherkin.Feature; +import io.karatelabs.gherkin.Scenario; +import io.karatelabs.gherkin.Step; +import io.karatelabs.output.ResultListener; import io.reactivex.Maybe; import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; @@ -55,18 +53,18 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank; /** - * ReportPortal test results reporting hook for Karate. This class publish results in the process of test pass. + * ReportPortal test results reporting listener for Karate. */ -public class ReportPortalHook implements RuntimeHook { - private static final Logger LOGGER = LoggerFactory.getLogger(ReportPortalHook.class); +public class ReportPortalResultListener implements ResultListener { + private static final Logger LOGGER = LoggerFactory.getLogger(ReportPortalResultListener.class); protected final MemoizingSupplier launch; private final BlockingConcurrentHashMap>> featureIdMap = new BlockingConcurrentHashMap<>(); private final Map> scenarioIdMap = new ConcurrentHashMap<>(); private final Map> backgroundIdMap = new ConcurrentHashMap<>(); private final Map backgroundStatusMap = new ConcurrentHashMap<>(); private final Map> stepIdMap = new ConcurrentHashMap<>(); - private final Map stepStartTimeMap = new ConcurrentHashMap<>(); private final Set> innerFeatures = Collections.newSetFromMap(new ConcurrentHashMap<>()); + private final ThreadLocal> parentScenarios = ThreadLocal.withInitial(LinkedList::new); private volatile Thread shutDownHook; /** @@ -74,7 +72,7 @@ public class ReportPortalHook implements RuntimeHook { * * @param reportPortal the ReportPortal instance */ - public ReportPortalHook(ReportPortal reportPortal) { + public ReportPortalResultListener(ReportPortal reportPortal) { ListenerParameters params = reportPortal.getParameters(); StartLaunchRQ rq = buildStartLaunchRq(params); launch = new MemoizingSupplier<>(() -> { @@ -90,12 +88,12 @@ public ReportPortalHook(ReportPortal reportPortal) { * Default constructor. Create a new instance of the ReportPortalHook with default ReportPortal instance. */ @SuppressWarnings("unused") - public ReportPortalHook() { + public ReportPortalResultListener() { this(ReportPortal.builder().build()); } @SuppressWarnings("unused") - public ReportPortalHook(Supplier launchSupplier) { + public ReportPortalResultListener(Supplier launchSupplier) { launch = new MemoizingSupplier<>(launchSupplier); } @@ -134,39 +132,24 @@ public void finishLaunch() { * @return request to ReportPortal */ @Nonnull - @SuppressWarnings("unchecked") - protected StartTestItemRQ buildStartFeatureRq(@Nonnull FeatureRuntime fr) { - StartTestItemRQ rq = ReportPortalUtils.buildStartFeatureRq(fr.featureCall.feature); - ofNullable(fr.caller).map(c -> c.arg) - .map(a -> (Map) a.getValue()) - .filter(args -> !args.isEmpty()) - .ifPresent(args -> { - // TODO: cover with tests - String parameters = String.format(PARAMETERS_PATTERN, formatParametersAsTable(getParameters(args))); - String description = rq.getDescription(); - if (isNotBlank(description)) { - rq.setDescription(MarkdownUtils.asTwoParts(parameters, description)); - } else { - rq.setDescription(parameters); - } - }); - return rq; + protected StartTestItemRQ buildStartFeatureRq(@Nonnull Feature fr) { + return ReportPortalUtils.buildStartFeatureRq(fr); } - private String getFeatureNameForReport(FeatureRuntime fr) { - int callDepth = ofNullable(fr.caller).map(c -> c.depth).orElse(0); - return callDepth + ":" + fr.featureCall.feature.getNameForReport(); + private String getFeatureNameForReport(Feature feature) { + return parentScenarios.get().size() + ":" + feature.getNameForReport(); } @Override - public boolean beforeFeature(FeatureRuntime fr) { - StartTestItemRQ rq = buildStartFeatureRq(fr); + public void onFeatureStart(Feature feature) { + Scenario parentScenario = parentScenarios.get().getLast(); + StartTestItemRQ rq = buildStartFeatureRq(feature); featureIdMap.computeIfAbsent( - getFeatureNameForReport(fr), f -> new MemoizingSupplier<>(() -> { - if (ofNullable(fr.caller).map(c -> c.depth).orElse(0) == 0) { + getFeatureNameForReport(feature), f -> new MemoizingSupplier<>(() -> { + if (parentScenario == null) { return launch.get().startTestItem(rq); } else { - Maybe scenarioId = scenarioIdMap.get(fr.caller.parentRuntime.scenario.getUniqueId()); + Maybe scenarioId = scenarioIdMap.get(parentScenario.getUniqueId()); if (scenarioId == null) { LOGGER.error("ERROR: Trying to post unspecified scenario."); return launch.get().startTestItem(rq); @@ -183,7 +166,6 @@ public boolean beforeFeature(FeatureRuntime fr) { } }) ); - return true; } /** @@ -193,13 +175,13 @@ public boolean beforeFeature(FeatureRuntime fr) { * @return request to ReportPortal */ @Nonnull - protected FinishTestItemRQ buildFinishFeatureRq(@Nonnull FeatureRuntime fr) { - return buildFinishTestItemRq(Instant.now(), fr.result.isFailed() ? ItemStatus.FAILED : ItemStatus.PASSED); + protected FinishTestItemRQ buildFinishFeatureRq(@Nonnull FeatureResult fr) { + return buildFinishTestItemRq(Instant.now(), fr.isFailed() ? ItemStatus.FAILED : ItemStatus.PASSED); } @Override - public void afterFeature(FeatureRuntime fr) { - Optional> optionalId = ofNullable(featureIdMap.get(getFeatureNameForReport(fr))).map(Supplier::get); + public void onFeatureEnd(FeatureResult fr) { + Optional> optionalId = ofNullable(featureIdMap.get(getFeatureNameForReport(fr.getFeature()))).map(Supplier::get); if (optionalId.isEmpty()) { LOGGER.error("ERROR: Trying to finish unspecified feature."); } @@ -217,9 +199,9 @@ public void afterFeature(FeatureRuntime fr) { * @return request to ReportPortal */ @Nonnull - protected StartTestItemRQ buildStartScenarioRq(@Nonnull ScenarioRuntime sr) { - StartTestItemRQ rq = ReportPortalUtils.buildStartScenarioRq(sr.result); - ofNullable(featureIdMap.get(getFeatureNameForReport(sr.featureRuntime))).map(Supplier::get) + protected StartTestItemRQ buildStartScenarioRq(@Nonnull Scenario sr) { + StartTestItemRQ rq = ReportPortalUtils.buildStartScenarioRq(sr); + ofNullable(featureIdMap.get(getFeatureNameForReport(sr.getFeature()))).map(Supplier::get) .map(featureId -> innerFeatures.contains(featureId) ? featureId : null) .ifPresent(featureId -> { rq.setType(ItemType.STEP.name()); @@ -230,13 +212,13 @@ protected StartTestItemRQ buildStartScenarioRq(@Nonnull ScenarioRuntime sr) { } @Override - public boolean beforeScenario(ScenarioRuntime sr) { - StartTestItemRQ rq = buildStartScenarioRq(sr); - Optional> optionalId = ofNullable(featureIdMap.get(getFeatureNameForReport(sr.featureRuntime))).map(Supplier::get); + public void onScenarioStart(Scenario scenario) { + StartTestItemRQ rq = buildStartScenarioRq(scenario); + Optional> optionalId = ofNullable(featureIdMap.get(getFeatureNameForReport(scenario.getFeature()))).map(Supplier::get); if (optionalId.isEmpty()) { LOGGER.error("ERROR: Trying to post unspecified feature."); } - ofNullable(scenarioIdMap.get(sr.scenario.getUniqueId())).map(Maybe::blockingGet).ifPresent(id -> { + ofNullable(scenarioIdMap.get(scenario.getUniqueId())).map(Maybe::blockingGet).ifPresent(id -> { rq.setRetry(true); rq.setRetryOf(id); }); @@ -245,9 +227,9 @@ public boolean beforeScenario(ScenarioRuntime sr) { if (innerFeatures.contains(featureId) && StringUtils.isNotBlank(rq.getDescription())) { ReportPortalUtils.sendLog(scenarioId, rq.getDescription(), LogLevel.INFO); } - scenarioIdMap.put(sr.scenario.getUniqueId(), scenarioId); + scenarioIdMap.put(scenario.getUniqueId(), scenarioId); + parentScenarios.get().add(scenario); }); - return true; } /** @@ -257,8 +239,8 @@ public boolean beforeScenario(ScenarioRuntime sr) { * @return request to ReportPortal */ @Nonnull - protected FinishTestItemRQ buildFinishScenarioRq(@Nonnull ScenarioRuntime sr) { - return ReportPortalUtils.buildFinishScenarioRq(sr.result); + protected FinishTestItemRQ buildFinishScenarioRq(@Nonnull ScenarioResult sr) { + return ReportPortalUtils.buildFinishScenarioRq(sr); } /** @@ -269,9 +251,8 @@ protected FinishTestItemRQ buildFinishScenarioRq(@Nonnull ScenarioRuntime sr) { * @return request to ReportPortal */ @Nonnull - @SuppressWarnings("unused") - protected StartTestItemRQ buildStartBackgroundRq(@Nonnull Step step, @Nonnull ScenarioRuntime sr) { - return ReportPortalUtils.buildStartBackgroundRq(step, sr.scenario); + protected StartTestItemRQ buildStartBackgroundRq(Instant startTime, @Nonnull Step step, @Nonnull Scenario sr) { + return ReportPortalUtils.buildStartBackgroundRq(startTime, step, sr); } /** @@ -281,11 +262,11 @@ protected StartTestItemRQ buildStartBackgroundRq(@Nonnull Step step, @Nonnull Sc * @param sr Karate's ScenarioRuntime object instance * @return item ID Future */ - public Maybe startBackground(@Nonnull Step step, @Nonnull ScenarioRuntime sr) { + public Maybe startBackground(Instant startTime, @Nonnull Step step, @Nonnull Scenario sr) { return backgroundIdMap.computeIfAbsent( - sr.scenario.getUniqueId(), k -> { - StartTestItemRQ backgroundRq = buildStartBackgroundRq(step, sr); - return launch.get().startTestItem(scenarioIdMap.get(sr.scenario.getUniqueId()), backgroundRq); + sr.getUniqueId(), k -> { + StartTestItemRQ backgroundRq = buildStartBackgroundRq(startTime, step, sr); + return launch.get().startTestItem(scenarioIdMap.get(sr.getUniqueId()), backgroundRq); } ); } @@ -299,8 +280,11 @@ public Maybe startBackground(@Nonnull Step step, @Nonnull ScenarioRuntim */ @Nonnull @SuppressWarnings("unused") - protected FinishTestItemRQ buildFinishBackgroundRq(@Nullable StepResult stepResult, @Nonnull ScenarioRuntime sr) { - return buildFinishTestItemRq(Instant.now(), backgroundStatusMap.remove(sr.scenario.getUniqueId())); + protected FinishTestItemRQ buildFinishBackgroundRq(@Nullable StepResult stepResult, @Nonnull ScenarioResult sr) { + long duration = ofNullable(stepResult).map(StepResult::getDurationNanos).orElse(0L); + Instant startTime = ofNullable(stepResult).map(StepResult::getStartTime).map(Instant::ofEpochMilli).orElseGet(Instant::now); + Instant endTime = startTime.plusNanos(duration); + return buildFinishTestItemRq(endTime, backgroundStatusMap.remove(sr.getScenario().getUniqueId())); } /** @@ -309,11 +293,12 @@ protected FinishTestItemRQ buildFinishBackgroundRq(@Nullable StepResult stepResu * @param stepResult Karate's StepResult class instance * @param sr Karate's ScenarioRuntime object instance */ - public void finishBackground(@Nullable StepResult stepResult, @Nonnull ScenarioRuntime sr) { - String uniqueId = sr.scenario.getUniqueId(); + public void finishBackground(@Nullable StepResult stepResult, @Nonnull ScenarioResult sr) { + String uniqueId = sr.getScenario().getUniqueId(); Maybe backgroundId = backgroundIdMap.remove(uniqueId); if (backgroundId != null) { FinishTestItemRQ finishRq = buildFinishBackgroundRq(stepResult, sr); + //noinspection ReactiveStreamsUnusedPublisher launch.get().finishTestItem(backgroundId, finishRq); } @@ -325,24 +310,14 @@ public void finishBackground(@Nullable StepResult stepResult, @Nonnull ScenarioR * @param itemId item ID future * @param embed Karate's Embed object */ - protected void embedAttachment(@Nonnull Maybe itemId, @Nonnull Embed embed) { - ReportPortalUtils.embedAttachment(itemId, embed); - } - - /** - * Embed an attachment to ReportPortal. - * - * @param itemId item ID future - * @param embeddedEntities a list of Karate's Embed object - */ - protected void embedAttachments(@Nonnull Maybe itemId, @Nullable List embeddedEntities) { - ofNullable(embeddedEntities).ifPresent(embeds -> embeds.forEach(embed -> embedAttachment(itemId, embed))); + protected void embedAttachment(@Nonnull Instant time, @Nonnull Maybe itemId, @Nonnull StepResult.Embed embed) { + ReportPortalUtils.embedAttachment(time, itemId, embed); } @Override - public void afterScenario(ScenarioRuntime sr) { - Maybe scenarioId = scenarioIdMap.get(sr.scenario.getUniqueId()); - stepStartTimeMap.remove(sr.scenario.getUniqueId()); + public void onScenarioEnd(ScenarioResult sr) { + Scenario scenario = sr.getScenario(); + Maybe scenarioId = scenarioIdMap.get(scenario.getUniqueId()); finishBackground(null, sr); if (scenarioId == null) { @@ -350,32 +325,15 @@ public void afterScenario(ScenarioRuntime sr) { return; } - try { - @SuppressWarnings("unchecked") - List embeddedEntities = (List) new Accessible(sr).field("embeds").getValue(); - embedAttachments(scenarioId, embeddedEntities); - } catch (Exception e) { - LOGGER.warn( - "Unable to retrieve scenario embeddings; attachments (such as screenshots or logs) will not be reported for this" // - + " scenario. Test execution and reporting will continue. Exception details:", e - ); - } + sr.getStepResults().forEach(stepResult -> { + beforeStep(stepResult, sr); + afterStep(stepResult, sr); + }); FinishTestItemRQ rq = buildFinishScenarioRq(sr); //noinspection ReactiveStreamsUnusedPublisher launch.get().finishTestItem(scenarioId, rq); - } - - /** - * Get step start time. To keep the steps order in case previous step startTime == current step startTime or - * previous step startTime > current step startTime. - * - * @param scenarioUniqueId Karate's Scenario Unique ID - * @return step new startTime in Instant format. - */ - @Nonnull - private Instant getStepStartTime(@Nullable String scenarioUniqueId) { - return ReportPortalUtils.getStepStartTime(scenarioUniqueId, stepStartTimeMap, launch.get().useMicroseconds()); + parentScenarios.get().removeFirst(); } /** @@ -386,9 +344,8 @@ private Instant getStepStartTime(@Nullable String scenarioUniqueId) { * @return request to ReportPortal */ @Nonnull - protected StartTestItemRQ buildStartStepRq(@Nonnull Step step, @Nonnull ScenarioRuntime sr) { - StartTestItemRQ rq = ReportPortalUtils.buildStartStepRq(step, sr.scenario); - Instant startTime = getStepStartTime(sr.scenario.getUniqueId()); + protected StartTestItemRQ buildStartStepRq(Instant startTime, @Nonnull Step step, @Nonnull Scenario sr) { + StartTestItemRQ rq = ReportPortalUtils.buildStartStepRq(step, sr); rq.setStartTime(startTime); return rq; } @@ -400,30 +357,42 @@ protected StartTestItemRQ buildStartStepRq(@Nonnull Step step, @Nonnull Scenario * @param message log message to send * @param level log level */ - protected void sendLog(Maybe itemId, String message, LogLevel level) { - ReportPortalUtils.sendLog(itemId, message, level); + protected void sendLog(Instant time, Maybe itemId, String message, LogLevel level) { + ReportPortalUtils.sendLog(itemId, message, level, time); } - @Override - public boolean beforeStep(Step step, ScenarioRuntime sr) { + public void beforeStep(StepResult stepResult, ScenarioResult sr) { + Step step = stepResult.getStep(); + Scenario scenario = sr.getScenario(); + Instant startTime = Instant.ofEpochMilli(stepResult.getStartTime()); + boolean background = step.isBackground(); Maybe backgroundId = null; if (background) { - backgroundId = startBackground(step, sr); + backgroundId = startBackground(startTime, step, scenario); } - StartTestItemRQ stepRq = buildStartStepRq(step, sr); + StartTestItemRQ stepRq = buildStartStepRq(startTime, step, scenario); - String scenarioId = sr.scenario.getUniqueId(); + String scenarioId = scenario.getUniqueId(); Maybe stepId = launch.get().startTestItem(background ? backgroundId : scenarioIdMap.get(scenarioId), stepRq); stepIdMap.put(scenarioId, stepId); ofNullable(stepRq.getParameters()).filter(params -> !params.isEmpty()) - .ifPresent(params -> sendLog(stepId, String.format(PARAMETERS_PATTERN, formatParametersAsTable(params)), LogLevel.INFO)); - ofNullable(step.getTable()).ifPresent(table -> sendLog(stepId, "Table:\n\n" + formatDataTable(table.getRows()), LogLevel.INFO)); + .ifPresent(params -> sendLog( + startTime.plusMillis(1), + stepId, + String.format(PARAMETERS_PATTERN, formatParametersAsTable(params)), + LogLevel.INFO + )); + ofNullable(step.getTable()).ifPresent(table -> sendLog( + startTime.plusMillis(2), + stepId, + "Table:\n\n" + formatDataTable(table.getRows()), + LogLevel.INFO + )); String docString = step.getDocString(); if (isNotBlank(docString)) { - sendLog(stepId, "Docstring:\n\n" + asMarkdownCode(step.getDocString()), LogLevel.INFO); + sendLog(startTime.plusMillis(3), stepId, "Docstring:\n\n" + asMarkdownCode(step.getDocString()), LogLevel.INFO); } - return true; } /** @@ -432,20 +401,36 @@ public boolean beforeStep(Step step, ScenarioRuntime sr) { * @param stepResult step execution results * @param sr Karate's ScenarioRuntime object instance */ - public void sendStepResults(StepResult stepResult, ScenarioRuntime sr) { - Maybe stepId = stepIdMap.get(sr.scenario.getUniqueId()); + public void sendStepResults(StepResult stepResult, ScenarioResult sr) { + List embeds = ofNullable(stepResult.getEmbeds()).orElse(Collections.emptyList()); + String log = ofNullable(stepResult.getLog()).filter(logs -> !logs.isBlank()).orElse(null); + + Instant itemTime = Instant.ofEpochMilli(stepResult.getStartTime()); + long stepDuration = stepResult.getDurationNanos(); + int numberOfArtefacts = embeds.size() + (log != null ? 1 : 0) + (stepResult.isFailed() ? 1 : 0); + int numberOfSteps = numberOfArtefacts + 1; // To always log a little bit after step start time + long duration = stepDuration / numberOfSteps; + + Maybe stepId = stepIdMap.get(sr.getScenario().getUniqueId()); Step step = stepResult.getStep(); - Result result = stepResult.getResult(); + for (var embed : embeds) { + itemTime = itemTime.plusNanos(duration); + embedAttachment(itemTime, stepId, embed); + } - ofNullable(stepResult.getEmbeds()).ifPresent(embeds -> embeds.forEach(embed -> embedAttachment(stepId, embed))); + if (log != null) { + itemTime = itemTime.plusNanos(duration); + sendLog(itemTime, stepId, log, LogLevel.INFO); + } - if (result.isFailed()) { + if (stepResult.isFailed()) { String fullErrorMessage = step.getPrefix() + " " + step.getText(); - String errorMessage = result.getErrorMessage(); + String errorMessage = stepResult.getErrorMessage(); if (isNotBlank(errorMessage)) { fullErrorMessage = fullErrorMessage + "\n" + errorMessage; } - sendLog(stepId, fullErrorMessage, LogLevel.ERROR); + itemTime = itemTime.plusNanos(duration); + sendLog(itemTime, stepId, fullErrorMessage, LogLevel.ERROR); } } @@ -458,29 +443,28 @@ public void sendStepResults(StepResult stepResult, ScenarioRuntime sr) { */ @Nonnull @SuppressWarnings("unused") - protected FinishTestItemRQ buildFinishStepRq(@Nonnull StepResult stepResult, @Nonnull ScenarioRuntime sr) { - return buildFinishTestItemRq(Instant.now(), getStepStatus(stepResult.getResult().getStatus())); + protected FinishTestItemRQ buildFinishStepRq(@Nonnull StepResult stepResult, @Nonnull ScenarioResult sr) { + Instant endTime = Instant.ofEpochMilli(stepResult.getStartTime()).plusNanos(stepResult.getDurationNanos()); + return buildFinishTestItemRq(endTime, getStepStatus(stepResult.getStatus())); } - private void saveBackgroundStatus(@Nonnull StepResult stepResult, @Nonnull ScenarioRuntime sr) { + private void saveBackgroundStatus(@Nonnull StepResult stepResult, @Nonnull ScenarioResult sr) { backgroundStatusMap.put( - sr.scenario.getUniqueId(), + sr.getScenario().getUniqueId(), StatusEvaluation.evaluateStatus( - backgroundStatusMap.get(sr.scenario.getUniqueId()), - getStepStatus(stepResult.getResult().getStatus()) + backgroundStatusMap.get(sr.getScenario().getUniqueId()), + getStepStatus(stepResult.getStatus()) ) ); } - @Override - public void afterStep(StepResult stepResult, ScenarioRuntime sr) { + public void afterStep(StepResult stepResult, ScenarioResult sr) { boolean background = stepResult.getStep().isBackground(); if (!background) { finishBackground(stepResult, sr); } - sendStepResults(stepResult, sr); - Maybe stepId = stepIdMap.remove(sr.scenario.getUniqueId()); + Maybe stepId = stepIdMap.remove(sr.getScenario().getUniqueId()); if (stepId == null) { LOGGER.error("ERROR: Trying to finish unspecified step."); return; @@ -495,24 +479,12 @@ public void afterStep(StepResult stepResult, ScenarioRuntime sr) { } @Override - public void beforeHttpCall(HttpRequest request, ScenarioRuntime sr) { - // TODO: Implement better HTTP request logging later - RuntimeHook.super.beforeHttpCall(request, sr); - } - - @Override - public void afterHttpCall(HttpRequest request, Response response, ScenarioRuntime sr) { - // TODO: Implement better HTTP response logging later - RuntimeHook.super.afterHttpCall(request, response, sr); - } - - @Override - public void beforeSuite(Suite suite) { + public void onSuiteStart(Suite suite) { // Omit Suite logic, since there is no Suite names in Karate } @Override - public void afterSuite(Suite suite) { + public void onSuiteEnd(SuiteResult suite) { // Omit Suite logic, since there is no Suite names in Karate } } diff --git a/src/main/java/com/epam/reportportal/karate/ReportPortalUtils.java b/src/main/java/com/epam/reportportal/karate/ReportPortalUtils.java index 766efbb..aebdfc7 100644 --- a/src/main/java/com/epam/reportportal/karate/ReportPortalUtils.java +++ b/src/main/java/com/epam/reportportal/karate/ReportPortalUtils.java @@ -35,7 +35,9 @@ import com.epam.ta.reportportal.ws.model.attribute.ItemAttributesRQ; import com.epam.ta.reportportal.ws.model.launch.StartLaunchRQ; import com.epam.ta.reportportal.ws.model.log.SaveLogRQ; -import com.intuit.karate.core.*; +import io.karatelabs.core.ScenarioResult; +import io.karatelabs.core.StepResult; +import io.karatelabs.gherkin.*; import io.reactivex.Maybe; import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; @@ -43,7 +45,6 @@ import org.slf4j.LoggerFactory; import java.time.Instant; -import java.time.temporal.ChronoUnit; import java.util.*; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -306,18 +307,17 @@ public static TestCaseIdEntry getTestCaseId(@Nonnull Scenario scenario) { /** * Build ReportPortal request for start Scenario event * - * @param result Karate's ScenarioResult object instance + * @param scenario Karate's Scenario object instance * @return request to ReportPortal */ @Nonnull - public static StartTestItemRQ buildStartScenarioRq(@Nonnull ScenarioResult result) { - Scenario scenario = result.getScenario(); + public static StartTestItemRQ buildStartScenarioRq(@Nonnull Scenario scenario) { StartTestItemRQ rq = buildStartTestItemRq(scenario.getName(), Instant.now(), ItemType.STEP); rq.setCodeRef(getCodeRef(scenario)); rq.setTestCaseId(ofNullable(getTestCaseId(scenario)).map(TestCaseIdEntry::getId).orElse(null)); rq.setAttributes(toAttributes(scenario.getTags())); rq.setParameters(getParameters(scenario)); - rq.setDescription(buildDescription(scenario, result.getErrorMessage(), getParameters(scenario))); + rq.setDescription(buildDescription(scenario, null, getParameters(scenario))); return rq; } @@ -334,7 +334,7 @@ public static FinishTestItemRQ buildFinishScenarioRq(@Nonnull ScenarioResult res Instant.now(), result.getFailureMessageForDisplay() == null ? ItemStatus.PASSED : ItemStatus.FAILED ); - rq.setDescription(buildDescription(scenario, result.getErrorMessage(), getParameters(scenario))); + rq.setDescription(buildDescription(scenario, result.getFailureMessageForDisplay(), getParameters(scenario))); return rq; } @@ -366,14 +366,15 @@ private static void appendWithDelimiter(StringBuilder builder, String text) { /** * Build ReportPortal request for start Background event. * - * @param step Karate's Step object instance - * @param scenario Karate's Scenario object instance + * @param startTime + * @param step Karate's Step object instance + * @param scenario Karate's Scenario object instance * @return request to ReportPortal */ @Nonnull @SuppressWarnings("unused") - public static StartTestItemRQ buildStartBackgroundRq(@Nonnull Step step, @Nonnull Scenario scenario) { - StartTestItemRQ rq = buildStartTestItemRq(Background.KEYWORD, Instant.now(), ItemType.STEP); + public static StartTestItemRQ buildStartBackgroundRq(Instant startTime, @Nonnull Step step, @Nonnull Scenario scenario) { + StartTestItemRQ rq = buildStartTestItemRq(Background.KEYWORD, startTime, ItemType.STEP); rq.setHasStats(false); return rq; } @@ -414,14 +415,12 @@ public static StartTestItemRQ buildStartStepRq(@Nonnull Step step, @Nonnull Scen * @param status Karate item status * @return ReportPortal status */ - public static ItemStatus getStepStatus(String status) { + @SuppressWarnings("UnnecessaryDefault") + public static ItemStatus getStepStatus(StepResult.Status status) { return switch (status) { - case "failed" -> ItemStatus.FAILED; - case "passed" -> ItemStatus.PASSED; - case "skipped" -> ItemStatus.SKIPPED; - case "stopped" -> ItemStatus.STOPPED; - case "interrupted" -> ItemStatus.INTERRUPTED; - case "cancelled" -> ItemStatus.CANCELLED; + case FAILED -> ItemStatus.FAILED; + case PASSED -> ItemStatus.PASSED; + case SKIPPED -> ItemStatus.SKIPPED; default -> { LOGGER.warn("Unknown step status received! Set it as SKIPPED"); yield ItemStatus.SKIPPED; @@ -467,19 +466,19 @@ public static void sendLog(Maybe itemId, String message, LogLevel level) * @param itemId item ID future * @param embed Karate's Embed object */ - public static void embedAttachment(@Nonnull Maybe itemId, @Nonnull Embed embed) { + public static void embedAttachment(@Nonnull Instant time, @Nonnull Maybe itemId, @Nonnull StepResult.Embed embed) { ReportPortal.emitLog( itemId, id -> { SaveLogRQ rq = new SaveLogRQ(); rq.setItemUuid(id); rq.setLevel(LogLevel.INFO.name()); - rq.setLogTime(Instant.now()); - rq.setMessage("Attachment: " + embed.getResourceType().contentType); + rq.setLogTime(time); + rq.setMessage("Attachment: " + embed.getMimeType()); SaveLogRQ.File file = new SaveLogRQ.File(); - file.setName(embed.getFile().getName()); - file.setContent(embed.getBytes()); - file.setContentType(embed.getResourceType().contentType); + file.setName(embed.getFileName()); + file.setContent(embed.getData()); + file.setContentType(embed.getMimeType()); rq.setFile(file); return rq; @@ -537,38 +536,4 @@ public static String getInnerScenarioName(String name) { public static String getInnerFeatureName(String name) { return FEATURE_TAG + name; } - - /** - * Get step start time. To keep the steps order in case previous step startTime == current step startTime or - * previous step startTime > current step startTime. - * - * @param scenarioUniqueId Karate's Scenario Unique ID, a key for stepStartTimeMap - * @param stepStartTimeMap a holder for start times for every particular scenario - * @param useMicroseconds if server supports microseconds - * @return step new startTime in Instant format. - */ - public static Instant getStepStartTime(@Nullable String scenarioUniqueId, Map stepStartTimeMap, - boolean useMicroseconds) { - Instant currentStepStartTime = Instant.now().truncatedTo(ChronoUnit.MICROS); - if (scenarioUniqueId == null || stepStartTimeMap.isEmpty()) { - stepStartTimeMap.put(scenarioUniqueId, currentStepStartTime); - return currentStepStartTime; - } - Instant lastStepStartTime = stepStartTimeMap.get(scenarioUniqueId); - if (lastStepStartTime == null) { - stepStartTimeMap.put(scenarioUniqueId, currentStepStartTime); - return currentStepStartTime; - } - if (useMicroseconds) { - if (lastStepStartTime.compareTo(currentStepStartTime) >= 0) { - currentStepStartTime = lastStepStartTime.plus(1, ChronoUnit.MICROS); - } - } else { - if (lastStepStartTime.truncatedTo(ChronoUnit.MILLIS).compareTo(currentStepStartTime.truncatedTo(ChronoUnit.MILLIS)) >= 0) { - currentStepStartTime = lastStepStartTime.plus(1, ChronoUnit.MILLIS); - } - } - stepStartTimeMap.put(scenarioUniqueId, currentStepStartTime); - return currentStepStartTime; - } } diff --git a/src/test/java/com/epam/reportportal/karate/KarateTest.java b/src/test/java/com/epam/reportportal/karate/KarateTest.java deleted file mode 100644 index dc64830..0000000 --- a/src/test/java/com/epam/reportportal/karate/KarateTest.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2024 EPAM Systems - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.epam.reportportal.karate; - -import com.intuit.karate.Results; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -class KarateTest { - @Test - void testParallel() { - Results results = KarateReportPortalRunner.path("classpath:feature") - .outputCucumberJson(true) - .tags("~@ignore", "@To_run") - .parallel(2); - assertEquals(0, results.getFailCount()); - assertEquals(0, results.getErrors().size()); - assertTrue(results.getSuite().parallel); - assertEquals(2, results.getScenariosTotal()); - } -} \ No newline at end of file diff --git a/src/test/java/com/epam/reportportal/karate/ReportPortalPublisherTest.java b/src/test/java/com/epam/reportportal/karate/ReportPortalPublisherTest.java deleted file mode 100644 index 8054d95..0000000 --- a/src/test/java/com/epam/reportportal/karate/ReportPortalPublisherTest.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2024 EPAM Systems - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.epam.reportportal.karate; - -import com.epam.reportportal.karate.utils.ReflectUtils; -import com.epam.reportportal.listeners.ListenerParameters; -import com.epam.reportportal.service.Launch; -import com.epam.ta.reportportal.ws.model.FinishExecutionRQ; -import com.epam.ta.reportportal.ws.model.FinishTestItemRQ; -import com.epam.ta.reportportal.ws.model.StartTestItemRQ; -import com.intuit.karate.core.Feature; -import com.intuit.karate.core.FeatureResult; -import com.intuit.karate.resource.Resource; -import io.reactivex.Maybe; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.concurrent.ConcurrentHashMap; - -import static org.mockito.Mockito.*; - -@ExtendWith(MockitoExtension.class) -public class ReportPortalPublisherTest { - @Mock - Launch launchMock; - private ReportPortalPublisher reportPortalPublisher; - - @BeforeEach - public void setUp() { - reportPortalPublisher = new ReportPortalPublisher(() -> launchMock); - } - - @Test - public void shouldStartLaunch() { - reportPortalPublisher.startLaunch(); - verify(launchMock, times(1)).start(); - } - - @Test - public void shouldFinishLaunch() { - when(launchMock.getParameters()).thenReturn(getListenerParameters()); - when(launchMock.getLaunch()).thenReturn(Maybe.just("launchUuid")); - reportPortalPublisher.finishLaunch(); - verify(launchMock, times(1)).finish(any(FinishExecutionRQ.class)); - } - - @SuppressWarnings("unchecked") - @Test - public void shouldStartFeature() throws URISyntaxException { - FeatureResult featureResult = mock(FeatureResult.class); - Feature feature = mock(Feature.class); - Resource resource = mock(Resource.class); - when(featureResult.getFeature()).thenReturn(feature); - when(featureResult.getCallNameForReport()).thenReturn("featureName"); - when(feature.getResource()).thenReturn(resource); - when(resource.getUri()).thenReturn(new URI("file:///feature/simple.feature")); - when(launchMock.startTestItem(any(StartTestItemRQ.class))).thenReturn(mock(Maybe.class)); - reportPortalPublisher.startFeature(featureResult); - verify(launchMock, times(1)).startTestItem(any(StartTestItemRQ.class)); - } - - @SuppressWarnings("unchecked") - @Test - public void shouldFinishFeature() throws NoSuchFieldException { - FeatureResult featureResult = mock(FeatureResult.class); - when(featureResult.getCallNameForReport()).thenReturn("featureName"); - ConcurrentHashMap> featureIdMap = new ConcurrentHashMap<>(); - featureIdMap.put("featureName", mock(Maybe.class)); - ReflectUtils.setField(reportPortalPublisher, ReportPortalPublisher.class.getDeclaredField("featureIdMap"), featureIdMap); - reportPortalPublisher.finishFeature(featureResult); - verify(launchMock, times(1)).finishTestItem(any(Maybe.class), any(FinishTestItemRQ.class)); - } - - private ListenerParameters getListenerParameters() { - ListenerParameters parameters = new ListenerParameters(); - parameters.setLaunchName("launch"); - parameters.setBaseUrl("url"); - parameters.setProjectName("project"); - System.setProperty("rp.launch.id", "launchId"); - return parameters; - } -} diff --git a/src/test/java/com/epam/reportportal/karate/attributes/DifferentAttributesTest.java b/src/test/java/com/epam/reportportal/karate/attributes/DifferentAttributesTest.java index aa0573b..fa29589 100644 --- a/src/test/java/com/epam/reportportal/karate/attributes/DifferentAttributesTest.java +++ b/src/test/java/com/epam/reportportal/karate/attributes/DifferentAttributesTest.java @@ -22,7 +22,7 @@ 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 com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import org.apache.commons.lang3.tuple.Pair; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; @@ -58,13 +58,13 @@ public void setupMock() { @ParameterizedTest @ValueSource(booleans = { true, false }) public void test_different_attributes(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); verify(client, times(1)).startTestItem(captor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/attributes/LaunchAttributesTest.java b/src/test/java/com/epam/reportportal/karate/attributes/LaunchAttributesTest.java index c419888..7185593 100644 --- a/src/test/java/com/epam/reportportal/karate/attributes/LaunchAttributesTest.java +++ b/src/test/java/com/epam/reportportal/karate/attributes/LaunchAttributesTest.java @@ -23,7 +23,7 @@ import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.attribute.ItemAttributesRQ; import com.epam.ta.reportportal.ws.model.launch.StartLaunchRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -63,13 +63,13 @@ public void setupMock() { @ParameterizedTest @ValueSource(booleans = { true, false }) public void verify_start_launch_request_contains_launch_attributes(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor startCaptor = ArgumentCaptor.forClass(StartLaunchRQ.class); verify(client).startLaunch(startCaptor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/attributes/NoAttributesTest.java b/src/test/java/com/epam/reportportal/karate/attributes/NoAttributesTest.java index 9ae4a8b..f1d1bb4 100644 --- a/src/test/java/com/epam/reportportal/karate/attributes/NoAttributesTest.java +++ b/src/test/java/com/epam/reportportal/karate/attributes/NoAttributesTest.java @@ -21,7 +21,7 @@ import com.epam.reportportal.service.ReportPortalClient; import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.StartTestItemRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -55,13 +55,13 @@ public void setupMock() { @ParameterizedTest @ValueSource(booleans = { true, false }) public void test_different_attributes(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); verify(client, times(1)).startTestItem(captor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/attributes/SystemAttributesTest.java b/src/test/java/com/epam/reportportal/karate/attributes/SystemAttributesTest.java index 23664a9..c8a3431 100644 --- a/src/test/java/com/epam/reportportal/karate/attributes/SystemAttributesTest.java +++ b/src/test/java/com/epam/reportportal/karate/attributes/SystemAttributesTest.java @@ -22,7 +22,7 @@ import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.attribute.ItemAttributesRQ; import com.epam.ta.reportportal.ws.model.launch.StartLaunchRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -57,13 +57,13 @@ public void setupMock() { @ParameterizedTest @ValueSource(booleans = { true, false }) public void verify_start_launch_request_contains_system_attributes(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor startCaptor = ArgumentCaptor.forClass(StartLaunchRQ.class); verify(client).startLaunch(startCaptor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/background/BackgroundExamplesTest.java b/src/test/java/com/epam/reportportal/karate/background/BackgroundExamplesTest.java index df30ea9..332097e 100644 --- a/src/test/java/com/epam/reportportal/karate/background/BackgroundExamplesTest.java +++ b/src/test/java/com/epam/reportportal/karate/background/BackgroundExamplesTest.java @@ -22,8 +22,8 @@ import com.epam.reportportal.service.ReportPortalClient; import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.StartTestItemRQ; -import com.intuit.karate.Results; -import com.intuit.karate.core.Background; +import io.karatelabs.core.SuiteResult; +import io.karatelabs.gherkin.Background; import org.apache.commons.lang3.tuple.Pair; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; @@ -68,13 +68,13 @@ public void setupMock() { @ParameterizedTest @ValueSource(booleans = { true, false }) public void test_background_steps(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); verify(client).startTestItem(captor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/background/BackgroundTest.java b/src/test/java/com/epam/reportportal/karate/background/BackgroundTest.java index 6a6aaac..cbd116a 100644 --- a/src/test/java/com/epam/reportportal/karate/background/BackgroundTest.java +++ b/src/test/java/com/epam/reportportal/karate/background/BackgroundTest.java @@ -22,8 +22,8 @@ import com.epam.reportportal.service.ReportPortalClient; import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.StartTestItemRQ; -import com.intuit.karate.Results; -import com.intuit.karate.core.Background; +import io.karatelabs.core.SuiteResult; +import io.karatelabs.gherkin.Background; import org.apache.commons.lang3.tuple.Pair; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; @@ -63,13 +63,13 @@ public void setupMock() { @ParameterizedTest @ValueSource(booleans = { true, false }) public void test_background_steps(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); verify(client).startTestItem(captor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/background/BackgroundTwoStepsTest.java b/src/test/java/com/epam/reportportal/karate/background/BackgroundTwoStepsTest.java index 67bd971..5fcd55e 100644 --- a/src/test/java/com/epam/reportportal/karate/background/BackgroundTwoStepsTest.java +++ b/src/test/java/com/epam/reportportal/karate/background/BackgroundTwoStepsTest.java @@ -22,8 +22,8 @@ import com.epam.reportportal.service.ReportPortalClient; import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.StartTestItemRQ; -import com.intuit.karate.Results; -import com.intuit.karate.core.Background; +import io.karatelabs.core.SuiteResult; +import io.karatelabs.gherkin.Background; import org.apache.commons.lang3.tuple.Pair; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; @@ -65,13 +65,13 @@ public void setupMock() { @ParameterizedTest @ValueSource(booleans = { true, false }) public void test_background_steps(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); verify(client).startTestItem(captor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/call/CallTheSameFeatureWithParametersHookTest.java b/src/test/java/com/epam/reportportal/karate/call/CallTheSameFeatureWithParametersHookTest.java index 220bce7..420de96 100644 --- a/src/test/java/com/epam/reportportal/karate/call/CallTheSameFeatureWithParametersHookTest.java +++ b/src/test/java/com/epam/reportportal/karate/call/CallTheSameFeatureWithParametersHookTest.java @@ -21,7 +21,7 @@ import com.epam.reportportal.service.ReportPortalClient; import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.StartTestItemRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import org.apache.commons.lang3.tuple.Pair; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -81,8 +81,8 @@ public void setupMock() { @Test @Timeout(value = 30, threadMode = Timeout.ThreadMode.SEPARATE_THREAD) public void test_call_feature_with_parameters_hook_reporting() { - Results results = TestUtils.runAsHook(rp, TEST_FEATURE); - assertThat(results.getFailCount(), equalTo(0)); + SuiteResult results = TestUtils.runAsEventListener(rp, TEST_FEATURE); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor featureCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); verify(client, times(1)).startTestItem(featureCaptor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/call/CallWithParametersHookTest.java b/src/test/java/com/epam/reportportal/karate/call/CallWithParametersHookTest.java index 44975a6..5164967 100644 --- a/src/test/java/com/epam/reportportal/karate/call/CallWithParametersHookTest.java +++ b/src/test/java/com/epam/reportportal/karate/call/CallWithParametersHookTest.java @@ -22,7 +22,7 @@ import com.epam.reportportal.util.test.CommonUtils; import com.epam.reportportal.utils.formatting.MarkdownUtils; import com.epam.ta.reportportal.ws.model.StartTestItemRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import org.apache.commons.lang3.tuple.Pair; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -82,8 +82,8 @@ public void setupMock() { @Test public void test_call_feature_with_parameters_hook_reporting() { - Results results = TestUtils.runAsHook(rp, TEST_FEATURE); - assertThat(results.getFailCount(), equalTo(0)); + SuiteResult results = TestUtils.runAsEventListener(rp, TEST_FEATURE); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor featureCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); verify(client, times(1)).startTestItem(featureCaptor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/call/CallWithParametersPublisherTest.java b/src/test/java/com/epam/reportportal/karate/call/CallWithParametersPublisherTest.java index 60ffd5b..8ec2754 100644 --- a/src/test/java/com/epam/reportportal/karate/call/CallWithParametersPublisherTest.java +++ b/src/test/java/com/epam/reportportal/karate/call/CallWithParametersPublisherTest.java @@ -21,7 +21,7 @@ import com.epam.reportportal.service.ReportPortalClient; import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.StartTestItemRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; @@ -52,8 +52,8 @@ public void setupMock() { @Test public void test_call_feature_with_parameters_publisher_reporting() { - Results results = TestUtils.runAsReport(rp, TEST_FEATURE); - assertThat(results.getFailCount(), equalTo(0)); + SuiteResult results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); verify(client).startTestItem(captor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/coderef/ExamplesCodeRefTest.java b/src/test/java/com/epam/reportportal/karate/coderef/ExamplesCodeRefTest.java index 0975f38..49b1cc6 100644 --- a/src/test/java/com/epam/reportportal/karate/coderef/ExamplesCodeRefTest.java +++ b/src/test/java/com/epam/reportportal/karate/coderef/ExamplesCodeRefTest.java @@ -22,7 +22,7 @@ import com.epam.reportportal.service.ReportPortalClient; import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.StartTestItemRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import org.apache.commons.lang3.tuple.Pair; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; @@ -61,13 +61,13 @@ public void setupMock() { @ParameterizedTest @ValueSource(booleans = { true, false }) public void test_examples_code_reference(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor featureCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); verify(client, times(1)).startTestItem(featureCaptor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/coderef/ScenarioCodeRefTest.java b/src/test/java/com/epam/reportportal/karate/coderef/ScenarioCodeRefTest.java index 4285363..569e3d6 100644 --- a/src/test/java/com/epam/reportportal/karate/coderef/ScenarioCodeRefTest.java +++ b/src/test/java/com/epam/reportportal/karate/coderef/ScenarioCodeRefTest.java @@ -22,7 +22,7 @@ import com.epam.reportportal.service.ReportPortalClient; import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.StartTestItemRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -56,13 +56,13 @@ public void setupMock() { @ParameterizedTest @ValueSource(booleans = { true, false }) public void test_scenario_code_reference(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor featureCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); verify(client).startTestItem(featureCaptor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/description/DescriptionExamplesTest.java b/src/test/java/com/epam/reportportal/karate/description/DescriptionExamplesTest.java index d7ca77b..bde75d8 100644 --- a/src/test/java/com/epam/reportportal/karate/description/DescriptionExamplesTest.java +++ b/src/test/java/com/epam/reportportal/karate/description/DescriptionExamplesTest.java @@ -22,7 +22,7 @@ import com.epam.reportportal.service.ReportPortalClient; import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.StartTestItemRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import org.apache.commons.lang3.tuple.Pair; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; @@ -68,13 +68,13 @@ public void setupMock() { @ParameterizedTest @ValueSource(booleans = { true, false }) public void test_examples_description(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor featureCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); verify(client, times(1)).startTestItem(featureCaptor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/description/LaunchDescriptionTest.java b/src/test/java/com/epam/reportportal/karate/description/LaunchDescriptionTest.java index b71479d..267ac38 100644 --- a/src/test/java/com/epam/reportportal/karate/description/LaunchDescriptionTest.java +++ b/src/test/java/com/epam/reportportal/karate/description/LaunchDescriptionTest.java @@ -22,7 +22,7 @@ import com.epam.reportportal.service.ReportPortalClient; import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.launch.StartLaunchRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -60,13 +60,13 @@ public void setupMock() { @ParameterizedTest @ValueSource(booleans = { true, false }) public void verify_start_launch_request_contains_launch_description(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor startCaptor = ArgumentCaptor.forClass(StartLaunchRQ.class); verify(client).startLaunch(startCaptor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/description/NoDescriptionExamplesTest.java b/src/test/java/com/epam/reportportal/karate/description/NoDescriptionExamplesTest.java index 55cf9a7..7871452 100644 --- a/src/test/java/com/epam/reportportal/karate/description/NoDescriptionExamplesTest.java +++ b/src/test/java/com/epam/reportportal/karate/description/NoDescriptionExamplesTest.java @@ -22,7 +22,7 @@ import com.epam.reportportal.util.test.CommonUtils; import com.epam.reportportal.utils.formatting.MarkdownUtils; import com.epam.ta.reportportal.ws.model.StartTestItemRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import org.apache.commons.lang3.tuple.Pair; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; @@ -63,13 +63,13 @@ public void setupMock() { @ParameterizedTest @ValueSource(booleans = { true, false }) public void test_examples_no_description(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor featureCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); verify(client, times(1)).startTestItem(featureCaptor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/description/NoDescriptionTest.java b/src/test/java/com/epam/reportportal/karate/description/NoDescriptionTest.java index 6effb32..c15db02 100644 --- a/src/test/java/com/epam/reportportal/karate/description/NoDescriptionTest.java +++ b/src/test/java/com/epam/reportportal/karate/description/NoDescriptionTest.java @@ -21,7 +21,7 @@ import com.epam.reportportal.service.ReportPortalClient; import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.StartTestItemRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -56,13 +56,13 @@ public void setupMock() { @ParameterizedTest @ValueSource(booleans = { true, false }) public void test_description_for_all_possible_items(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor featureCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); verify(client).startTestItem(featureCaptor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/description/NoLaunchDescriptionTest.java b/src/test/java/com/epam/reportportal/karate/description/NoLaunchDescriptionTest.java index f54dab8..487fe31 100644 --- a/src/test/java/com/epam/reportportal/karate/description/NoLaunchDescriptionTest.java +++ b/src/test/java/com/epam/reportportal/karate/description/NoLaunchDescriptionTest.java @@ -22,7 +22,7 @@ import com.epam.reportportal.service.ReportPortalClient; import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.launch.StartLaunchRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -66,13 +66,13 @@ public void verify_start_launch_request_contains_no_launch_description(boolean r ListenerParameters parameters = standardParameters(); parameters.setDescription(description); ReportPortal rp = ReportPortal.create(client, parameters, testExecutor()); - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor startCaptor = ArgumentCaptor.forClass(StartLaunchRQ.class); verify(client).startLaunch(startCaptor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogTest.java b/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogTest.java index 13f9eff..9032ebf 100644 --- a/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogTest.java +++ b/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogTest.java @@ -23,7 +23,7 @@ import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.FinishTestItemRQ; import com.epam.ta.reportportal.ws.model.log.SaveLogRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import okhttp3.MultipartBody; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; @@ -62,13 +62,13 @@ public void setupMock() { @ParameterizedTest @ValueSource(booleans = { true, false }) public void test_error_log_in_description(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(1)); + assertThat(results.getFeatureFailedCount(), equalTo(1)); @SuppressWarnings("unchecked") ArgumentCaptor> logCaptor = ArgumentCaptor.forClass(List.class); diff --git a/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithDescriptionAndExamplesTest.java b/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithDescriptionAndExamplesTest.java index 189c7af..e0d0b75 100644 --- a/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithDescriptionAndExamplesTest.java +++ b/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithDescriptionAndExamplesTest.java @@ -25,7 +25,7 @@ import com.epam.reportportal.utils.formatting.MarkdownUtils; import com.epam.ta.reportportal.ws.model.FinishTestItemRQ; import com.epam.ta.reportportal.ws.model.log.SaveLogRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import okhttp3.MultipartBody; import org.apache.commons.lang3.tuple.Pair; import org.junit.jupiter.api.BeforeEach; @@ -90,15 +90,15 @@ public void setupMock() { @ParameterizedTest @ValueSource(booleans = { true, false }) public void test_error_log_and_examples_in_description(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(1)); + assertThat(results.getFeatureFailedCount(), equalTo(1)); @SuppressWarnings("unchecked") ArgumentCaptor> logCaptor = ArgumentCaptor.forClass(List.class); diff --git a/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithDescriptionTest.java b/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithDescriptionTest.java index 3b39320..8635698 100644 --- a/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithDescriptionTest.java +++ b/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithDescriptionTest.java @@ -23,7 +23,7 @@ import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.FinishTestItemRQ; import com.epam.ta.reportportal.ws.model.log.SaveLogRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import okhttp3.MultipartBody; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; @@ -69,13 +69,13 @@ public void setupMock() { @ParameterizedTest @ValueSource(booleans = { true, false }) public void test_error_log_and_description_in_description(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(1)); + assertThat(results.getFeatureFailedCount(), equalTo(1)); @SuppressWarnings("unchecked") ArgumentCaptor> logCaptor = ArgumentCaptor.forClass(List.class); diff --git a/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithExamplesTest.java b/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithExamplesTest.java index 8cd7503..5c4ef96 100644 --- a/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithExamplesTest.java +++ b/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithExamplesTest.java @@ -25,7 +25,7 @@ import com.epam.reportportal.utils.formatting.MarkdownUtils; import com.epam.ta.reportportal.ws.model.FinishTestItemRQ; import com.epam.ta.reportportal.ws.model.log.SaveLogRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import okhttp3.MultipartBody; import org.apache.commons.lang3.tuple.Pair; import org.junit.jupiter.api.BeforeEach; @@ -82,15 +82,15 @@ public void setupMock() { @ParameterizedTest @ValueSource(booleans = { true, false }) public void test_error_log_and_examples_in_description(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(1)); + assertThat(results.getFeatureFailedCount(), equalTo(1)); @SuppressWarnings("unchecked") ArgumentCaptor> logCaptor = ArgumentCaptor.forClass(List.class); diff --git a/src/test/java/com/epam/reportportal/karate/description/SimpleDescriptionTest.java b/src/test/java/com/epam/reportportal/karate/description/SimpleDescriptionTest.java index f328579..acdffe9 100644 --- a/src/test/java/com/epam/reportportal/karate/description/SimpleDescriptionTest.java +++ b/src/test/java/com/epam/reportportal/karate/description/SimpleDescriptionTest.java @@ -21,8 +21,8 @@ import com.epam.reportportal.service.ReportPortalClient; import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.StartTestItemRQ; -import com.intuit.karate.Results; -import com.intuit.karate.core.Background; +import io.karatelabs.core.SuiteResult; +import io.karatelabs.gherkin.Background; import org.apache.commons.lang3.tuple.Pair; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; @@ -62,13 +62,13 @@ public void setupMock() { @ParameterizedTest @ValueSource(booleans = { true, false }) public void test_description_for_all_possible_items(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor featureCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); verify(client).startTestItem(featureCaptor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/id/ExamplesTestCaseIdTest.java b/src/test/java/com/epam/reportportal/karate/id/ExamplesTestCaseIdTest.java index 0da55a9..fbea9d7 100644 --- a/src/test/java/com/epam/reportportal/karate/id/ExamplesTestCaseIdTest.java +++ b/src/test/java/com/epam/reportportal/karate/id/ExamplesTestCaseIdTest.java @@ -21,7 +21,7 @@ import com.epam.reportportal.service.ReportPortalClient; import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.StartTestItemRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import org.apache.commons.lang3.tuple.Pair; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; @@ -60,13 +60,13 @@ public void setupMock() { @ParameterizedTest @ValueSource(booleans = { true, false }) public void test_examples_test_case_id(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); verify(client, times(1)).startTestItem(captor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/id/ScenarioTestCaseIdTest.java b/src/test/java/com/epam/reportportal/karate/id/ScenarioTestCaseIdTest.java index 9084271..0c7ec04 100644 --- a/src/test/java/com/epam/reportportal/karate/id/ScenarioTestCaseIdTest.java +++ b/src/test/java/com/epam/reportportal/karate/id/ScenarioTestCaseIdTest.java @@ -21,7 +21,7 @@ import com.epam.reportportal.service.ReportPortalClient; import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.StartTestItemRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -55,13 +55,13 @@ public void setupMock() { @ParameterizedTest @ValueSource(booleans = { true, false }) public void test_test_case_id(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); verify(client, times(1)).startTestItem(captor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/launch/LaunchRequiredFieldsTest.java b/src/test/java/com/epam/reportportal/karate/launch/LaunchRequiredFieldsTest.java index 3e37dcb..3c601d4 100644 --- a/src/test/java/com/epam/reportportal/karate/launch/LaunchRequiredFieldsTest.java +++ b/src/test/java/com/epam/reportportal/karate/launch/LaunchRequiredFieldsTest.java @@ -21,7 +21,7 @@ import com.epam.reportportal.service.ReportPortalClient; import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.launch.StartLaunchRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -57,13 +57,13 @@ public void setupMock() { @ParameterizedTest @ValueSource(booleans = { true, false }) public void verify_start_launch_request_contains_required_fields(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor startCaptor = ArgumentCaptor.forClass(StartLaunchRQ.class); verify(client).startLaunch(startCaptor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/logging/EmbedLoggingTest.java b/src/test/java/com/epam/reportportal/karate/logging/EmbedLoggingTest.java index bd2cb58..2e23562 100644 --- a/src/test/java/com/epam/reportportal/karate/logging/EmbedLoggingTest.java +++ b/src/test/java/com/epam/reportportal/karate/logging/EmbedLoggingTest.java @@ -22,7 +22,7 @@ import com.epam.reportportal.service.ReportPortalClient; import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.log.SaveLogRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import okhttp3.MultipartBody; import org.apache.commons.lang3.tuple.Pair; import org.junit.jupiter.api.BeforeEach; @@ -59,13 +59,13 @@ public void setupMock() { @ValueSource(booleans = { true, false }) @SuppressWarnings({ "unchecked", "rawtypes" }) public void test_embed_image_attachment(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor logCaptor = ArgumentCaptor.forClass(List.class); verify(client).log(logCaptor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/logging/HttpRequestLoggingTest.java b/src/test/java/com/epam/reportportal/karate/logging/HttpRequestLoggingTest.java index 7079575..4664a40 100644 --- a/src/test/java/com/epam/reportportal/karate/logging/HttpRequestLoggingTest.java +++ b/src/test/java/com/epam/reportportal/karate/logging/HttpRequestLoggingTest.java @@ -22,7 +22,7 @@ import com.epam.reportportal.service.ReportPortalClient; import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.log.SaveLogRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import okhttp3.MultipartBody; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; @@ -58,13 +58,13 @@ public void setupMock() { @ValueSource(booleans = { true, false }) @SuppressWarnings({ "unchecked", "rawtypes" }) public void test_http_request_logging(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(1)); + assertThat(results.getFeatureFailedCount(), equalTo(1)); ArgumentCaptor logCaptor = ArgumentCaptor.forClass(List.class); verify(client, atLeastOnce()).log(logCaptor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/logging/SimpleFailureLoggingTest.java b/src/test/java/com/epam/reportportal/karate/logging/SimpleFailureLoggingTest.java index 7699d95..673d25e 100644 --- a/src/test/java/com/epam/reportportal/karate/logging/SimpleFailureLoggingTest.java +++ b/src/test/java/com/epam/reportportal/karate/logging/SimpleFailureLoggingTest.java @@ -22,7 +22,7 @@ import com.epam.reportportal.service.ReportPortalClient; import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.log.SaveLogRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import okhttp3.MultipartBody; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; @@ -58,13 +58,13 @@ public void setupMock() { @ValueSource(booleans = { true, false }) @SuppressWarnings({ "unchecked", "rawtypes" }) public void test_simple_one_step_failed_error_log(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(1)); + assertThat(results.getFeatureFailedCount(), equalTo(1)); ArgumentCaptor logCaptor = ArgumentCaptor.forClass(List.class); verify(client, atLeastOnce()).log(logCaptor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/name/NoFeatureNameTest.java b/src/test/java/com/epam/reportportal/karate/name/NoFeatureNameTest.java index 71ead9c..89696c5 100644 --- a/src/test/java/com/epam/reportportal/karate/name/NoFeatureNameTest.java +++ b/src/test/java/com/epam/reportportal/karate/name/NoFeatureNameTest.java @@ -21,7 +21,7 @@ import com.epam.reportportal.service.ReportPortalClient; import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.StartTestItemRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -53,13 +53,13 @@ public void setupMock() { @ParameterizedTest @ValueSource(booleans = { true, false }) public void test_item_names_simple(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_NO_NAME_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_NO_NAME_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_NO_NAME_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_NO_NAME_FEATURE); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor featureCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); verify(client, times(1)).startTestItem(featureCaptor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/name/SimpleItemNameTest.java b/src/test/java/com/epam/reportportal/karate/name/SimpleItemNameTest.java index fe90e95..b7a3b24 100644 --- a/src/test/java/com/epam/reportportal/karate/name/SimpleItemNameTest.java +++ b/src/test/java/com/epam/reportportal/karate/name/SimpleItemNameTest.java @@ -21,7 +21,7 @@ import com.epam.reportportal.service.ReportPortalClient; import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.StartTestItemRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -56,13 +56,13 @@ public void setupMock() { @ParameterizedTest @ValueSource(booleans = { true, false }) public void test_item_names_simple(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor featureCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); verify(client, times(1)).startTestItem(featureCaptor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/parameters/ExamplesScenarioParametersTest.java b/src/test/java/com/epam/reportportal/karate/parameters/ExamplesScenarioParametersTest.java index 9e779e1..812c36e 100644 --- a/src/test/java/com/epam/reportportal/karate/parameters/ExamplesScenarioParametersTest.java +++ b/src/test/java/com/epam/reportportal/karate/parameters/ExamplesScenarioParametersTest.java @@ -22,7 +22,7 @@ import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.ParameterResource; import com.epam.ta.reportportal.ws.model.StartTestItemRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import org.apache.commons.lang3.tuple.Pair; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; @@ -59,13 +59,13 @@ public void setupMock() { @ParameterizedTest @ValueSource(booleans = { true, false }) public void test_examples_scenario_parameters(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); verify(client, times(1)).startTestItem(captor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/parameters/ExamplesStepParametersTest.java b/src/test/java/com/epam/reportportal/karate/parameters/ExamplesStepParametersTest.java index 030ee07..c961b8d 100644 --- a/src/test/java/com/epam/reportportal/karate/parameters/ExamplesStepParametersTest.java +++ b/src/test/java/com/epam/reportportal/karate/parameters/ExamplesStepParametersTest.java @@ -24,7 +24,7 @@ import com.epam.ta.reportportal.ws.model.ParameterResource; import com.epam.ta.reportportal.ws.model.StartTestItemRQ; import com.epam.ta.reportportal.ws.model.log.SaveLogRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import okhttp3.MultipartBody; import org.apache.commons.lang3.tuple.Pair; import org.junit.jupiter.api.BeforeEach; @@ -72,13 +72,13 @@ public void setupMock() { @ValueSource(booleans = { true, false }) @SuppressWarnings({ "unchecked", "rawtypes" }) public void test_examples_parameters_for_steps(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); verify(client).startTestItem(captor.capture()); @@ -112,7 +112,7 @@ public void test_examples_parameters_for_steps(boolean report) { .filter(rq -> LogLevel.INFO.name().equals(rq.getLevel())) .collect(Collectors.toMap(SaveLogRQ::getItemUuid, v -> v)); - List stepIdList = stepIds.stream().flatMap(e -> e.getValue().stream()).collect(Collectors.toList()); + List stepIdList = stepIds.stream().flatMap(e -> e.getValue().stream()).toList(); assertThat(logs.keySet(), hasSize(stepIdList.size())); stepIdList.forEach(id -> assertThat(logs, hasKey(id))); assertThat( diff --git a/src/test/java/com/epam/reportportal/karate/parameters/NoParametersTest.java b/src/test/java/com/epam/reportportal/karate/parameters/NoParametersTest.java index 715418b..e98814f 100644 --- a/src/test/java/com/epam/reportportal/karate/parameters/NoParametersTest.java +++ b/src/test/java/com/epam/reportportal/karate/parameters/NoParametersTest.java @@ -21,7 +21,7 @@ import com.epam.reportportal.service.ReportPortalClient; import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.StartTestItemRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -55,13 +55,13 @@ public void setupMock() { @ParameterizedTest @ValueSource(booleans = { true, false }) public void test_no_parameters_reporting(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); verify(client, times(1)).startTestItem(captor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/parameters/NullValueExamplesTest.java b/src/test/java/com/epam/reportportal/karate/parameters/NullValueExamplesTest.java index c535441..0267591 100644 --- a/src/test/java/com/epam/reportportal/karate/parameters/NullValueExamplesTest.java +++ b/src/test/java/com/epam/reportportal/karate/parameters/NullValueExamplesTest.java @@ -22,7 +22,7 @@ import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.ParameterResource; import com.epam.ta.reportportal.ws.model.StartTestItemRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import org.apache.commons.lang3.tuple.Pair; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; @@ -60,13 +60,13 @@ public void setupMock() { @ParameterizedTest @ValueSource(booleans = { true, false }) public void test_examples_null_value(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); verify(client, times(1)).startTestItem(captor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/parameters/TableParametersTest.java b/src/test/java/com/epam/reportportal/karate/parameters/TableParametersTest.java index 47c32c3..e0fb7c2 100644 --- a/src/test/java/com/epam/reportportal/karate/parameters/TableParametersTest.java +++ b/src/test/java/com/epam/reportportal/karate/parameters/TableParametersTest.java @@ -23,7 +23,7 @@ import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.StartTestItemRQ; import com.epam.ta.reportportal.ws.model.log.SaveLogRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import okhttp3.MultipartBody; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; @@ -60,13 +60,13 @@ public void setupMock() { @ValueSource(booleans = { true, false }) @SuppressWarnings({ "unchecked", "rawtypes" }) public void test_table_parameters_reporting(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); verify(client, times(1)).startTestItem(captor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/retry/RetryFailedTest.java b/src/test/java/com/epam/reportportal/karate/retry/RetryFailedTest.java deleted file mode 100644 index 0ecfec6..0000000 --- a/src/test/java/com/epam/reportportal/karate/retry/RetryFailedTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2024 EPAM Systems - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.epam.reportportal.karate.retry; - -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.FinishTestItemRQ; -import com.epam.ta.reportportal.ws.model.StartTestItemRQ; -import com.intuit.karate.Results; -import com.intuit.karate.core.ScenarioResult; -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.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.Mockito.*; -import static org.mockito.Mockito.any; - -public class RetryFailedTest { - private static final String TEST_FEATURE = "classpath:feature/simple_failed.feature"; - private final String launchUuid = CommonUtils.namedId("launch_"); - private final String featureId = CommonUtils.namedId("feature_"); - private final List scenarioIds = Stream.generate(() -> CommonUtils.namedId("scenario_")).limit(2).collect(Collectors.toList()); - private final List stepIds = Stream.generate(() -> CommonUtils.namedId("step_")).limit(6).collect(Collectors.toList()); - - private final List>> scenarioSteps = Stream.of( - Pair.of(scenarioIds.get(0), stepIds.subList(0, 3)), - Pair.of(scenarioIds.get(1), stepIds.subList(3, 6)) - ) - .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, launchUuid, featureId, scenarioSteps); - mockBatchLogging(client); - } - - @Test - public void test_simple_one_step_failed_retry() { - Results results = TestUtils.runAsHook(rp, TEST_FEATURE); - assertThat(results.getFailCount(), equalTo(1)); - - List failedResults = results.getScenarioResults().filter(ScenarioResult::isFailed).collect(Collectors.toList()); - assertThat(failedResults, hasSize(1)); - - results.getSuite().retryScenario(failedResults.get(0).getScenario()); - - verify(client).startTestItem(any(StartTestItemRQ.class)); - ArgumentCaptor scenarioStartCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); - verify(client, times(2)).startTestItem(same(featureId), scenarioStartCaptor.capture()); - - verify(client).finishTestItem(same(featureId), any(FinishTestItemRQ.class)); - ArgumentCaptor scenarioCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); - verify(client).finishTestItem(same(scenarioIds.get(0)), scenarioCaptor.capture()); - verify(client).finishTestItem(same(scenarioIds.get(1)), scenarioCaptor.capture()); - - assertThat(scenarioStartCaptor.getAllValues().get(0).isRetry(), anyOf(equalTo(false), nullValue())); - assertThat(scenarioStartCaptor.getAllValues().get(1).isRetry(), equalTo(true)); - assertThat(scenarioStartCaptor.getAllValues().get(1).getRetryOf(), equalTo(scenarioIds.get(0))); - } -} diff --git a/src/test/java/com/epam/reportportal/karate/status/OneExampleFailedTest.java b/src/test/java/com/epam/reportportal/karate/status/OneExampleFailedTest.java index 65c5c2b..60ac93f 100644 --- a/src/test/java/com/epam/reportportal/karate/status/OneExampleFailedTest.java +++ b/src/test/java/com/epam/reportportal/karate/status/OneExampleFailedTest.java @@ -22,7 +22,7 @@ import com.epam.reportportal.service.ReportPortalClient; import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.FinishTestItemRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import org.apache.commons.lang3.tuple.Pair; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; @@ -69,13 +69,13 @@ private static void verifyStatus(List rqs, ItemStatus... statu @ParameterizedTest @ValueSource(booleans = { true, false }) public void test_simple_one_step_failed(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(1)); + assertThat(results.getFeatureFailedCount(), equalTo(1)); ArgumentCaptor featureCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); verify(client).finishTestItem(same(featureId), featureCaptor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/status/OneExampleWithBackgroundFailedTest.java b/src/test/java/com/epam/reportportal/karate/status/OneExampleWithBackgroundFailedTest.java index e066b6d..62af211 100644 --- a/src/test/java/com/epam/reportportal/karate/status/OneExampleWithBackgroundFailedTest.java +++ b/src/test/java/com/epam/reportportal/karate/status/OneExampleWithBackgroundFailedTest.java @@ -23,7 +23,7 @@ import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.FinishExecutionRQ; import com.epam.ta.reportportal.ws.model.FinishTestItemRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import org.apache.commons.lang3.tuple.Pair; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; @@ -82,13 +82,13 @@ private static void verifyStatus(List rqs, ItemStatus... statu @ParameterizedTest @ValueSource(booleans = { true, false }) public void test_simple_one_step_failed(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(1)); + assertThat(results.getFeatureFailedCount(), equalTo(1)); ArgumentCaptor featureCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); verify(client).finishTestItem(same(featureId), featureCaptor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/status/SimpleAllPassedTest.java b/src/test/java/com/epam/reportportal/karate/status/SimpleAllPassedTest.java index 0174ece..9aa6943 100644 --- a/src/test/java/com/epam/reportportal/karate/status/SimpleAllPassedTest.java +++ b/src/test/java/com/epam/reportportal/karate/status/SimpleAllPassedTest.java @@ -22,7 +22,7 @@ import com.epam.reportportal.service.ReportPortalClient; import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.FinishTestItemRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -57,13 +57,13 @@ public void setupMock() { @ParameterizedTest @ValueSource(booleans = { true, false }) public void test_simple_all_passed(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor featureCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); verify(client).finishTestItem(same(featureId), featureCaptor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/status/SimpleOneStepFailedTest.java b/src/test/java/com/epam/reportportal/karate/status/SimpleOneStepFailedTest.java index 5b82026..fbd9420 100644 --- a/src/test/java/com/epam/reportportal/karate/status/SimpleOneStepFailedTest.java +++ b/src/test/java/com/epam/reportportal/karate/status/SimpleOneStepFailedTest.java @@ -23,7 +23,7 @@ import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.FinishExecutionRQ; import com.epam.ta.reportportal.ws.model.FinishTestItemRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -58,13 +58,13 @@ public void setupMock() { @ParameterizedTest @ValueSource(booleans = { true, false }) public void test_simple_one_step_failed(boolean report) { - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(1)); + assertThat(results.getFeatureFailedCount(), equalTo(1)); ArgumentCaptor featureCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); verify(client).finishTestItem(same(featureId), featureCaptor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/tags/SimpleTagInclusionTest.java b/src/test/java/com/epam/reportportal/karate/tags/SimpleTagInclusionTest.java index 48e7b7d..96fd67e 100644 --- a/src/test/java/com/epam/reportportal/karate/tags/SimpleTagInclusionTest.java +++ b/src/test/java/com/epam/reportportal/karate/tags/SimpleTagInclusionTest.java @@ -23,7 +23,7 @@ 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.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -61,13 +61,13 @@ public void setupMock() { @ValueSource(booleans = { true, false }) public void test_simple_all_passed(boolean report) { List tagsToRun = Collections.singletonList("scope=smoke"); - Results results; + SuiteResult results; if (report) { - results = TestUtils.runAsReport(rp, tagsToRun, TEST_FEATURES); + results = TestUtils.runAsReportListener(rp, tagsToRun, TEST_FEATURES); } else { - results = TestUtils.runAsHook(rp, tagsToRun, TEST_FEATURES); + results = TestUtils.runAsEventListener(rp, tagsToRun, TEST_FEATURES); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor featureCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class); verify(client).startTestItem(featureCaptor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/timing/SimpleTimingTest.java b/src/test/java/com/epam/reportportal/karate/timing/SimpleTimingTest.java index c87e6d7..ce278ad 100644 --- a/src/test/java/com/epam/reportportal/karate/timing/SimpleTimingTest.java +++ b/src/test/java/com/epam/reportportal/karate/timing/SimpleTimingTest.java @@ -22,7 +22,7 @@ import com.epam.reportportal.util.test.CommonUtils; import com.epam.ta.reportportal.ws.model.StartTestItemRQ; import com.epam.ta.reportportal.ws.model.launch.StartLaunchRQ; -import com.intuit.karate.Results; +import io.karatelabs.core.SuiteResult; import io.reactivex.Maybe; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; @@ -68,19 +68,19 @@ public static Stream testCases() { @ParameterizedTest @MethodSource("testCases") public void test_each_item_has_correct_start_date(boolean report, boolean useMicroseconds) { - Results results; + SuiteResult results; if (report) { if (useMicroseconds) { when(client.getApiInfo()).thenReturn(Maybe.just(TestUtils.testApiInfo())); } - results = TestUtils.runAsReport(rp, TEST_FEATURE); + results = TestUtils.runAsReportListener(rp, TEST_FEATURE); } else { if (useMicroseconds) { when(client.getApiInfo()).thenReturn(Maybe.just(TestUtils.testApiInfo())); } - results = TestUtils.runAsHook(rp, TEST_FEATURE); + results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } - assertThat(results.getFailCount(), equalTo(0)); + assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor launchCaptor = ArgumentCaptor.forClass(StartLaunchRQ.class); verify(client).startLaunch(launchCaptor.capture()); diff --git a/src/test/java/com/epam/reportportal/karate/utils/ReflectUtils.java b/src/test/java/com/epam/reportportal/karate/utils/ReflectUtils.java deleted file mode 100644 index bb61de3..0000000 --- a/src/test/java/com/epam/reportportal/karate/utils/ReflectUtils.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2024 EPAM Systems - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.epam.reportportal.karate.utils; - -import java.lang.reflect.Field; - -public class ReflectUtils { - - private ReflectUtils() { - } - - public static void setField(Object object, Field fld, Object value) { - try { - fld.setAccessible(true); - fld.set(object, value); - } catch (IllegalAccessException e) { - String fieldName = fld.getName(); - throw new RuntimeException("Failed to set " + fieldName + " of object", e); - } - } -} diff --git a/src/test/java/com/epam/reportportal/karate/utils/TestUtils.java b/src/test/java/com/epam/reportportal/karate/utils/TestUtils.java index 311d46c..1acb112 100644 --- a/src/test/java/com/epam/reportportal/karate/utils/TestUtils.java +++ b/src/test/java/com/epam/reportportal/karate/utils/TestUtils.java @@ -16,8 +16,7 @@ package com.epam.reportportal.karate.utils; -import com.epam.reportportal.karate.KarateReportPortalRunner; -import com.epam.reportportal.karate.ReportPortalHook; +import com.epam.reportportal.karate.ReportPortalResultListener; import com.epam.reportportal.listeners.ListenerParameters; import com.epam.reportportal.service.LaunchImpl; import com.epam.reportportal.service.ReportPortal; @@ -32,8 +31,8 @@ import com.epam.ta.reportportal.ws.model.launch.StartLaunchRS; import com.epam.ta.reportportal.ws.model.log.SaveLogRQ; import com.fasterxml.jackson.core.type.TypeReference; -import com.intuit.karate.Results; -import com.intuit.karate.Runner; +import io.karatelabs.core.Runner; +import io.karatelabs.core.SuiteResult; import io.reactivex.Maybe; import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; @@ -68,24 +67,28 @@ public static ExecutorService testExecutor() { }); } - public static Results runAsReport(ReportPortal reportPortal, List tags, String... paths) { - return KarateReportPortalRunner.path(paths).withReportPortal(reportPortal).outputCucumberJson(false).tags(tags).parallel(1); + public static SuiteResult runAsReportListener(ReportPortal reportPortal, List tags, String... paths) { + ReportPortalResultListener listener = new ReportPortalResultListener(reportPortal); + Runner.Builder path = Runner.path(paths).resultListener(listener).outputCucumberJson(false); + SuiteResult result = path.tags(tags.toArray(new String[0])).parallel(1); + listener.finishLaunch(); + return result; } - public static Results runAsReport(ReportPortal reportPortal, String... paths) { - return runAsReport(reportPortal, Collections.emptyList(), paths); + public static SuiteResult runAsReportListener(ReportPortal reportPortal, String... paths) { + return runAsReportListener(reportPortal, Collections.emptyList(), paths); } - public static Results runAsHook(ReportPortal reportPortal, List tags, String... paths) { - ReportPortalHook hook = new ReportPortalHook(reportPortal); - Runner.Builder path = Runner.path(paths).hook(hook).outputCucumberJson(false); - Results result = path.tags(tags).parallel(1); - hook.finishLaunch(); + public static SuiteResult runAsEventListener(ReportPortal reportPortal, List tags, String... paths) { + ReportPortalResultListener listener = new ReportPortalResultListener(reportPortal); + Runner.Builder path = Runner.path(paths).resultListener(listener).outputCucumberJson(false); + SuiteResult result = path.tags(tags.toArray(new String[0])).parallel(1); + listener.finishLaunch(); return result; } - public static Results runAsHook(ReportPortal reportPortal, String... paths) { - return runAsHook(reportPortal, Collections.emptyList(), paths); + public static SuiteResult runAsEventListener(ReportPortal reportPortal, String... paths) { + return runAsEventListener(reportPortal, Collections.emptyList(), paths); } public static ListenerParameters standardParameters() { From 5363ea7da15e3da401f62a0d4fcb6d5ee131f766 Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Sat, 25 Apr 2026 14:16:59 +0300 Subject: [PATCH 03/19] Add launch start --- .../epam/reportportal/karate/ReportPortalResultListener.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java b/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java index ab716d0..bb31459 100644 --- a/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java +++ b/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java @@ -480,7 +480,8 @@ public void afterStep(StepResult stepResult, ScenarioResult sr) { @Override public void onSuiteStart(Suite suite) { - // Omit Suite logic, since there is no Suite names in Karate + // Trigger launch start + launch.get(); } @Override From d7e3b0ecac1789d955cf111473db2f33cca6e0ec Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Sat, 25 Apr 2026 14:23:11 +0300 Subject: [PATCH 04/19] Fix scenario tracking --- .../epam/reportportal/karate/ReportPortalResultListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java b/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java index bb31459..4df2a46 100644 --- a/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java +++ b/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java @@ -142,7 +142,7 @@ private String getFeatureNameForReport(Feature feature) { @Override public void onFeatureStart(Feature feature) { - Scenario parentScenario = parentScenarios.get().getLast(); + Scenario parentScenario = parentScenarios.get().peekLast(); StartTestItemRQ rq = buildStartFeatureRq(feature); featureIdMap.computeIfAbsent( getFeatureNameForReport(feature), f -> new MemoizingSupplier<>(() -> { From a281bfd42661e57da8877b018ed9770ac8c22fff Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Sat, 25 Apr 2026 14:42:51 +0300 Subject: [PATCH 05/19] Fix comments --- .../epam/reportportal/karate/ReportPortalResultListener.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java b/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java index 4df2a46..f61c74c 100644 --- a/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java +++ b/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 EPAM Systems + * Copyright 2026 EPAM Systems * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -480,8 +480,7 @@ public void afterStep(StepResult stepResult, ScenarioResult sr) { @Override public void onSuiteStart(Suite suite) { - // Trigger launch start - launch.get(); + launch.get(); // Trigger launch start } @Override From d1e69773c274853acf997ea8f34a062d07917f21 Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Sat, 25 Apr 2026 16:24:58 +0300 Subject: [PATCH 06/19] Add ReportPortalRunListener --- .../karate/ReportPortalRunListener.java | 536 ++++++++++++++++++ .../karate/ReportPortalUtils.java | 35 ++ .../reportportal/karate/utils/TestUtils.java | 5 +- 3 files changed, 574 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/epam/reportportal/karate/ReportPortalRunListener.java diff --git a/src/main/java/com/epam/reportportal/karate/ReportPortalRunListener.java b/src/main/java/com/epam/reportportal/karate/ReportPortalRunListener.java new file mode 100644 index 0000000..f24852b --- /dev/null +++ b/src/main/java/com/epam/reportportal/karate/ReportPortalRunListener.java @@ -0,0 +1,536 @@ +/* + * Copyright 2026 EPAM Systems + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.epam.reportportal.karate; + +import com.epam.reportportal.karate.utils.BlockingConcurrentHashMap; +import com.epam.reportportal.listeners.ItemStatus; +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.utils.MemoizingSupplier; +import com.epam.reportportal.utils.StatusEvaluation; +import com.epam.reportportal.utils.formatting.MarkdownUtils; +import com.epam.ta.reportportal.ws.model.FinishExecutionRQ; +import com.epam.ta.reportportal.ws.model.FinishTestItemRQ; +import com.epam.ta.reportportal.ws.model.StartTestItemRQ; +import com.epam.ta.reportportal.ws.model.launch.StartLaunchRQ; +import io.karatelabs.core.*; +import io.karatelabs.gherkin.Step; +import io.karatelabs.http.HttpRequest; +import io.karatelabs.http.HttpResponse; +import io.reactivex.Maybe; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.time.Instant; +import java.util.Collections; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Supplier; + +import static com.epam.reportportal.karate.ReportPortalUtils.*; +import static com.epam.reportportal.utils.ParameterUtils.formatParametersAsTable; +import static com.epam.reportportal.utils.formatting.MarkdownUtils.formatDataTable; +import static java.util.Optional.ofNullable; +import static org.apache.commons.lang3.StringUtils.isNotBlank; + +/** + * ReportPortal test run reporting listener for Karate. This class publish results in the process of test pass. + */ +public class ReportPortalRunListener implements RunListener { + private static final Logger LOGGER = LoggerFactory.getLogger(ReportPortalRunListener.class); + protected final MemoizingSupplier launch; + private final BlockingConcurrentHashMap>> featureIdMap = new BlockingConcurrentHashMap<>(); + private final Map> scenarioIdMap = new ConcurrentHashMap<>(); + private final Map> backgroundIdMap = new ConcurrentHashMap<>(); + private final Map backgroundStatusMap = new ConcurrentHashMap<>(); + private final Map> stepIdMap = new ConcurrentHashMap<>(); + private final Map stepStartTimeMap = new ConcurrentHashMap<>(); + private final Set> innerFeatures = Collections.newSetFromMap(new ConcurrentHashMap<>()); + private volatile Thread shutDownHook; + + /** + * Create a new instance of the ReportPortalHook with the specified ReportPortal instance. + * + * @param reportPortal the ReportPortal instance + */ + public ReportPortalRunListener(ReportPortal reportPortal) { + ListenerParameters params = reportPortal.getParameters(); + StartLaunchRQ rq = buildStartLaunchRq(params); + launch = new MemoizingSupplier<>(() -> { + Launch newLaunch = reportPortal.newLaunch(rq); + //noinspection ReactiveStreamsUnusedPublisher + newLaunch.start(); + shutDownHook = registerShutdownHook(this::finishLaunch); + return newLaunch; + }); + } + + /** + * Default constructor. Create a new instance of the ReportPortalHook with default ReportPortal instance. + */ + @SuppressWarnings("unused") + public ReportPortalRunListener() { + this(ReportPortal.builder().build()); + } + + @SuppressWarnings("unused") + public ReportPortalRunListener(Supplier launchSupplier) { + launch = new MemoizingSupplier<>(launchSupplier); + } + + /** + * Customize start launch event/request + * + * @param parameters Launch configuration parameters + * @return request to ReportPortal + */ + protected StartLaunchRQ buildStartLaunchRq(ListenerParameters parameters) { + return ReportPortalUtils.buildStartLaunchRq(parameters); + } + + /** + * Customize start Launch finish event/request. + * + * @param parameters Launch configuration parameters + * @return request to ReportPortal + */ + @Nonnull + protected FinishExecutionRQ buildFinishLaunchRq(@Nonnull ListenerParameters parameters) { + return ReportPortalUtils.buildFinishLaunchRq(parameters); + } + + /** + * Finish sending Launch data to ReportPortal. + */ + public void finishLaunch() { + ReportPortalUtils.doFinishLaunch(launch.get(), buildFinishLaunchRq(launch.get().getParameters()), shutDownHook); + } + + /** + * Build ReportPortal request for start Feature event. + * + * @param fr Karate's FeatureRuntime object instance + * @return request to ReportPortal + */ + @Nonnull + protected StartTestItemRQ buildStartFeatureRq(@Nonnull FeatureRuntime fr) { + StartTestItemRQ rq = ReportPortalUtils.buildStartFeatureRq(fr.getFeature()); + ofNullable(fr.getCaller()).map(FeatureRuntime::getCallArg).filter(args -> !args.isEmpty()).ifPresent(args -> { + String parameters = String.format(PARAMETERS_PATTERN, formatParametersAsTable(getParameters(args))); + String description = rq.getDescription(); + if (isNotBlank(description)) { + rq.setDescription(MarkdownUtils.asTwoParts(parameters, description)); + } else { + rq.setDescription(parameters); + } + }); + return rq; + } + + private int getDepth(FeatureRuntime fr) { + var caller = fr.getCallerScenario(); + if (caller == null) { + return 0; + } + int depth = 0; + while (caller != null) { + depth++; + caller = caller.getFeatureRuntime().getCallerScenario(); + } + return depth; + } + + private String getFeatureNameForReport(FeatureRuntime fr) { + int callDepth = getDepth(fr); + return callDepth + ":" + fr.getFeature().getNameForReport(); + } + + public void beforeFeature(FeatureRuntime fr) { + StartTestItemRQ rq = buildStartFeatureRq(fr); + featureIdMap.computeIfAbsent( + getFeatureNameForReport(fr), f -> new MemoizingSupplier<>(() -> { + if (getDepth(fr) == 0) { + return launch.get().startTestItem(rq); + } else { + Maybe scenarioId = scenarioIdMap.get(fr.getCaller().getCallerScenario().getScenario().getUniqueId()); + if (scenarioId == null) { + LOGGER.error("ERROR: Trying to post unspecified scenario."); + return launch.get().startTestItem(rq); + } + rq.setType(ItemType.STEP.name()); + rq.setHasStats(false); + rq.setName(getInnerFeatureName(rq.getName())); + Maybe itemId = launch.get().startTestItem(scenarioId, rq); + innerFeatures.add(itemId); + if (StringUtils.isNotBlank(rq.getDescription())) { + ReportPortalUtils.sendLog(itemId, rq.getDescription(), LogLevel.INFO, (Instant) rq.getStartTime()); + } + return itemId; + } + }) + ); + } + + /** + * Build ReportPortal request for finish Feature event. + * + * @param fr Karate's FeatureRuntime object instance + * @return request to ReportPortal + */ + @Nonnull + protected FinishTestItemRQ buildFinishFeatureRq(@Nonnull FeatureRuntime fr) { + return buildFinishTestItemRq(Instant.now(), fr.getResult().isFailed() ? ItemStatus.FAILED : ItemStatus.PASSED); + } + + public void afterFeature(FeatureRuntime fr) { + Optional> optionalId = ofNullable(featureIdMap.get(getFeatureNameForReport(fr))).map(Supplier::get); + if (optionalId.isEmpty()) { + LOGGER.error("ERROR: Trying to finish unspecified feature."); + } + optionalId.ifPresent(featureId -> { + //noinspection ReactiveStreamsUnusedPublisher + launch.get().finishTestItem(featureId, buildFinishFeatureRq(fr)); + innerFeatures.remove(featureId); + }); + } + + /** + * Build ReportPortal request for start Scenario event. + * + * @param sr Karate's ScenarioRuntime object instance + * @return request to ReportPortal + */ + @Nonnull + protected StartTestItemRQ buildStartScenarioRq(@Nonnull ScenarioRuntime sr) { + StartTestItemRQ rq = ReportPortalUtils.buildStartScenarioRq(sr.getScenario()); + ofNullable(featureIdMap.get(getFeatureNameForReport(sr.getFeatureRuntime()))).map(Supplier::get) + .map(featureId -> innerFeatures.contains(featureId) ? featureId : null) + .ifPresent(featureId -> { + rq.setType(ItemType.STEP.name()); + rq.setHasStats(false); + rq.setName(getInnerScenarioName(rq.getName())); + }); + return rq; + } + + public void beforeScenario(ScenarioRuntime sr) { + StartTestItemRQ rq = buildStartScenarioRq(sr); + Optional> optionalId = ofNullable(featureIdMap.get(getFeatureNameForReport(sr.getFeatureRuntime()))).map(Supplier::get); + if (optionalId.isEmpty()) { + LOGGER.error("ERROR: Trying to post unspecified feature."); + } + String uniqueId = sr.getScenario().getUniqueId(); + ofNullable(scenarioIdMap.get(uniqueId)).map(Maybe::blockingGet).ifPresent(id -> { + rq.setRetry(true); + rq.setRetryOf(id); + }); + optionalId.ifPresent(featureId -> { + Maybe scenarioId = launch.get().startTestItem(featureId, rq); + if (innerFeatures.contains(featureId) && StringUtils.isNotBlank(rq.getDescription())) { + ReportPortalUtils.sendLog(scenarioId, rq.getDescription(), LogLevel.INFO); + } + scenarioIdMap.put(uniqueId, scenarioId); + }); + } + + /** + * Build ReportPortal request for finish Scenario event. + * + * @param sr Karate's ScenarioRuntime object instance + * @return request to ReportPortal + */ + @Nonnull + protected FinishTestItemRQ buildFinishScenarioRq(@Nonnull ScenarioRuntime sr) { + return ReportPortalUtils.buildFinishScenarioRq(sr.getResult()); + } + + /** + * Build ReportPortal request for start Background event. + * + * @param step Karate's Step object instance + * @param sr Karate's ScenarioRuntime object instance + * @return request to ReportPortal + */ + @Nonnull + @SuppressWarnings("unused") + protected StartTestItemRQ buildStartBackgroundRq(@Nonnull Step step, @Nonnull ScenarioRuntime sr) { + return ReportPortalUtils.buildStartBackgroundRq(Instant.now(), step, sr.getScenario()); + } + + /** + * Start sending Background data to ReportPortal. + * + * @param step Karate's Step object instance + * @param sr Karate's ScenarioRuntime object instance + * @return item ID Future + */ + public Maybe startBackground(@Nonnull Step step, @Nonnull ScenarioRuntime sr) { + String uniqueId = sr.getScenario().getUniqueId(); + return backgroundIdMap.computeIfAbsent( + uniqueId, k -> { + StartTestItemRQ backgroundRq = buildStartBackgroundRq(step, sr); + return launch.get().startTestItem(scenarioIdMap.get(uniqueId), backgroundRq); + } + ); + } + + /** + * Build ReportPortal request for finish Background event. + * + * @param stepResult Karate's StepResult class instance + * @param sr Karate's ScenarioRuntime object instance + * @return request to ReportPortal + */ + @Nonnull + @SuppressWarnings("unused") + protected FinishTestItemRQ buildFinishBackgroundRq(@Nullable StepResult stepResult, @Nonnull ScenarioRuntime sr) { + return buildFinishTestItemRq(Instant.now(), backgroundStatusMap.remove(sr.getScenario().getUniqueId())); + } + + /** + * Finish sending Scenario data to ReportPortal. + * + * @param stepResult Karate's StepResult class instance + * @param sr Karate's ScenarioRuntime object instance + */ + public void finishBackground(@Nullable StepResult stepResult, @Nonnull ScenarioRuntime sr) { + String uniqueId = sr.getScenario().getUniqueId(); + Maybe backgroundId = backgroundIdMap.remove(uniqueId); + if (backgroundId != null) { + FinishTestItemRQ finishRq = buildFinishBackgroundRq(stepResult, sr); + //noinspection ReactiveStreamsUnusedPublisher + launch.get().finishTestItem(backgroundId, finishRq); + } + } + + /** + * Embed an attachment to ReportPortal. + * + * @param itemId item ID future + * @param embed Karate's Embed object + */ + protected void embedAttachment(@Nonnull Maybe itemId, @Nonnull StepResult.Embed embed) { + ReportPortalUtils.embedAttachment(Instant.now(), itemId, embed); + } + + public void afterScenario(ScenarioRuntime sr) { + String uniqueId = sr.getScenario().getUniqueId(); + Maybe scenarioId = scenarioIdMap.get(uniqueId); + stepStartTimeMap.remove(uniqueId); + finishBackground(null, sr); + + if (scenarioId == null) { + LOGGER.error("ERROR: Trying to finish unspecified scenario."); + return; + } + + FinishTestItemRQ rq = buildFinishScenarioRq(sr); + //noinspection ReactiveStreamsUnusedPublisher + launch.get().finishTestItem(scenarioId, rq); + } + + /** + * Get step start time. To keep the steps order in case previous step startTime == current step startTime or + * previous step startTime > current step startTime. + * + * @param scenarioUniqueId Karate's Scenario Unique ID + * @return step new startTime in Instant format. + */ + @Nonnull + private Instant getStepStartTime(@Nullable String scenarioUniqueId) { + return ReportPortalUtils.getStepStartTime(scenarioUniqueId, stepStartTimeMap, launch.get().useMicroseconds()); + } + + /** + * Customize start Step test item event/request. + * + * @param step Karate's Step object instance + * @param sr Karate's ScenarioRuntime object instance + * @return request to ReportPortal + */ + @Nonnull + protected StartTestItemRQ buildStartStepRq(@Nonnull Step step, @Nonnull ScenarioRuntime sr) { + StartTestItemRQ rq = ReportPortalUtils.buildStartStepRq(step, sr.getScenario()); + Instant startTime = getStepStartTime(sr.getScenario().getUniqueId()); + rq.setStartTime(startTime); + return rq; + } + + /** + * Send Step logs to ReportPortal. + * + * @param itemId item ID future + * @param message log message to send + * @param level log level + */ + protected void sendLog(Maybe itemId, String message, LogLevel level) { + ReportPortalUtils.sendLog(itemId, message, level); + } + + public void beforeStep(Step step, ScenarioRuntime sr) { + boolean background = step.isBackground(); + Maybe backgroundId = null; + if (background) { + backgroundId = startBackground(step, sr); + } + StartTestItemRQ stepRq = buildStartStepRq(step, sr); + + String scenarioId = sr.getScenario().getUniqueId(); + Maybe stepId = launch.get().startTestItem(background ? backgroundId : scenarioIdMap.get(scenarioId), stepRq); + stepIdMap.put(scenarioId, stepId); + ofNullable(stepRq.getParameters()).filter(params -> !params.isEmpty()) + .ifPresent(params -> sendLog(stepId, String.format(PARAMETERS_PATTERN, formatParametersAsTable(params)), LogLevel.INFO)); + ofNullable(step.getTable()).ifPresent(table -> sendLog(stepId, "Table:\n\n" + formatDataTable(table.getRows()), LogLevel.INFO)); + String docString = step.getDocString(); + if (isNotBlank(docString)) { + sendLog(stepId, "Docstring:\n\n" + asMarkdownCode(step.getDocString()), LogLevel.INFO); + } + } + + /** + * Send Step execution results to ReportPortal. + * + * @param stepResult step execution results + * @param sr Karate's ScenarioRuntime object instance + */ + public void sendStepResults(StepResult stepResult, ScenarioRuntime sr) { + Maybe stepId = stepIdMap.get(sr.getScenario().getUniqueId()); + Step step = stepResult.getStep(); + ofNullable(stepResult.getEmbeds()).ifPresent(embeds -> embeds.forEach(embed -> embedAttachment(stepId, embed))); + + if (stepResult.isFailed()) { + String fullErrorMessage = step.getPrefix() + " " + step.getText(); + String errorMessage = stepResult.getErrorMessage(); + if (isNotBlank(errorMessage)) { + fullErrorMessage = fullErrorMessage + "\n" + errorMessage; + } + sendLog(stepId, fullErrorMessage, LogLevel.ERROR); + } + } + + /** + * Build ReportPortal request for finish Step event. + * + * @param stepResult Karate's StepResult class instance + * @param sr Karate's ScenarioRuntime object instance + * @return request to ReportPortal + */ + @Nonnull + @SuppressWarnings("unused") + protected FinishTestItemRQ buildFinishStepRq(@Nonnull StepResult stepResult, @Nonnull ScenarioRuntime sr) { + return buildFinishTestItemRq(Instant.now(), getStepStatus(stepResult.getStatus())); + } + + private void saveBackgroundStatus(@Nonnull StepResult stepResult, @Nonnull ScenarioRuntime sr) { + String scenarioId = sr.getScenario().getUniqueId(); + backgroundStatusMap.put( + scenarioId, + StatusEvaluation.evaluateStatus(backgroundStatusMap.get(scenarioId), getStepStatus(stepResult.getStatus())) + ); + } + + public void afterStep(StepResult stepResult, ScenarioRuntime sr) { + boolean background = stepResult.getStep().isBackground(); + if (!background) { + finishBackground(stepResult, sr); + } + + sendStepResults(stepResult, sr); + Maybe stepId = stepIdMap.remove(sr.getScenario().getUniqueId()); + if (stepId == null) { + LOGGER.error("ERROR: Trying to finish unspecified step."); + return; + } + + FinishTestItemRQ rq = buildFinishStepRq(stepResult, sr); + if (background) { + saveBackgroundStatus(stepResult, sr); + } + //noinspection ReactiveStreamsUnusedPublisher + launch.get().finishTestItem(stepId, rq); + } + + @SuppressWarnings("unused") + public void sendErrorResults(long timestamp, Throwable error, ScenarioRuntime sr) { + ReportPortal.sendStackTraceToRP(error); + } + + @SuppressWarnings("unused") + public void beforeHttpCall(HttpRequest request, ScenarioRuntime sr) { + } + + @SuppressWarnings("unused") + public void afterHttpCall(HttpRequest request, HttpResponse response, ScenarioRuntime sr) { + } + + @SuppressWarnings("unused") + public void beforeSuite(Suite suite) { + // Omit Suite logic, since there is no Suite names in Karate + } + + @SuppressWarnings("unused") + public void afterSuite(SuiteResult suite) { + // Omit Suite logic, since there is no Suite names in Karate + } + + @Override + @SuppressWarnings("UnnecessaryDefault") + public boolean onEvent(RunEvent event) { + launch.get(); // Trigger launch start + switch (event.getType()) { + case SUITE_ENTER -> beforeSuite(((SuiteRunEvent) event).source()); + case SUITE_EXIT -> afterSuite(((SuiteRunEvent) event).result()); + case FEATURE_ENTER -> beforeFeature(((FeatureRunEvent) event).source()); + case FEATURE_EXIT -> afterFeature(((FeatureRunEvent) event).source()); + case SCENARIO_ENTER -> beforeScenario(((ScenarioRunEvent) event).source()); + case SCENARIO_EXIT -> afterScenario(((ScenarioRunEvent) event).source()); + case STEP_ENTER -> { + var stepEvent = ((StepRunEvent) event); + beforeStep(stepEvent.step(), stepEvent.scenarioRuntime()); + } + case STEP_EXIT -> { + var stepEvent = ((StepRunEvent) event); + afterStep(stepEvent.result(), stepEvent.scenarioRuntime()); + } + case HTTP_ENTER -> { + var httpEvent = ((HttpRunEvent) event); + beforeHttpCall(httpEvent.request(), httpEvent.scenarioRuntime()); + } + case HTTP_EXIT -> { + var httpEvent = ((HttpRunEvent) event); + afterHttpCall(httpEvent.request(), httpEvent.response(), httpEvent.scenarioRuntime()); + } + case ERROR -> { + var errorEvent = ((ErrorRunEvent) event); + sendErrorResults(errorEvent.timeStamp(), errorEvent.error(), errorEvent.scenarioRuntime()); + } + case PROGRESS -> { + // do we need it? + } + default -> LOGGER.warn("Unknown event type received: {}", event.getType().name()); + } + return true; + } +} diff --git a/src/main/java/com/epam/reportportal/karate/ReportPortalUtils.java b/src/main/java/com/epam/reportportal/karate/ReportPortalUtils.java index aebdfc7..fb4d6b7 100644 --- a/src/main/java/com/epam/reportportal/karate/ReportPortalUtils.java +++ b/src/main/java/com/epam/reportportal/karate/ReportPortalUtils.java @@ -45,6 +45,7 @@ import org.slf4j.LoggerFactory; import java.time.Instant; +import java.time.temporal.ChronoUnit; import java.util.*; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -536,4 +537,38 @@ public static String getInnerScenarioName(String name) { public static String getInnerFeatureName(String name) { return FEATURE_TAG + name; } + + /** + * Get step start time. To keep the steps order in case previous step startTime == current step startTime or + * previous step startTime > current step startTime. + * + * @param scenarioUniqueId Karate's Scenario Unique ID, a key for stepStartTimeMap + * @param stepStartTimeMap a holder for start times for every particular scenario + * @param useMicroseconds if server supports microseconds + * @return step new startTime in Instant format. + */ + public static Instant getStepStartTime(@Nullable String scenarioUniqueId, Map stepStartTimeMap, + boolean useMicroseconds) { + Instant currentStepStartTime = Instant.now().truncatedTo(ChronoUnit.MICROS); + if (scenarioUniqueId == null || stepStartTimeMap.isEmpty()) { + stepStartTimeMap.put(scenarioUniqueId, currentStepStartTime); + return currentStepStartTime; + } + Instant lastStepStartTime = stepStartTimeMap.get(scenarioUniqueId); + if (lastStepStartTime == null) { + stepStartTimeMap.put(scenarioUniqueId, currentStepStartTime); + return currentStepStartTime; + } + if (useMicroseconds) { + if (lastStepStartTime.compareTo(currentStepStartTime) >= 0) { + currentStepStartTime = lastStepStartTime.plus(1, ChronoUnit.MICROS); + } + } else { + if (lastStepStartTime.truncatedTo(ChronoUnit.MILLIS).compareTo(currentStepStartTime.truncatedTo(ChronoUnit.MILLIS)) >= 0) { + currentStepStartTime = lastStepStartTime.plus(1, ChronoUnit.MILLIS); + } + } + stepStartTimeMap.put(scenarioUniqueId, currentStepStartTime); + return currentStepStartTime; + } } diff --git a/src/test/java/com/epam/reportportal/karate/utils/TestUtils.java b/src/test/java/com/epam/reportportal/karate/utils/TestUtils.java index 1acb112..bd59733 100644 --- a/src/test/java/com/epam/reportportal/karate/utils/TestUtils.java +++ b/src/test/java/com/epam/reportportal/karate/utils/TestUtils.java @@ -17,6 +17,7 @@ package com.epam.reportportal.karate.utils; import com.epam.reportportal.karate.ReportPortalResultListener; +import com.epam.reportportal.karate.ReportPortalRunListener; import com.epam.reportportal.listeners.ListenerParameters; import com.epam.reportportal.service.LaunchImpl; import com.epam.reportportal.service.ReportPortal; @@ -80,8 +81,8 @@ public static SuiteResult runAsReportListener(ReportPortal reportPortal, String. } public static SuiteResult runAsEventListener(ReportPortal reportPortal, List tags, String... paths) { - ReportPortalResultListener listener = new ReportPortalResultListener(reportPortal); - Runner.Builder path = Runner.path(paths).resultListener(listener).outputCucumberJson(false); + ReportPortalRunListener listener = new ReportPortalRunListener(reportPortal); + Runner.Builder path = Runner.path(paths).listener(listener).outputCucumberJson(false); SuiteResult result = path.tags(tags.toArray(new String[0])).parallel(1); listener.finishLaunch(); return result; From fc607e5a3228977a6c9704231024057c06545caa Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Sat, 25 Apr 2026 16:43:29 +0300 Subject: [PATCH 07/19] Test fixes --- .../attributes/DifferentAttributesTest.java | 2 +- .../attributes/LaunchAttributesTest.java | 2 +- .../karate/attributes/NoAttributesTest.java | 2 +- .../attributes/SystemAttributesTest.java | 2 +- .../background/BackgroundExamplesTest.java | 6 ++--- .../karate/background/BackgroundTest.java | 8 +++---- .../background/BackgroundTwoStepsTest.java | 6 ++--- .../call/CallWithParametersPublisherTest.java | 2 +- .../karate/coderef/ExamplesCodeRefTest.java | 6 ++--- .../karate/coderef/ScenarioCodeRefTest.java | 2 +- .../description/DescriptionExamplesTest.java | 4 ++-- .../description/LaunchDescriptionTest.java | 2 +- .../NoDescriptionExamplesTest.java | 4 ++-- .../karate/description/NoDescriptionTest.java | 2 +- .../description/NoLaunchDescriptionTest.java | 2 +- .../ScenarioDescriptionErrorLogTest.java | 6 ++--- ...rrorLogWithDescriptionAndExamplesTest.java | 10 ++++----- ...escriptionErrorLogWithDescriptionTest.java | 6 ++--- ...ioDescriptionErrorLogWithExamplesTest.java | 10 ++++----- .../description/SimpleDescriptionTest.java | 4 ++-- .../karate/id/ExamplesTestCaseIdTest.java | 4 ++-- .../karate/id/ScenarioTestCaseIdTest.java | 2 +- .../launch/LaunchRequiredFieldsTest.java | 2 +- .../karate/logging/EmbedLoggingTest.java | 11 +++++----- .../logging/HttpRequestLoggingTest.java | 15 +++++++++---- .../logging/SimpleFailureLoggingTest.java | 11 +++++----- .../karate/name/NoFeatureNameTest.java | 2 +- .../karate/name/SimpleItemNameTest.java | 2 +- .../ExamplesScenarioParametersTest.java | 4 ++-- .../ExamplesStepParametersTest.java | 8 +++---- .../karate/parameters/NoParametersTest.java | 2 +- .../parameters/NullValueExamplesTest.java | 6 ++--- .../parameters/TableParametersTest.java | 6 ++--- .../karate/status/OneExampleFailedTest.java | 6 ++--- .../OneExampleWithBackgroundFailedTest.java | 17 ++++++++------ .../karate/status/SimpleAllPassedTest.java | 4 ++-- .../status/SimpleOneStepFailedTest.java | 6 ++--- .../karate/tags/SimpleTagInclusionTest.java | 4 ++-- .../karate/timing/SimpleTimingTest.java | 2 +- .../reportportal/karate/utils/TestUtils.java | 22 +++++++++---------- 40 files changed, 117 insertions(+), 107 deletions(-) diff --git a/src/test/java/com/epam/reportportal/karate/attributes/DifferentAttributesTest.java b/src/test/java/com/epam/reportportal/karate/attributes/DifferentAttributesTest.java index fa29589..e4fa796 100644 --- a/src/test/java/com/epam/reportportal/karate/attributes/DifferentAttributesTest.java +++ b/src/test/java/com/epam/reportportal/karate/attributes/DifferentAttributesTest.java @@ -60,7 +60,7 @@ public void setupMock() { public void test_different_attributes(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } diff --git a/src/test/java/com/epam/reportportal/karate/attributes/LaunchAttributesTest.java b/src/test/java/com/epam/reportportal/karate/attributes/LaunchAttributesTest.java index 7185593..d52833a 100644 --- a/src/test/java/com/epam/reportportal/karate/attributes/LaunchAttributesTest.java +++ b/src/test/java/com/epam/reportportal/karate/attributes/LaunchAttributesTest.java @@ -65,7 +65,7 @@ public void setupMock() { public void verify_start_launch_request_contains_launch_attributes(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } diff --git a/src/test/java/com/epam/reportportal/karate/attributes/NoAttributesTest.java b/src/test/java/com/epam/reportportal/karate/attributes/NoAttributesTest.java index f1d1bb4..1bd64f6 100644 --- a/src/test/java/com/epam/reportportal/karate/attributes/NoAttributesTest.java +++ b/src/test/java/com/epam/reportportal/karate/attributes/NoAttributesTest.java @@ -57,7 +57,7 @@ public void setupMock() { public void test_different_attributes(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } diff --git a/src/test/java/com/epam/reportportal/karate/attributes/SystemAttributesTest.java b/src/test/java/com/epam/reportportal/karate/attributes/SystemAttributesTest.java index c8a3431..a8e8aeb 100644 --- a/src/test/java/com/epam/reportportal/karate/attributes/SystemAttributesTest.java +++ b/src/test/java/com/epam/reportportal/karate/attributes/SystemAttributesTest.java @@ -59,7 +59,7 @@ public void setupMock() { public void verify_start_launch_request_contains_system_attributes(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } diff --git a/src/test/java/com/epam/reportportal/karate/background/BackgroundExamplesTest.java b/src/test/java/com/epam/reportportal/karate/background/BackgroundExamplesTest.java index 332097e..9be0687 100644 --- a/src/test/java/com/epam/reportportal/karate/background/BackgroundExamplesTest.java +++ b/src/test/java/com/epam/reportportal/karate/background/BackgroundExamplesTest.java @@ -45,7 +45,7 @@ public class BackgroundExamplesTest { private static final String TEST_FEATURE = "classpath:feature/background_examples.feature"; private final String featureId = CommonUtils.namedId("feature_"); - private final List scenarioIds = Stream.generate(() -> CommonUtils.namedId("scenario_")).limit(2).collect(Collectors.toList()); + private final List scenarioIds = Stream.generate(() -> CommonUtils.namedId("scenario_")).limit(2).toList(); private final List>> scenarioSteps = scenarioIds.stream() .map(s -> Pair.of(s, Stream.generate(() -> CommonUtils.namedId("step_")).limit(3).collect(Collectors.toList()))) @@ -70,7 +70,7 @@ public void setupMock() { public void test_background_steps(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } @@ -115,6 +115,6 @@ public void test_background_steps(boolean report) { Set nestedStepNames = nestedSteps.stream().map(StartTestItemRQ::getName).collect(Collectors.toSet()); assertThat(nestedStepNames, hasSize(1)); - assertThat(nestedStepNames, hasItem("Given def varb = 2")); + assertThat(nestedStepNames, hasItem("Given varb = 2")); } } diff --git a/src/test/java/com/epam/reportportal/karate/background/BackgroundTest.java b/src/test/java/com/epam/reportportal/karate/background/BackgroundTest.java index cbd116a..b23f484 100644 --- a/src/test/java/com/epam/reportportal/karate/background/BackgroundTest.java +++ b/src/test/java/com/epam/reportportal/karate/background/BackgroundTest.java @@ -65,7 +65,7 @@ public void setupMock() { public void test_background_steps(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } @@ -88,7 +88,7 @@ public void test_background_steps(boolean report) { .filter(s -> s.getName().startsWith(Background.KEYWORD)) .collect(Collectors.toList()); assertThat(backgroundSteps, hasSize(1)); - StartTestItemRQ backgroundStep = backgroundSteps.get(0); + StartTestItemRQ backgroundStep = backgroundSteps.getFirst(); assertThat(backgroundStep.getName(), equalTo(Background.KEYWORD)); // No name for Background in Karate assertThat(backgroundStep.isHasStats(), equalTo(Boolean.FALSE)); assertThat(backgroundStep.getStartTime(), notNullValue()); @@ -96,8 +96,8 @@ public void test_background_steps(boolean report) { List nestedSteps = nestedStepCaptor.getAllValues(); assertThat(nestedSteps, hasSize(1)); - StartTestItemRQ nestedStep = nestedSteps.get(0); - assertThat(nestedStep.getName(), equalTo("Given def four = 4")); + StartTestItemRQ nestedStep = nestedSteps.getFirst(); + assertThat(nestedStep.getName(), equalTo("Given four = 4")); assertThat(nestedStep.isHasStats(), equalTo(Boolean.FALSE)); } } diff --git a/src/test/java/com/epam/reportportal/karate/background/BackgroundTwoStepsTest.java b/src/test/java/com/epam/reportportal/karate/background/BackgroundTwoStepsTest.java index 5fcd55e..4a2a8cf 100644 --- a/src/test/java/com/epam/reportportal/karate/background/BackgroundTwoStepsTest.java +++ b/src/test/java/com/epam/reportportal/karate/background/BackgroundTwoStepsTest.java @@ -67,7 +67,7 @@ public void setupMock() { public void test_background_steps(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } @@ -90,7 +90,7 @@ public void test_background_steps(boolean report) { .filter(s -> s.getName().startsWith(Background.KEYWORD)) .collect(Collectors.toList()); assertThat(backgroundSteps, hasSize(1)); - StartTestItemRQ backgroundStep = backgroundSteps.get(0); + StartTestItemRQ backgroundStep = backgroundSteps.getFirst(); assertThat(backgroundStep.getName(), equalTo(Background.KEYWORD)); // No name for Background in Karate assertThat(backgroundStep.isHasStats(), equalTo(Boolean.FALSE)); assertThat(backgroundStep.getStartTime(), notNullValue()); @@ -101,6 +101,6 @@ public void test_background_steps(boolean report) { nestedSteps.forEach(step -> assertThat(step.isHasStats(), equalTo(Boolean.FALSE))); Set nestedStepNames = nestedSteps.stream().map(StartTestItemRQ::getName).collect(Collectors.toSet()); - assertThat(nestedStepNames, allOf(hasItem("Given def vara = 2"), hasItem("And def varb = 2"))); + assertThat(nestedStepNames, allOf(hasItem("Given vara = 2"), hasItem("And varb = 2"))); } } diff --git a/src/test/java/com/epam/reportportal/karate/call/CallWithParametersPublisherTest.java b/src/test/java/com/epam/reportportal/karate/call/CallWithParametersPublisherTest.java index 8ec2754..64a70c7 100644 --- a/src/test/java/com/epam/reportportal/karate/call/CallWithParametersPublisherTest.java +++ b/src/test/java/com/epam/reportportal/karate/call/CallWithParametersPublisherTest.java @@ -52,7 +52,7 @@ public void setupMock() { @Test public void test_call_feature_with_parameters_publisher_reporting() { - SuiteResult results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + SuiteResult results = TestUtils.runAsResultListener(rp, TEST_FEATURE); assertThat(results.getFeatureFailedCount(), equalTo(0)); ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); diff --git a/src/test/java/com/epam/reportportal/karate/coderef/ExamplesCodeRefTest.java b/src/test/java/com/epam/reportportal/karate/coderef/ExamplesCodeRefTest.java index 49b1cc6..6e8de8e 100644 --- a/src/test/java/com/epam/reportportal/karate/coderef/ExamplesCodeRefTest.java +++ b/src/test/java/com/epam/reportportal/karate/coderef/ExamplesCodeRefTest.java @@ -45,7 +45,7 @@ public class ExamplesCodeRefTest { private static final String FIRST_EXAMPLE_CODE_REFERENCE = String.format(EXAMPLE_CODE_REFERENCE_PATTERN, "result:4;vara:2;varb:2"); private static final String SECOND_EXAMPLE_CODE_REFERENCE = String.format(EXAMPLE_CODE_REFERENCE_PATTERN, "result:3;vara:1;varb:2"); private final String featureId = CommonUtils.namedId("feature_"); - private final List exampleIds = Stream.generate(() -> CommonUtils.namedId("example_")).limit(2).collect(Collectors.toList()); + private final List exampleIds = Stream.generate(() -> CommonUtils.namedId("example_")).limit(2).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()); @@ -63,7 +63,7 @@ public void setupMock() { public void test_examples_code_reference(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } @@ -82,7 +82,7 @@ public void test_examples_code_reference(boolean report) { assertThat(featureRq.getType(), allOf(notNullValue(), equalTo(ItemType.STORY.name()))); List scenarios = scenarioCaptor.getAllValues(); - StartTestItemRQ firstScenarioRq = scenarios.get(0); + StartTestItemRQ firstScenarioRq = scenarios.getFirst(); assertThat(firstScenarioRq.getType(), allOf(notNullValue(), equalTo(ItemType.STEP.name()))); assertThat(firstScenarioRq.getCodeRef(), allOf(notNullValue(), equalTo(FIRST_EXAMPLE_CODE_REFERENCE))); diff --git a/src/test/java/com/epam/reportportal/karate/coderef/ScenarioCodeRefTest.java b/src/test/java/com/epam/reportportal/karate/coderef/ScenarioCodeRefTest.java index 569e3d6..a37e20a 100644 --- a/src/test/java/com/epam/reportportal/karate/coderef/ScenarioCodeRefTest.java +++ b/src/test/java/com/epam/reportportal/karate/coderef/ScenarioCodeRefTest.java @@ -58,7 +58,7 @@ public void setupMock() { public void test_scenario_code_reference(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } diff --git a/src/test/java/com/epam/reportportal/karate/description/DescriptionExamplesTest.java b/src/test/java/com/epam/reportportal/karate/description/DescriptionExamplesTest.java index bde75d8..e49a313 100644 --- a/src/test/java/com/epam/reportportal/karate/description/DescriptionExamplesTest.java +++ b/src/test/java/com/epam/reportportal/karate/description/DescriptionExamplesTest.java @@ -52,7 +52,7 @@ public class DescriptionExamplesTest { ); private static final String TEST_FEATURE = "classpath:feature/description_examples.feature"; private final String featureId = CommonUtils.namedId("feature_"); - private final List exampleIds = Stream.generate(() -> CommonUtils.namedId("example_")).limit(2).collect(Collectors.toList()); + private final List exampleIds = Stream.generate(() -> CommonUtils.namedId("example_")).limit(2).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()); @@ -70,7 +70,7 @@ public void setupMock() { public void test_examples_description(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } diff --git a/src/test/java/com/epam/reportportal/karate/description/LaunchDescriptionTest.java b/src/test/java/com/epam/reportportal/karate/description/LaunchDescriptionTest.java index 267ac38..9fd0f0e 100644 --- a/src/test/java/com/epam/reportportal/karate/description/LaunchDescriptionTest.java +++ b/src/test/java/com/epam/reportportal/karate/description/LaunchDescriptionTest.java @@ -62,7 +62,7 @@ public void setupMock() { public void verify_start_launch_request_contains_launch_description(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } diff --git a/src/test/java/com/epam/reportportal/karate/description/NoDescriptionExamplesTest.java b/src/test/java/com/epam/reportportal/karate/description/NoDescriptionExamplesTest.java index 7871452..e275aa7 100644 --- a/src/test/java/com/epam/reportportal/karate/description/NoDescriptionExamplesTest.java +++ b/src/test/java/com/epam/reportportal/karate/description/NoDescriptionExamplesTest.java @@ -47,7 +47,7 @@ public class NoDescriptionExamplesTest { public static final String FIRST_EXAMPLE_DESCRIPTION = EXAMPLE_PARAMETERS_DESCRIPTION_PATTERN + "|  2   |  2   |   4    |"; public static final String SECOND_EXAMPLE_DESCRIPTION = EXAMPLE_PARAMETERS_DESCRIPTION_PATTERN + "|  1   |  2   |   3    |"; private final String featureId = CommonUtils.namedId("feature_"); - private final List exampleIds = Stream.generate(() -> CommonUtils.namedId("example_")).limit(2).collect(Collectors.toList()); + private final List exampleIds = Stream.generate(() -> CommonUtils.namedId("example_")).limit(2).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()); @@ -65,7 +65,7 @@ public void setupMock() { public void test_examples_no_description(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } diff --git a/src/test/java/com/epam/reportportal/karate/description/NoDescriptionTest.java b/src/test/java/com/epam/reportportal/karate/description/NoDescriptionTest.java index c15db02..f5b5f32 100644 --- a/src/test/java/com/epam/reportportal/karate/description/NoDescriptionTest.java +++ b/src/test/java/com/epam/reportportal/karate/description/NoDescriptionTest.java @@ -58,7 +58,7 @@ public void setupMock() { public void test_description_for_all_possible_items(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } diff --git a/src/test/java/com/epam/reportportal/karate/description/NoLaunchDescriptionTest.java b/src/test/java/com/epam/reportportal/karate/description/NoLaunchDescriptionTest.java index 487fe31..861bc6b 100644 --- a/src/test/java/com/epam/reportportal/karate/description/NoLaunchDescriptionTest.java +++ b/src/test/java/com/epam/reportportal/karate/description/NoLaunchDescriptionTest.java @@ -68,7 +68,7 @@ public void verify_start_launch_request_contains_no_launch_description(boolean r ReportPortal rp = ReportPortal.create(client, parameters, testExecutor()); SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } diff --git a/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogTest.java b/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogTest.java index 9032ebf..51930ab 100644 --- a/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogTest.java +++ b/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogTest.java @@ -64,7 +64,7 @@ public void setupMock() { public void test_error_log_in_description(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } @@ -80,7 +80,7 @@ public void test_error_log_in_description(boolean report) { .collect(Collectors.toList()); assertThat(logs, hasSize(greaterThan(0))); - SaveLogRQ log = logs.get(logs.size() - 1); + SaveLogRQ log = logs.getLast(); assertThat(log.getItemUuid(), oneOf(stepIds.toArray(new String[0]))); assertThat(log.getLaunchUuid(), equalTo(launchUuid)); assertThat(log.getMessage(), equalTo(ERROR_MESSAGE)); @@ -89,7 +89,7 @@ public void test_error_log_in_description(boolean report) { verify(client, times(1)).finishTestItem(same(scenarioId), scenarioCaptorFinish.capture()); List scenarios = scenarioCaptorFinish.getAllValues(); - FinishTestItemRQ scenario = scenarios.get(0); + FinishTestItemRQ scenario = scenarios.getFirst(); assertThat(scenario.getDescription(), allOf(notNullValue(), equalTo(DESCRIPTION_ERROR_LOG))); } } diff --git a/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithDescriptionAndExamplesTest.java b/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithDescriptionAndExamplesTest.java index e0d0b75..504e3c0 100644 --- a/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithDescriptionAndExamplesTest.java +++ b/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithDescriptionAndExamplesTest.java @@ -73,7 +73,7 @@ public class ScenarioDescriptionErrorLogWithDescriptionAndExamplesTest { private static final String TEST_FEATURE = "classpath:feature/simple_failed_description_examples.feature"; private final String featureId = CommonUtils.namedId("feature_"); - private final List exampleIds = Stream.generate(() -> CommonUtils.namedId("example_")).limit(2).collect(Collectors.toList()); + private final List exampleIds = Stream.generate(() -> CommonUtils.namedId("example_")).limit(2).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()); @@ -93,7 +93,7 @@ public void test_error_log_and_examples_in_description(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } @@ -110,7 +110,7 @@ public void test_error_log_and_examples_in_description(boolean report) { .collect(Collectors.toList()); assertThat(logs, hasSize(greaterThan(0))); - SaveLogRQ log = logs.get(logs.size() - 1); + SaveLogRQ log = logs.getLast(); assertThat(log.getMessage(), equalTo(ERROR_MESSAGE)); ArgumentCaptor scenarioCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); @@ -121,9 +121,9 @@ public void test_error_log_and_examples_in_description(boolean report) { stepIds.size(), ArgumentCaptor.forClass(FinishTestItemRQ.class) )); - stepIds.forEach(pair -> pair.getValue().forEach(id -> verify(client).finishTestItem(same(id), stepCaptors.get(0).capture()))); + stepIds.forEach(pair -> pair.getValue().forEach(id -> verify(client).finishTestItem(same(id), stepCaptors.getFirst().capture()))); - FinishTestItemRQ firstScenarioRq = scenarioCaptor.getAllValues().get(0); + FinishTestItemRQ firstScenarioRq = scenarioCaptor.getAllValues().getFirst(); assertThat(firstScenarioRq.getStatus(), allOf(notNullValue(), equalTo(ItemStatus.PASSED.name()))); assertThat(firstScenarioRq.getDescription(), allOf(notNullValue(), equalTo(FIRST_EXAMPLE_DESCRIPTION_WITHOUT_ERROR_LOG))); diff --git a/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithDescriptionTest.java b/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithDescriptionTest.java index 8635698..e917722 100644 --- a/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithDescriptionTest.java +++ b/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithDescriptionTest.java @@ -71,7 +71,7 @@ public void setupMock() { public void test_error_log_and_description_in_description(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } @@ -87,7 +87,7 @@ public void test_error_log_and_description_in_description(boolean report) { .collect(Collectors.toList()); assertThat(logs, hasSize(greaterThan(0))); - SaveLogRQ log = logs.get(logs.size() - 1); + SaveLogRQ log = logs.getLast(); assertThat(log.getItemUuid(), oneOf(stepIds.toArray(new String[0]))); assertThat(log.getLaunchUuid(), equalTo(launchUuid)); assertThat(log.getMessage(), equalTo(ERROR_MESSAGE)); @@ -96,7 +96,7 @@ public void test_error_log_and_description_in_description(boolean report) { verify(client, times(1)).finishTestItem(same(scenarioId), scenarioCaptorFinish.capture()); List scenarios = scenarioCaptorFinish.getAllValues(); - FinishTestItemRQ scenario = scenarios.get(0); + FinishTestItemRQ scenario = scenarios.getFirst(); assertThat(scenario.getDescription(), allOf(notNullValue(), equalTo(DESCRIPTION_ERROR_LOG_WITH_DESCRIPTION))); } diff --git a/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithExamplesTest.java b/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithExamplesTest.java index 5c4ef96..87d5fd8 100644 --- a/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithExamplesTest.java +++ b/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithExamplesTest.java @@ -65,7 +65,7 @@ public class ScenarioDescriptionErrorLogWithExamplesTest { private static final String TEST_FEATURE = "classpath:feature/simple_failed_examples.feature"; private final String featureId = CommonUtils.namedId("feature_"); - private final List exampleIds = Stream.generate(() -> CommonUtils.namedId("example_")).limit(2).collect(Collectors.toList()); + private final List exampleIds = Stream.generate(() -> CommonUtils.namedId("example_")).limit(2).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()); @@ -85,7 +85,7 @@ public void test_error_log_and_examples_in_description(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } @@ -102,7 +102,7 @@ public void test_error_log_and_examples_in_description(boolean report) { .collect(Collectors.toList()); assertThat(logs, hasSize(greaterThan(0))); - SaveLogRQ log = logs.get(logs.size() - 1); + SaveLogRQ log = logs.getLast(); assertThat(log.getMessage(), equalTo(ERROR_MESSAGE)); ArgumentCaptor scenarioCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); @@ -113,9 +113,9 @@ public void test_error_log_and_examples_in_description(boolean report) { stepIds.size(), ArgumentCaptor.forClass(FinishTestItemRQ.class) )); - stepIds.forEach(pair -> pair.getValue().forEach(id -> verify(client).finishTestItem(same(id), stepCaptors.get(0).capture()))); + stepIds.forEach(pair -> pair.getValue().forEach(id -> verify(client).finishTestItem(same(id), stepCaptors.getFirst().capture()))); - FinishTestItemRQ firstScenarioRq = scenarioCaptor.getAllValues().get(0); + FinishTestItemRQ firstScenarioRq = scenarioCaptor.getAllValues().getFirst(); assertThat(firstScenarioRq.getStatus(), allOf(notNullValue(), equalTo(ItemStatus.PASSED.name()))); assertThat(firstScenarioRq.getDescription(), allOf(notNullValue(), equalTo(FIRST_EXAMPLE_DESCRIPTION))); diff --git a/src/test/java/com/epam/reportportal/karate/description/SimpleDescriptionTest.java b/src/test/java/com/epam/reportportal/karate/description/SimpleDescriptionTest.java index acdffe9..e5123fd 100644 --- a/src/test/java/com/epam/reportportal/karate/description/SimpleDescriptionTest.java +++ b/src/test/java/com/epam/reportportal/karate/description/SimpleDescriptionTest.java @@ -64,7 +64,7 @@ public void setupMock() { public void test_description_for_all_possible_items(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } @@ -88,7 +88,7 @@ public void test_description_for_all_possible_items(boolean report) { .filter(s -> s.getName().startsWith(Background.KEYWORD)) .collect(Collectors.toList()); assertThat(backgroundSteps, hasSize(1)); - StartTestItemRQ backgroundStep = backgroundSteps.get(0); + StartTestItemRQ backgroundStep = backgroundSteps.getFirst(); assertThat( "No support of Background description in Karate yet. But this is a part of Gherkin standard.", backgroundStep.getDescription(), diff --git a/src/test/java/com/epam/reportportal/karate/id/ExamplesTestCaseIdTest.java b/src/test/java/com/epam/reportportal/karate/id/ExamplesTestCaseIdTest.java index fbea9d7..15c550f 100644 --- a/src/test/java/com/epam/reportportal/karate/id/ExamplesTestCaseIdTest.java +++ b/src/test/java/com/epam/reportportal/karate/id/ExamplesTestCaseIdTest.java @@ -44,7 +44,7 @@ public class ExamplesTestCaseIdTest { private static final String FIRST_EXAMPLE_TEST_CASE_ID = String.format(EXAMPLE_TEST_CASE_ID_PATTERN, "result:4;vara:2;varb:2"); private static final String SECOND_EXAMPLE_TEST_CASE_ID = String.format(EXAMPLE_TEST_CASE_ID_PATTERN, "result:3;vara:1;varb:2"); private final String featureId = CommonUtils.namedId("feature_"); - private final List exampleIds = Stream.generate(() -> CommonUtils.namedId("example_")).limit(2).collect(Collectors.toList()); + private final List exampleIds = Stream.generate(() -> CommonUtils.namedId("example_")).limit(2).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()); @@ -62,7 +62,7 @@ public void setupMock() { public void test_examples_test_case_id(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } diff --git a/src/test/java/com/epam/reportportal/karate/id/ScenarioTestCaseIdTest.java b/src/test/java/com/epam/reportportal/karate/id/ScenarioTestCaseIdTest.java index 0c7ec04..d9c85a7 100644 --- a/src/test/java/com/epam/reportportal/karate/id/ScenarioTestCaseIdTest.java +++ b/src/test/java/com/epam/reportportal/karate/id/ScenarioTestCaseIdTest.java @@ -57,7 +57,7 @@ public void setupMock() { public void test_test_case_id(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } diff --git a/src/test/java/com/epam/reportportal/karate/launch/LaunchRequiredFieldsTest.java b/src/test/java/com/epam/reportportal/karate/launch/LaunchRequiredFieldsTest.java index 3c601d4..806efe0 100644 --- a/src/test/java/com/epam/reportportal/karate/launch/LaunchRequiredFieldsTest.java +++ b/src/test/java/com/epam/reportportal/karate/launch/LaunchRequiredFieldsTest.java @@ -59,7 +59,7 @@ public void setupMock() { public void verify_start_launch_request_contains_required_fields(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } diff --git a/src/test/java/com/epam/reportportal/karate/logging/EmbedLoggingTest.java b/src/test/java/com/epam/reportportal/karate/logging/EmbedLoggingTest.java index 2e23562..0a2f954 100644 --- a/src/test/java/com/epam/reportportal/karate/logging/EmbedLoggingTest.java +++ b/src/test/java/com/epam/reportportal/karate/logging/EmbedLoggingTest.java @@ -37,7 +37,8 @@ import static com.epam.reportportal.karate.utils.TestUtils.*; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; public class EmbedLoggingTest { private static final String TEST_FEATURE = "classpath:feature/embed.feature"; @@ -61,7 +62,7 @@ public void setupMock() { public void test_embed_image_attachment(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } @@ -84,7 +85,7 @@ public void test_embed_image_attachment(boolean report) { assertThat("Should have one attachment log message", attachmentLogs, hasSize(1)); // Verify the attachment log properties - SaveLogRQ attachmentLog = attachmentLogs.get(0); + SaveLogRQ attachmentLog = attachmentLogs.getFirst(); assertThat("Attachment log should have INFO level", attachmentLog.getLevel(), equalTo(LogLevel.INFO.name())); assertThat("Attachment log should have item UUID", attachmentLog.getItemUuid(), notNullValue()); assertThat("Attachment log should have log time", attachmentLog.getLogTime(), notNullValue()); @@ -95,8 +96,8 @@ public void test_embed_image_attachment(boolean report) { .flatMap(rq -> extractBinaryParts((List) rq).stream()) .collect(Collectors.toList()); assertThat(attachments, hasSize(1)); - assertThat(attachments.get(0).getKey(), equalTo("image/png")); - assertThat(attachments.get(0).getValue().length, greaterThan(0)); + assertThat(attachments.getFirst().getKey(), equalTo("image/png")); + assertThat(attachments.getFirst().getValue().length, greaterThan(0)); } } diff --git a/src/test/java/com/epam/reportportal/karate/logging/HttpRequestLoggingTest.java b/src/test/java/com/epam/reportportal/karate/logging/HttpRequestLoggingTest.java index 4664a40..d91b673 100644 --- a/src/test/java/com/epam/reportportal/karate/logging/HttpRequestLoggingTest.java +++ b/src/test/java/com/epam/reportportal/karate/logging/HttpRequestLoggingTest.java @@ -60,7 +60,7 @@ public void setupMock() { public void test_http_request_logging(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } @@ -78,9 +78,16 @@ public void test_http_request_logging(boolean report) { List messages = logs.stream().map(SaveLogRQ::getMessage).collect(Collectors.toList()); assertThat( messages, hasItems( - equalTo("Docstring:\n\n```\n{\n" + " username: 'user',\n" + " password: 'password',\n" - + " grant_type: 'password'\n" + "}\n```"), - containsString("{\"username\":\"user\",\"password\":\"password\",\"grant_type\":\"password\"}") + equalTo(""" + Docstring: + + ``` + { + username: 'user', + password: 'password', + grant_type: 'password' + } + ```"""), containsString("{\"username\":\"user\",\"password\":\"password\",\"grant_type\":\"password\"}") ) ); } diff --git a/src/test/java/com/epam/reportportal/karate/logging/SimpleFailureLoggingTest.java b/src/test/java/com/epam/reportportal/karate/logging/SimpleFailureLoggingTest.java index 673d25e..8144e5e 100644 --- a/src/test/java/com/epam/reportportal/karate/logging/SimpleFailureLoggingTest.java +++ b/src/test/java/com/epam/reportportal/karate/logging/SimpleFailureLoggingTest.java @@ -60,7 +60,7 @@ public void setupMock() { public void test_simple_one_step_failed_error_log(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } @@ -75,13 +75,14 @@ public void test_simple_one_step_failed_error_log(boolean report) { .collect(Collectors.toList()); assertThat(logs, hasSize(greaterThan(0))); - SaveLogRQ log = logs.get(logs.size() - 1); + SaveLogRQ log = logs.getLast(); assertThat(log.getItemUuid(), oneOf(stepIds.toArray(new String[0]))); assertThat(log.getLaunchUuid(), equalTo(launchUuid)); assertThat( - log.getMessage(), - equalTo("Then assert actualFour != four\n" + "did not evaluate to 'true': actualFour != four\n" - + "classpath:feature/simple_failed.feature:6") + log.getMessage(), equalTo(""" + Then assert actualFour != four + did not evaluate to 'true': actualFour != four + classpath:feature/simple_failed.feature:6""") ); } } diff --git a/src/test/java/com/epam/reportportal/karate/name/NoFeatureNameTest.java b/src/test/java/com/epam/reportportal/karate/name/NoFeatureNameTest.java index 89696c5..a160cdb 100644 --- a/src/test/java/com/epam/reportportal/karate/name/NoFeatureNameTest.java +++ b/src/test/java/com/epam/reportportal/karate/name/NoFeatureNameTest.java @@ -55,7 +55,7 @@ public void setupMock() { public void test_item_names_simple(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_NO_NAME_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_NO_NAME_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_NO_NAME_FEATURE); } diff --git a/src/test/java/com/epam/reportportal/karate/name/SimpleItemNameTest.java b/src/test/java/com/epam/reportportal/karate/name/SimpleItemNameTest.java index b7a3b24..669937a 100644 --- a/src/test/java/com/epam/reportportal/karate/name/SimpleItemNameTest.java +++ b/src/test/java/com/epam/reportportal/karate/name/SimpleItemNameTest.java @@ -58,7 +58,7 @@ public void setupMock() { public void test_item_names_simple(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } diff --git a/src/test/java/com/epam/reportportal/karate/parameters/ExamplesScenarioParametersTest.java b/src/test/java/com/epam/reportportal/karate/parameters/ExamplesScenarioParametersTest.java index 812c36e..821de51 100644 --- a/src/test/java/com/epam/reportportal/karate/parameters/ExamplesScenarioParametersTest.java +++ b/src/test/java/com/epam/reportportal/karate/parameters/ExamplesScenarioParametersTest.java @@ -42,7 +42,7 @@ public class ExamplesScenarioParametersTest { private static final String TEST_FEATURE = "classpath:feature/examples.feature"; private final String featureId = CommonUtils.namedId("feature_"); - private final List exampleIds = Stream.generate(() -> CommonUtils.namedId("example_")).limit(2).collect(Collectors.toList()); + private final List exampleIds = Stream.generate(() -> CommonUtils.namedId("example_")).limit(2).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()); @@ -61,7 +61,7 @@ public void setupMock() { public void test_examples_scenario_parameters(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } diff --git a/src/test/java/com/epam/reportportal/karate/parameters/ExamplesStepParametersTest.java b/src/test/java/com/epam/reportportal/karate/parameters/ExamplesStepParametersTest.java index c961b8d..3f6d96c 100644 --- a/src/test/java/com/epam/reportportal/karate/parameters/ExamplesStepParametersTest.java +++ b/src/test/java/com/epam/reportportal/karate/parameters/ExamplesStepParametersTest.java @@ -50,7 +50,7 @@ public class ExamplesStepParametersTest { private static final String TEST_FEATURE = "classpath:feature/examples.feature"; private final String featureId = CommonUtils.namedId("feature_"); - private final List exampleIds = Stream.generate(() -> CommonUtils.namedId("example_")).limit(2).collect(Collectors.toList()); + private final List exampleIds = Stream.generate(() -> CommonUtils.namedId("example_")).limit(2).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()); @@ -74,7 +74,7 @@ public void setupMock() { public void test_examples_parameters_for_steps(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } @@ -89,7 +89,7 @@ public void test_examples_parameters_for_steps(boolean report) { verify(client, times(2)).startTestItem(same(exampleIds.get(1)), secondExampleCaptor.capture()); List firstSteps = firstExampleCaptor.getAllValues(); - Set parameterStrings = toParameterStringList(firstSteps.get(0).getParameters()); + Set parameterStrings = toParameterStringList(firstSteps.getFirst().getParameters()); assertThat(parameterStrings, hasSize(2)); assertThat(parameterStrings, allOf(hasItem("vara:2"), hasItem("varb:2"))); parameterStrings = toParameterStringList(firstSteps.get(1).getParameters()); @@ -97,7 +97,7 @@ public void test_examples_parameters_for_steps(boolean report) { assertThat(parameterStrings, hasItem("result:4")); List secondSteps = secondExampleCaptor.getAllValues(); - parameterStrings = toParameterStringList(secondSteps.get(0).getParameters()); + parameterStrings = toParameterStringList(secondSteps.getFirst().getParameters()); assertThat(parameterStrings, hasSize(2)); assertThat(parameterStrings, allOf(hasItem("vara:1"), hasItem("varb:2"))); parameterStrings = toParameterStringList(secondSteps.get(1).getParameters()); diff --git a/src/test/java/com/epam/reportportal/karate/parameters/NoParametersTest.java b/src/test/java/com/epam/reportportal/karate/parameters/NoParametersTest.java index e98814f..81b1588 100644 --- a/src/test/java/com/epam/reportportal/karate/parameters/NoParametersTest.java +++ b/src/test/java/com/epam/reportportal/karate/parameters/NoParametersTest.java @@ -57,7 +57,7 @@ public void setupMock() { public void test_no_parameters_reporting(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } diff --git a/src/test/java/com/epam/reportportal/karate/parameters/NullValueExamplesTest.java b/src/test/java/com/epam/reportportal/karate/parameters/NullValueExamplesTest.java index 0267591..0125172 100644 --- a/src/test/java/com/epam/reportportal/karate/parameters/NullValueExamplesTest.java +++ b/src/test/java/com/epam/reportportal/karate/parameters/NullValueExamplesTest.java @@ -43,7 +43,7 @@ public class NullValueExamplesTest { private static final String TEST_FEATURE = "classpath:feature/null_examples.feature"; private final String featureId = CommonUtils.namedId("feature_"); - private final List exampleIds = Stream.generate(() -> CommonUtils.namedId("example_")).limit(1).collect(Collectors.toList()); + private final List exampleIds = Stream.generate(() -> CommonUtils.namedId("example_")).limit(1).toList(); private final List>> stepIds = exampleIds.stream() .map(e -> Pair.of(e, Stream.generate(() -> CommonUtils.namedId("step_")).limit(1).collect(Collectors.toList()))) .collect(Collectors.toList()); @@ -62,7 +62,7 @@ public void setupMock() { public void test_examples_null_value(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } @@ -71,7 +71,7 @@ public void test_examples_null_value(boolean report) { 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(1)).startTestItem(same(exampleIds.get(0)), captor.capture()); + verify(client, times(1)).startTestItem(same(exampleIds.getFirst()), captor.capture()); List items = captor.getAllValues(); assertThat(items, hasSize(3)); diff --git a/src/test/java/com/epam/reportportal/karate/parameters/TableParametersTest.java b/src/test/java/com/epam/reportportal/karate/parameters/TableParametersTest.java index e0fb7c2..0b08c5d 100644 --- a/src/test/java/com/epam/reportportal/karate/parameters/TableParametersTest.java +++ b/src/test/java/com/epam/reportportal/karate/parameters/TableParametersTest.java @@ -62,7 +62,7 @@ public void setupMock() { public void test_table_parameters_reporting(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } @@ -85,7 +85,7 @@ public void test_table_parameters_reporting(boolean report) { .filter(rq -> LogLevel.INFO.name().equals(rq.getLevel())) .collect(Collectors.toList()); assertThat(logs, hasSize(1)); - assertThat(logs.get(0).getMessage(), startsWith("Table:\n\n")); - assertThat(logs.get(0).getItemUuid(), startsWith("step_")); + assertThat(logs.getFirst().getMessage(), startsWith("Table:\n\n")); + assertThat(logs.getFirst().getItemUuid(), startsWith("step_")); } } diff --git a/src/test/java/com/epam/reportportal/karate/status/OneExampleFailedTest.java b/src/test/java/com/epam/reportportal/karate/status/OneExampleFailedTest.java index 60ac93f..73f094c 100644 --- a/src/test/java/com/epam/reportportal/karate/status/OneExampleFailedTest.java +++ b/src/test/java/com/epam/reportportal/karate/status/OneExampleFailedTest.java @@ -42,7 +42,7 @@ public class OneExampleFailedTest { private static final String TEST_FEATURE = "classpath:feature/examples_one_failed.feature"; private final String featureId = CommonUtils.namedId("feature_"); - private final List exampleIds = Stream.generate(() -> CommonUtils.namedId("example_")).limit(2).collect(Collectors.toList()); + private final List exampleIds = Stream.generate(() -> CommonUtils.namedId("example_")).limit(2).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()); @@ -71,7 +71,7 @@ private static void verifyStatus(List rqs, ItemStatus... statu public void test_simple_one_step_failed(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } @@ -84,7 +84,7 @@ public void test_simple_one_step_failed(boolean report) { ArgumentCaptor secondExampleCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); verify(client).finishTestItem(same(exampleIds.get(1)), secondExampleCaptor.capture()); ArgumentCaptor firstExampleFirstStepCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); - verify(client).finishTestItem(same(stepIds.get(0).getValue().get(0)), firstExampleFirstStepCaptor.capture()); + verify(client).finishTestItem(same(stepIds.getFirst().getValue().getFirst()), firstExampleFirstStepCaptor.capture()); ArgumentCaptor firstExampleSecondStepCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); verify(client).finishTestItem(same(stepIds.get(0).getValue().get(1)), firstExampleSecondStepCaptor.capture()); ArgumentCaptor secondExampleFirstStepCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); diff --git a/src/test/java/com/epam/reportportal/karate/status/OneExampleWithBackgroundFailedTest.java b/src/test/java/com/epam/reportportal/karate/status/OneExampleWithBackgroundFailedTest.java index 62af211..dc077dd 100644 --- a/src/test/java/com/epam/reportportal/karate/status/OneExampleWithBackgroundFailedTest.java +++ b/src/test/java/com/epam/reportportal/karate/status/OneExampleWithBackgroundFailedTest.java @@ -45,13 +45,16 @@ public class OneExampleWithBackgroundFailedTest { private static final String TEST_FEATURE = "classpath:feature/examples_one_failed_with_background.feature"; private final String featureId = CommonUtils.namedId("feature_"); - private final List exampleIds = Stream.generate(() -> CommonUtils.namedId("example_")).limit(2).collect(Collectors.toList()); + private final List exampleIds = Stream.generate(() -> CommonUtils.namedId("example_")).limit(2).toList(); private final List>> stepIds = exampleIds.stream() .map(e -> Pair.of(e, Stream.generate(() -> CommonUtils.namedId("step_")).limit(3).collect(Collectors.toList()))) .collect(Collectors.toList()); private final List> nestedSteps = Arrays.asList( - Pair.of(stepIds.get(0).getValue().get(0), CommonUtils.namedId("nested_step_")), - Pair.of(stepIds.get(1).getValue().get(0), CommonUtils.namedId("nested_step_")) + Pair.of( + stepIds.getFirst().getValue().getFirst(), + CommonUtils.namedId("nested_step_") + ), + Pair.of(stepIds.get(1).getValue().getFirst(), CommonUtils.namedId("nested_step_")) ); private final ReportPortalClient client = mock(ReportPortalClient.class); @@ -66,7 +69,7 @@ public void setupMock() { private static void verifyStatus(List rqs, ItemStatus... statuses) { List actualStatuses = rqs.stream().map(FinishExecutionRQ::getStatus).collect(Collectors.toList()); - List expectedStatuses = Arrays.stream(statuses).map(ItemStatus::name).collect(Collectors.toList()); + List expectedStatuses = Arrays.stream(statuses).map(ItemStatus::name).toList(); assertThat("Failed verifying status number", actualStatuses, hasSize(rqs.size())); // Status for the last item may come in different order, that's OK. @@ -84,7 +87,7 @@ private static void verifyStatus(List rqs, ItemStatus... statu public void test_simple_one_step_failed(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } @@ -97,9 +100,9 @@ public void test_simple_one_step_failed(boolean report) { ArgumentCaptor secondExampleCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); verify(client).finishTestItem(same(exampleIds.get(1)), secondExampleCaptor.capture()); ArgumentCaptor firstExampleFirstStepCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); - verify(client).finishTestItem(same(stepIds.get(0).getValue().get(0)), firstExampleFirstStepCaptor.capture()); + verify(client).finishTestItem(same(stepIds.getFirst().getValue().get(0)), firstExampleFirstStepCaptor.capture()); ArgumentCaptor firstExampleSecondStepCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); - verify(client).finishTestItem(same(stepIds.get(0).getValue().get(1)), firstExampleSecondStepCaptor.capture()); + verify(client).finishTestItem(same(stepIds.getFirst().getValue().get(1)), firstExampleSecondStepCaptor.capture()); ArgumentCaptor firstExampleThirdStepCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); verify(client).finishTestItem(same(stepIds.get(0).getValue().get(2)), firstExampleThirdStepCaptor.capture()); ArgumentCaptor secondExampleFirstStepCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); diff --git a/src/test/java/com/epam/reportportal/karate/status/SimpleAllPassedTest.java b/src/test/java/com/epam/reportportal/karate/status/SimpleAllPassedTest.java index 9aa6943..9eb4d16 100644 --- a/src/test/java/com/epam/reportportal/karate/status/SimpleAllPassedTest.java +++ b/src/test/java/com/epam/reportportal/karate/status/SimpleAllPassedTest.java @@ -59,7 +59,7 @@ public void setupMock() { public void test_simple_all_passed(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } @@ -71,7 +71,7 @@ public void test_simple_all_passed(boolean report) { verify(client).finishTestItem(same(scenarioId), scenarioCaptor.capture()); List> stepCaptors = Stream.generate(() -> ArgumentCaptor.forClass(FinishTestItemRQ.class)) .limit(stepIds.size()) - .collect(Collectors.toList()); + .toList(); IntStream.range(0, stepIds.size()).forEach(i -> verify(client).finishTestItem(same(stepIds.get(i)), stepCaptors.get(i).capture())); FinishTestItemRQ featureRq = featureCaptor.getValue(); diff --git a/src/test/java/com/epam/reportportal/karate/status/SimpleOneStepFailedTest.java b/src/test/java/com/epam/reportportal/karate/status/SimpleOneStepFailedTest.java index fbd9420..bebcf1f 100644 --- a/src/test/java/com/epam/reportportal/karate/status/SimpleOneStepFailedTest.java +++ b/src/test/java/com/epam/reportportal/karate/status/SimpleOneStepFailedTest.java @@ -60,7 +60,7 @@ public void setupMock() { public void test_simple_one_step_failed(boolean report) { SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { results = TestUtils.runAsEventListener(rp, TEST_FEATURE); } @@ -72,7 +72,7 @@ public void test_simple_one_step_failed(boolean report) { verify(client).finishTestItem(same(scenarioId), scenarioCaptor.capture()); List> stepCaptors = Stream.generate(() -> ArgumentCaptor.forClass(FinishTestItemRQ.class)) .limit(stepIds.size()) - .collect(Collectors.toList()); + .toList(); IntStream.range(0, stepIds.size()).forEach(i -> verify(client).finishTestItem(same(stepIds.get(i)), stepCaptors.get(i).capture())); FinishTestItemRQ featureRq = featureCaptor.getValue(); @@ -86,7 +86,7 @@ public void test_simple_one_step_failed(boolean report) { assertThat(scenarioRq.getLaunchUuid(), allOf(notNullValue(), equalTo(launchUuid))); assertThat(scenarioRq.getEndTime(), notNullValue()); - List steps = stepCaptors.stream().map(ArgumentCaptor::getValue).collect(Collectors.toList()); + List steps = stepCaptors.stream().map(ArgumentCaptor::getValue).toList(); steps.forEach(step -> { assertThat(step.getLaunchUuid(), allOf(notNullValue(), equalTo(launchUuid))); assertThat(step.getEndTime(), notNullValue()); diff --git a/src/test/java/com/epam/reportportal/karate/tags/SimpleTagInclusionTest.java b/src/test/java/com/epam/reportportal/karate/tags/SimpleTagInclusionTest.java index 96fd67e..13928ec 100644 --- a/src/test/java/com/epam/reportportal/karate/tags/SimpleTagInclusionTest.java +++ b/src/test/java/com/epam/reportportal/karate/tags/SimpleTagInclusionTest.java @@ -63,7 +63,7 @@ public void test_simple_all_passed(boolean report) { List tagsToRun = Collections.singletonList("scope=smoke"); SuiteResult results; if (report) { - results = TestUtils.runAsReportListener(rp, tagsToRun, TEST_FEATURES); + results = TestUtils.runAsResultListener(rp, tagsToRun, TEST_FEATURES); } else { results = TestUtils.runAsEventListener(rp, tagsToRun, TEST_FEATURES); } @@ -82,7 +82,7 @@ public void test_simple_all_passed(boolean report) { verify(client).finishTestItem(same(scenarioId), scenarioFinishCaptor.capture()); List> stepFinishCaptors = Stream.generate(() -> ArgumentCaptor.forClass(FinishTestItemRQ.class)) .limit(stepIds.size()) - .collect(Collectors.toList()); + .toList(); IntStream.range(0, stepIds.size()) .forEach(i -> verify(client).finishTestItem(same(stepIds.get(i)), stepFinishCaptors.get(i).capture())); diff --git a/src/test/java/com/epam/reportportal/karate/timing/SimpleTimingTest.java b/src/test/java/com/epam/reportportal/karate/timing/SimpleTimingTest.java index ce278ad..6d9ec85 100644 --- a/src/test/java/com/epam/reportportal/karate/timing/SimpleTimingTest.java +++ b/src/test/java/com/epam/reportportal/karate/timing/SimpleTimingTest.java @@ -73,7 +73,7 @@ public void test_each_item_has_correct_start_date(boolean report, boolean useMic if (useMicroseconds) { when(client.getApiInfo()).thenReturn(Maybe.just(TestUtils.testApiInfo())); } - results = TestUtils.runAsReportListener(rp, TEST_FEATURE); + results = TestUtils.runAsResultListener(rp, TEST_FEATURE); } else { if (useMicroseconds) { when(client.getApiInfo()).thenReturn(Maybe.just(TestUtils.testApiInfo())); diff --git a/src/test/java/com/epam/reportportal/karate/utils/TestUtils.java b/src/test/java/com/epam/reportportal/karate/utils/TestUtils.java index bd59733..34156e2 100644 --- a/src/test/java/com/epam/reportportal/karate/utils/TestUtils.java +++ b/src/test/java/com/epam/reportportal/karate/utils/TestUtils.java @@ -68,7 +68,7 @@ public static ExecutorService testExecutor() { }); } - public static SuiteResult runAsReportListener(ReportPortal reportPortal, List tags, String... paths) { + public static SuiteResult runAsResultListener(ReportPortal reportPortal, List tags, String... paths) { ReportPortalResultListener listener = new ReportPortalResultListener(reportPortal); Runner.Builder path = Runner.path(paths).resultListener(listener).outputCucumberJson(false); SuiteResult result = path.tags(tags.toArray(new String[0])).parallel(1); @@ -76,8 +76,8 @@ public static SuiteResult runAsReportListener(ReportPortal reportPortal, List tags, String... paths) { @@ -141,7 +141,7 @@ public static > void mockFeatures(@Nonnull final Re if (features.isEmpty()) { return; } - String firstFeature = features.get(0).getKey(); + String firstFeature = features.getFirst().getKey(); Maybe first = Maybe.just(new ItemCreatedRS(firstFeature, firstFeature)); Maybe[] other = (Maybe[]) features.subList(1, features.size()) .stream() @@ -163,9 +163,9 @@ public static > void mockScenario(@Nonnull final Re List> testResponses = scenarioSteps.stream() .map(Pair::getKey) .map(uuid -> Maybe.just(new ItemCreatedRS(uuid, uuid))) - .collect(Collectors.toList()); + .toList(); - Maybe first = testResponses.get(0); + Maybe first = testResponses.getFirst(); Maybe[] other = testResponses.subList(1, testResponses.size()).toArray(new Maybe[0]); when(client.startTestItem(same(featureUuid), any())).thenReturn(first, other); @@ -174,10 +174,10 @@ public static > void mockScenario(@Nonnull final Re List> stepResponses = test.getValue() .stream() .map(uuid -> Maybe.just(new ItemCreatedRS(uuid, uuid))) - .collect(Collectors.toList()); + .toList(); when(client.finishTestItem(same(scenarioUuid), any())).thenReturn(Maybe.just(new OperationCompletionRS())); if (!stepResponses.isEmpty()) { - Maybe myFirst = stepResponses.get(0); + Maybe myFirst = stepResponses.getFirst(); Maybe[] myOther = stepResponses.subList(1, stepResponses.size()).toArray(new Maybe[0]); when(client.startTestItem(same(scenarioUuid), any())).thenReturn(myFirst, myOther); new HashSet<>(test.getValue()).forEach(testMethodUuid -> when(client.finishTestItem( @@ -198,11 +198,9 @@ public static void mockNestedSteps(final ReportPortalClient client, final List

> responseOrders = parentNestedPairs.stream() .collect(Collectors.groupingBy(Pair::getKey, Collectors.mapping(Pair::getValue, Collectors.toList()))); responseOrders.forEach((k, v) -> { - List> responses = v.stream() - .map(uuid -> Maybe.just(new ItemCreatedRS(uuid, uuid))) - .collect(Collectors.toList()); + List> responses = v.stream().map(uuid -> Maybe.just(new ItemCreatedRS(uuid, uuid))).toList(); - Maybe first = responses.get(0); + Maybe first = responses.getFirst(); Maybe[] other = responses.subList(1, responses.size()).toArray(new Maybe[0]); when(client.startTestItem(eq(k), any())).thenReturn(first, other); }); From 777da8b77f44a2651aac8e2f4031feba8e447815 Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Sat, 25 Apr 2026 16:54:29 +0300 Subject: [PATCH 08/19] Fix javadocs --- .../karate/ReportPortalResultListener.java | 115 ++++++++++++++---- .../karate/ReportPortalRunListener.java | 112 +++++++++++++++-- .../karate/ReportPortalUtils.java | 64 +++++++++- .../utils/BlockingConcurrentHashMap.java | 24 ++++ 4 files changed, 280 insertions(+), 35 deletions(-) diff --git a/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java b/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java index f61c74c..2679c38 100644 --- a/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java +++ b/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java @@ -53,10 +53,13 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank; /** - * ReportPortal test results reporting listener for Karate. + * ReportPortal result listener for Karate that reports completed execution output. */ public class ReportPortalResultListener implements ResultListener { private static final Logger LOGGER = LoggerFactory.getLogger(ReportPortalResultListener.class); + /** + * Lazily initialized ReportPortal launch facade used for all item operations. + */ protected final MemoizingSupplier launch; private final BlockingConcurrentHashMap>> featureIdMap = new BlockingConcurrentHashMap<>(); private final Map> scenarioIdMap = new ConcurrentHashMap<>(); @@ -68,9 +71,9 @@ public class ReportPortalResultListener implements ResultListener { private volatile Thread shutDownHook; /** - * Create a new instance of the ReportPortalHook with the specified ReportPortal instance. + * Creates a listener instance backed by the provided ReportPortal client. * - * @param reportPortal the ReportPortal instance + * @param reportPortal ReportPortal client instance */ public ReportPortalResultListener(ReportPortal reportPortal) { ListenerParameters params = reportPortal.getParameters(); @@ -85,13 +88,18 @@ public ReportPortalResultListener(ReportPortal reportPortal) { } /** - * Default constructor. Create a new instance of the ReportPortalHook with default ReportPortal instance. + * Creates a listener with a default ReportPortal client configuration. */ @SuppressWarnings("unused") public ReportPortalResultListener() { this(ReportPortal.builder().build()); } + /** + * Creates a listener with a preconfigured launch supplier. + * + * @param launchSupplier launch supplier used to lazily initialize launch interactions + */ @SuppressWarnings("unused") public ReportPortalResultListener(Supplier launchSupplier) { launch = new MemoizingSupplier<>(launchSupplier); @@ -108,9 +116,9 @@ protected StartLaunchRQ buildStartLaunchRq(ListenerParameters parameters) { } /** - * Customize start Launch finish event/request. + * Customizes the launch finish request. * - * @param parameters Launch configuration parameters + * @param parameters launch configuration parameters * @return request to ReportPortal */ @Nonnull @@ -128,7 +136,7 @@ public void finishLaunch() { /** * Build ReportPortal request for start Feature event. * - * @param fr Karate's FeatureRuntime object instance + * @param fr Karate feature descriptor * @return request to ReportPortal */ @Nonnull @@ -136,10 +144,21 @@ protected StartTestItemRQ buildStartFeatureRq(@Nonnull Feature fr) { return ReportPortalUtils.buildStartFeatureRq(fr); } + /** + * Builds a unique feature key that includes parent scenario nesting depth. + * + * @param feature feature descriptor + * @return depth-qualified feature name + */ private String getFeatureNameForReport(Feature feature) { return parentScenarios.get().size() + ":" + feature.getNameForReport(); } + /** + * Starts a feature item in ReportPortal. + * + * @param feature feature descriptor + */ @Override public void onFeatureStart(Feature feature) { Scenario parentScenario = parentScenarios.get().peekLast(); @@ -171,7 +190,7 @@ public void onFeatureStart(Feature feature) { /** * Build ReportPortal request for finish Feature event. * - * @param fr Karate's FeatureRuntime object instance + * @param fr Karate feature result * @return request to ReportPortal */ @Nonnull @@ -179,6 +198,11 @@ protected FinishTestItemRQ buildFinishFeatureRq(@Nonnull FeatureResult fr) { return buildFinishTestItemRq(Instant.now(), fr.isFailed() ? ItemStatus.FAILED : ItemStatus.PASSED); } + /** + * Finishes a feature item in ReportPortal. + * + * @param fr feature result + */ @Override public void onFeatureEnd(FeatureResult fr) { Optional> optionalId = ofNullable(featureIdMap.get(getFeatureNameForReport(fr.getFeature()))).map(Supplier::get); @@ -195,7 +219,7 @@ public void onFeatureEnd(FeatureResult fr) { /** * Build ReportPortal request for start Scenario event. * - * @param sr Karate's ScenarioRuntime object instance + * @param sr Karate scenario descriptor * @return request to ReportPortal */ @Nonnull @@ -211,6 +235,11 @@ protected StartTestItemRQ buildStartScenarioRq(@Nonnull Scenario sr) { return rq; } + /** + * Starts a scenario item in ReportPortal. + * + * @param scenario scenario descriptor + */ @Override public void onScenarioStart(Scenario scenario) { StartTestItemRQ rq = buildStartScenarioRq(scenario); @@ -235,7 +264,7 @@ public void onScenarioStart(Scenario scenario) { /** * Build ReportPortal request for finish Scenario event. * - * @param sr Karate's ScenarioRuntime object instance + * @param sr Karate scenario result * @return request to ReportPortal */ @Nonnull @@ -246,8 +275,9 @@ protected FinishTestItemRQ buildFinishScenarioRq(@Nonnull ScenarioResult sr) { /** * Build ReportPortal request for start Background event. * - * @param step Karate's Step object instance - * @param sr Karate's ScenarioRuntime object instance + * @param startTime background start time + * @param step Karate step descriptor + * @param sr Karate scenario descriptor * @return request to ReportPortal */ @Nonnull @@ -258,8 +288,9 @@ protected StartTestItemRQ buildStartBackgroundRq(Instant startTime, @Nonnull Ste /** * Start sending Background data to ReportPortal. * - * @param step Karate's Step object instance - * @param sr Karate's ScenarioRuntime object instance + * @param startTime background start time + * @param step Karate step descriptor + * @param sr Karate scenario descriptor * @return item ID Future */ public Maybe startBackground(Instant startTime, @Nonnull Step step, @Nonnull Scenario sr) { @@ -274,8 +305,8 @@ public Maybe startBackground(Instant startTime, @Nonnull Step step, @Non /** * Build ReportPortal request for finish Background event. * - * @param stepResult Karate's StepResult class instance - * @param sr Karate's ScenarioRuntime object instance + * @param stepResult Karate step result + * @param sr Karate scenario result * @return request to ReportPortal */ @Nonnull @@ -288,10 +319,10 @@ protected FinishTestItemRQ buildFinishBackgroundRq(@Nullable StepResult stepResu } /** - * Finish sending Scenario data to ReportPortal. + * Finishes the background item for a scenario, if it was started. * - * @param stepResult Karate's StepResult class instance - * @param sr Karate's ScenarioRuntime object instance + * @param stepResult step result that completed the background flow + * @param sr scenario result */ public void finishBackground(@Nullable StepResult stepResult, @Nonnull ScenarioResult sr) { String uniqueId = sr.getScenario().getUniqueId(); @@ -307,6 +338,7 @@ public void finishBackground(@Nullable StepResult stepResult, @Nonnull ScenarioR /** * Embed an attachment to ReportPortal. * + * @param time log time * @param itemId item ID future * @param embed Karate's Embed object */ @@ -314,6 +346,11 @@ protected void embedAttachment(@Nonnull Instant time, @Nonnull Maybe ite ReportPortalUtils.embedAttachment(time, itemId, embed); } + /** + * Replays collected step results and finishes the scenario in ReportPortal. + * + * @param sr scenario result + */ @Override public void onScenarioEnd(ScenarioResult sr) { Scenario scenario = sr.getScenario(); @@ -339,8 +376,9 @@ public void onScenarioEnd(ScenarioResult sr) { /** * Customize start Step test item event/request. * - * @param step Karate's Step object instance - * @param sr Karate's ScenarioRuntime object instance + * @param startTime step start time + * @param step Karate step descriptor + * @param sr Karate scenario descriptor * @return request to ReportPortal */ @Nonnull @@ -353,6 +391,7 @@ protected StartTestItemRQ buildStartStepRq(Instant startTime, @Nonnull Step step /** * Send Step logs to ReportPortal. * + * @param time log time * @param itemId item ID future * @param message log message to send * @param level log level @@ -361,6 +400,12 @@ protected void sendLog(Instant time, Maybe itemId, String message, LogLe ReportPortalUtils.sendLog(itemId, message, level, time); } + /** + * Starts a step item and emits step input details. + * + * @param stepResult step execution result + * @param sr scenario result + */ public void beforeStep(StepResult stepResult, ScenarioResult sr) { Step step = stepResult.getStep(); Scenario scenario = sr.getScenario(); @@ -399,7 +444,7 @@ public void beforeStep(StepResult stepResult, ScenarioResult sr) { * Send Step execution results to ReportPortal. * * @param stepResult step execution results - * @param sr Karate's ScenarioRuntime object instance + * @param sr Karate scenario result */ public void sendStepResults(StepResult stepResult, ScenarioResult sr) { List embeds = ofNullable(stepResult.getEmbeds()).orElse(Collections.emptyList()); @@ -437,8 +482,8 @@ public void sendStepResults(StepResult stepResult, ScenarioResult sr) { /** * Build ReportPortal request for finish Step event. * - * @param stepResult Karate's StepResult class instance - * @param sr Karate's ScenarioRuntime object instance + * @param stepResult Karate step result + * @param sr Karate scenario result * @return request to ReportPortal */ @Nonnull @@ -448,6 +493,12 @@ protected FinishTestItemRQ buildFinishStepRq(@Nonnull StepResult stepResult, @No return buildFinishTestItemRq(endTime, getStepStatus(stepResult.getStatus())); } + /** + * Aggregates background status across background steps. + * + * @param stepResult background step result + * @param sr scenario result + */ private void saveBackgroundStatus(@Nonnull StepResult stepResult, @Nonnull ScenarioResult sr) { backgroundStatusMap.put( sr.getScenario().getUniqueId(), @@ -458,6 +509,12 @@ private void saveBackgroundStatus(@Nonnull StepResult stepResult, @Nonnull Scena ); } + /** + * Finishes a step item and sends corresponding step output. + * + * @param stepResult step execution result + * @param sr scenario result + */ public void afterStep(StepResult stepResult, ScenarioResult sr) { boolean background = stepResult.getStep().isBackground(); if (!background) { @@ -478,11 +535,21 @@ public void afterStep(StepResult stepResult, ScenarioResult sr) { launch.get().finishTestItem(stepId, rq); } + /** + * Initializes the launch at suite start. + * + * @param suite suite descriptor + */ @Override public void onSuiteStart(Suite suite) { launch.get(); // Trigger launch start } + /** + * Karate suite callback after execution. + * + * @param suite suite result + */ @Override public void onSuiteEnd(SuiteResult suite) { // Omit Suite logic, since there is no Suite names in Karate diff --git a/src/main/java/com/epam/reportportal/karate/ReportPortalRunListener.java b/src/main/java/com/epam/reportportal/karate/ReportPortalRunListener.java index f24852b..00b425c 100644 --- a/src/main/java/com/epam/reportportal/karate/ReportPortalRunListener.java +++ b/src/main/java/com/epam/reportportal/karate/ReportPortalRunListener.java @@ -56,10 +56,13 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank; /** - * ReportPortal test run reporting listener for Karate. This class publish results in the process of test pass. + * ReportPortal run listener for Karate that streams runtime events directly to ReportPortal. */ public class ReportPortalRunListener implements RunListener { private static final Logger LOGGER = LoggerFactory.getLogger(ReportPortalRunListener.class); + /** + * Lazily initialized ReportPortal launch facade used for all item operations. + */ protected final MemoizingSupplier launch; private final BlockingConcurrentHashMap>> featureIdMap = new BlockingConcurrentHashMap<>(); private final Map> scenarioIdMap = new ConcurrentHashMap<>(); @@ -71,9 +74,9 @@ public class ReportPortalRunListener implements RunListener { private volatile Thread shutDownHook; /** - * Create a new instance of the ReportPortalHook with the specified ReportPortal instance. + * Creates a listener instance backed by the provided ReportPortal client. * - * @param reportPortal the ReportPortal instance + * @param reportPortal ReportPortal client instance */ public ReportPortalRunListener(ReportPortal reportPortal) { ListenerParameters params = reportPortal.getParameters(); @@ -88,13 +91,18 @@ public ReportPortalRunListener(ReportPortal reportPortal) { } /** - * Default constructor. Create a new instance of the ReportPortalHook with default ReportPortal instance. + * Creates a listener with a default ReportPortal client configuration. */ @SuppressWarnings("unused") public ReportPortalRunListener() { this(ReportPortal.builder().build()); } + /** + * Creates a listener with a preconfigured launch supplier. + * + * @param launchSupplier launch supplier used to lazily initialize launch interactions + */ @SuppressWarnings("unused") public ReportPortalRunListener(Supplier launchSupplier) { launch = new MemoizingSupplier<>(launchSupplier); @@ -111,9 +119,9 @@ protected StartLaunchRQ buildStartLaunchRq(ListenerParameters parameters) { } /** - * Customize start Launch finish event/request. + * Customizes the launch finish request. * - * @param parameters Launch configuration parameters + * @param parameters launch configuration parameters * @return request to ReportPortal */ @Nonnull @@ -149,6 +157,12 @@ protected StartTestItemRQ buildStartFeatureRq(@Nonnull FeatureRuntime fr) { return rq; } + /** + * Calculates feature nesting depth for called features. + * + * @param fr feature runtime + * @return nesting depth where 0 means a top-level feature + */ private int getDepth(FeatureRuntime fr) { var caller = fr.getCallerScenario(); if (caller == null) { @@ -162,11 +176,22 @@ private int getDepth(FeatureRuntime fr) { return depth; } + /** + * Builds a unique feature key that includes call depth. + * + * @param fr feature runtime + * @return depth-qualified feature name + */ private String getFeatureNameForReport(FeatureRuntime fr) { int callDepth = getDepth(fr); return callDepth + ":" + fr.getFeature().getNameForReport(); } + /** + * Starts a feature item in ReportPortal. + * + * @param fr feature runtime + */ public void beforeFeature(FeatureRuntime fr) { StartTestItemRQ rq = buildStartFeatureRq(fr); featureIdMap.computeIfAbsent( @@ -204,6 +229,11 @@ protected FinishTestItemRQ buildFinishFeatureRq(@Nonnull FeatureRuntime fr) { return buildFinishTestItemRq(Instant.now(), fr.getResult().isFailed() ? ItemStatus.FAILED : ItemStatus.PASSED); } + /** + * Finishes a feature item in ReportPortal. + * + * @param fr feature runtime + */ public void afterFeature(FeatureRuntime fr) { Optional> optionalId = ofNullable(featureIdMap.get(getFeatureNameForReport(fr))).map(Supplier::get); if (optionalId.isEmpty()) { @@ -235,6 +265,11 @@ protected StartTestItemRQ buildStartScenarioRq(@Nonnull ScenarioRuntime sr) { return rq; } + /** + * Starts a scenario item in ReportPortal. + * + * @param sr scenario runtime + */ public void beforeScenario(ScenarioRuntime sr) { StartTestItemRQ rq = buildStartScenarioRq(sr); Optional> optionalId = ofNullable(featureIdMap.get(getFeatureNameForReport(sr.getFeatureRuntime()))).map(Supplier::get); @@ -310,10 +345,10 @@ protected FinishTestItemRQ buildFinishBackgroundRq(@Nullable StepResult stepResu } /** - * Finish sending Scenario data to ReportPortal. + * Finishes the background item for a scenario, if it was started. * - * @param stepResult Karate's StepResult class instance - * @param sr Karate's ScenarioRuntime object instance + * @param stepResult step result that completed the background flow + * @param sr scenario runtime */ public void finishBackground(@Nullable StepResult stepResult, @Nonnull ScenarioRuntime sr) { String uniqueId = sr.getScenario().getUniqueId(); @@ -335,6 +370,11 @@ protected void embedAttachment(@Nonnull Maybe itemId, @Nonnull StepResul ReportPortalUtils.embedAttachment(Instant.now(), itemId, embed); } + /** + * Finishes a scenario item in ReportPortal. + * + * @param sr scenario runtime + */ public void afterScenario(ScenarioRuntime sr) { String uniqueId = sr.getScenario().getUniqueId(); Maybe scenarioId = scenarioIdMap.get(uniqueId); @@ -389,6 +429,12 @@ protected void sendLog(Maybe itemId, String message, LogLevel level) { ReportPortalUtils.sendLog(itemId, message, level); } + /** + * Starts a step item and emits step input details. + * + * @param step step definition + * @param sr scenario runtime + */ public void beforeStep(Step step, ScenarioRuntime sr) { boolean background = step.isBackground(); Maybe backgroundId = null; @@ -443,6 +489,12 @@ protected FinishTestItemRQ buildFinishStepRq(@Nonnull StepResult stepResult, @No return buildFinishTestItemRq(Instant.now(), getStepStatus(stepResult.getStatus())); } + /** + * Aggregates background status across background steps. + * + * @param stepResult background step result + * @param sr scenario runtime + */ private void saveBackgroundStatus(@Nonnull StepResult stepResult, @Nonnull ScenarioRuntime sr) { String scenarioId = sr.getScenario().getUniqueId(); backgroundStatusMap.put( @@ -451,6 +503,12 @@ private void saveBackgroundStatus(@Nonnull StepResult stepResult, @Nonnull Scena ); } + /** + * Finishes a step item and sends corresponding step output. + * + * @param stepResult step execution result + * @param sr scenario runtime + */ public void afterStep(StepResult stepResult, ScenarioRuntime sr) { boolean background = stepResult.getStep().isBackground(); if (!background) { @@ -472,29 +530,65 @@ public void afterStep(StepResult stepResult, ScenarioRuntime sr) { launch.get().finishTestItem(stepId, rq); } + /** + * Publishes an unexpected runtime error stack trace to ReportPortal. + * + * @param timestamp error timestamp + * @param error runtime error + * @param sr scenario runtime + */ @SuppressWarnings("unused") public void sendErrorResults(long timestamp, Throwable error, ScenarioRuntime sr) { ReportPortal.sendStackTraceToRP(error); } + /** + * Karate HTTP callback executed before HTTP invocation. + * + * @param request HTTP request + * @param sr scenario runtime + */ @SuppressWarnings("unused") public void beforeHttpCall(HttpRequest request, ScenarioRuntime sr) { } + /** + * Karate HTTP callback executed after HTTP invocation. + * + * @param request HTTP request + * @param response HTTP response + * @param sr scenario runtime + */ @SuppressWarnings("unused") public void afterHttpCall(HttpRequest request, HttpResponse response, ScenarioRuntime sr) { } + /** + * Karate suite callback before execution. + * + * @param suite suite descriptor + */ @SuppressWarnings("unused") public void beforeSuite(Suite suite) { // Omit Suite logic, since there is no Suite names in Karate } + /** + * Karate suite callback after execution. + * + * @param suite suite result + */ @SuppressWarnings("unused") public void afterSuite(SuiteResult suite) { // Omit Suite logic, since there is no Suite names in Karate } + /** + * Handles Karate runtime events and delegates to ReportPortal lifecycle methods. + * + * @param event Karate runtime event + * @return {@code true} to keep event processing active + */ @Override @SuppressWarnings("UnnecessaryDefault") public boolean onEvent(RunEvent event) { diff --git a/src/main/java/com/epam/reportportal/karate/ReportPortalUtils.java b/src/main/java/com/epam/reportportal/karate/ReportPortalUtils.java index fb4d6b7..e077f21 100644 --- a/src/main/java/com/epam/reportportal/karate/ReportPortalUtils.java +++ b/src/main/java/com/epam/reportportal/karate/ReportPortalUtils.java @@ -56,19 +56,52 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank; /** - * Set of useful utils related to Karate -> ReportPortal integration + * Utility methods for mapping Karate runtime entities to ReportPortal API requests. */ public class ReportPortalUtils { + /** + * Markdown template for rendering code blocks. + */ public static final String MARKDOWN_CODE_PATTERN = "```\n%s\n```"; + /** + * Markdown template for rendering parameter tables. + */ public static final String PARAMETERS_PATTERN = "Parameters:\n\n%s"; + /** + * Regex template used to match Karate outline variable placeholders in a step. + */ public static final String VARIABLE_PATTERN = "(?:(?<=#\\()%1$s(?=\\)))|(?:(?<=[\\s=+-/*<>(]|^)%1$s(?=[\\s=+-/*<>)]|(?:\\r?\\n)|$))"; + /** + * Agent properties file name used to enrich launch/system attributes. + */ public static final String AGENT_PROPERTIES_FILE = "agent.properties"; + /** + * System attribute key that controls skipped issue behavior in ReportPortal. + */ public static final String SKIPPED_ISSUE_KEY = "skippedIssue"; + /** + * Code reference template for a concrete scenario. + */ public static final String SCENARIO_CODE_REFERENCE_PATTERN = "%s/[SCENARIO:%s]"; + /** + * Code reference template for a scenario outline example. + */ public static final String EXAMPLE_CODE_REFERENCE_PATTERN = "%s/[EXAMPLE:%s%s]"; + /** + * Markdown delimiter used to join logical description sections. + */ public static final String MARKDOWN_DELIMITER = MarkdownUtils.LOGICAL_SEPARATOR; + /** + * Pattern for joining two text blocks with a markdown delimiter. + */ public static final String MARKDOWN_DELIMITER_PATTERN = "%s" + MARKDOWN_DELIMITER + "%s"; + /** + * Prefix used for naming called (inner) feature items. + */ public static final String FEATURE_TAG = "Feature: "; + /** + * Prefix used for naming called (inner) scenario items. + */ public static final String SCENARIO_TAG = "Scenario: "; private static final Logger LOGGER = LoggerFactory.getLogger(ReportPortalUtils.class); private static final String PARAMETER_ITEMS_START = "["; @@ -174,6 +207,12 @@ public static FinishExecutionRQ buildFinishLaunchRq(@Nonnull ListenerParameters return rq; } + /** + * Returns a feature file code reference. + * + * @param feature Karate feature + * @return feature-relative code reference + */ @Nonnull public static String getCodeRef(@Nonnull Feature feature) { return feature.getResource().getRelativePath(); @@ -232,6 +271,12 @@ public static FinishTestItemRQ buildFinishTestItemRq(@Nonnull Instant endTime, @ return rq; } + /** + * Converts Karate tags to ReportPortal attributes. + * + * @param tags Karate tags + * @return ReportPortal attributes or {@code null} when there are no tags + */ @Nullable public static Set toAttributes(@Nullable List tags) { Set attributes = ofNullable(tags).orElse(Collections.emptyList()).stream().flatMap(tag -> { @@ -339,6 +384,14 @@ public static FinishTestItemRQ buildFinishScenarioRq(@Nonnull ScenarioResult res return rq; } + /** + * Builds scenario description from parameters, scenario description and optional error details. + * + * @param scenario scenario descriptor + * @param errorMessage optional error message + * @param parameters optional outline parameters + * @return formatted Markdown description + */ @Nonnull private static String buildDescription(@Nonnull Scenario scenario, @Nullable String errorMessage, @Nullable List parameters) { @@ -357,6 +410,12 @@ private static String buildDescription(@Nonnull Scenario scenario, @Nullable Str return descriptionBuilder.toString(); } + /** + * Appends text using the configured Markdown delimiter when needed. + * + * @param builder destination description builder + * @param text text block to append + */ private static void appendWithDelimiter(StringBuilder builder, String text) { if (!builder.isEmpty()) { builder.append(MARKDOWN_DELIMITER); @@ -367,7 +426,7 @@ private static void appendWithDelimiter(StringBuilder builder, String text) { /** * Build ReportPortal request for start Background event. * - * @param startTime + * @param startTime background start time * @param step Karate's Step object instance * @param scenario Karate's Scenario object instance * @return request to ReportPortal @@ -464,6 +523,7 @@ public static void sendLog(Maybe itemId, String message, LogLevel level) /** * Embed an attachment to ReportPortal. * + * @param time log time * @param itemId item ID future * @param embed Karate's Embed object */ diff --git a/src/main/java/com/epam/reportportal/karate/utils/BlockingConcurrentHashMap.java b/src/main/java/com/epam/reportportal/karate/utils/BlockingConcurrentHashMap.java index 20a31e9..094dd29 100644 --- a/src/main/java/com/epam/reportportal/karate/utils/BlockingConcurrentHashMap.java +++ b/src/main/java/com/epam/reportportal/karate/utils/BlockingConcurrentHashMap.java @@ -76,10 +76,28 @@ public T get(long timeout, TimeUnit unit) throws InterruptedException { private final Map> map = new ConcurrentHashMap<>(); + /** + * Creates an empty blocking concurrent map wrapper. + */ + public BlockingConcurrentHashMap() { + } + + /** + * Computes and stores a value for the key if it is absent. + * + * @param key map key + * @param mappingFunction function used to compute the value + */ public void computeIfAbsent(@Nonnull K key, Function mappingFunction) { map.computeIfAbsent(key, k -> new BlockingReference<>()).set(mappingFunction); } + /** + * Returns a value for the key, waiting until it is available or timeout expires. + * + * @param key map key + * @return stored value or {@code null} on timeout/interruption + */ @Nullable public V get(@Nonnull K key) { try { @@ -90,6 +108,12 @@ public V get(@Nonnull K key) { return null; } + /** + * Removes and returns a value for the key, waiting for pending computation if needed. + * + * @param key map key + * @return removed value or {@code null} on timeout/interruption + */ @Nullable public V remove(@Nonnull K key) { try { From f3c89eb0cba9a5edc9b657c4a0ea0b6bf90f4a41 Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Mon, 27 Apr 2026 16:52:41 +0300 Subject: [PATCH 09/19] Fix tests --- .../ScenarioDescriptionErrorLogTest.java | 12 ++++-- ...rrorLogWithDescriptionAndExamplesTest.java | 42 ++++++++++--------- ...escriptionErrorLogWithDescriptionTest.java | 22 +++++----- ...ioDescriptionErrorLogWithExamplesTest.java | 25 ++++++----- .../logging/SimpleFailureLoggingTest.java | 5 +-- .../karate/name/SimpleItemNameTest.java | 3 +- .../karate/timing/SimpleTimingTest.java | 6 +-- 7 files changed, 62 insertions(+), 53 deletions(-) diff --git a/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogTest.java b/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogTest.java index 51930ab..16f7022 100644 --- a/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogTest.java +++ b/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogTest.java @@ -37,14 +37,18 @@ import static com.epam.reportportal.karate.utils.TestUtils.*; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.endsWith; +import static org.hamcrest.Matchers.startsWith; import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.*; public class ScenarioDescriptionErrorLogTest { - public static final String ERROR = "did not evaluate to 'true': actualFour != four\nclasspath:feature/simple_failed.feature:6"; - public static final String ERROR_MESSAGE = "Then assert actualFour != four\n" + ERROR; - public static final String DESCRIPTION_ERROR_LOG = "Error:\n" + ERROR; + public static final String ERROR = "/feature/simple_failed.feature:6 actualFour != four"; + public static final String ERROR_MESSAGE = """ + Then actualFour != four + assert failed: actualFour != four"""; + public static final String DESCRIPTION_ERROR_LOG = "Error:\n"; private static final String TEST_FEATURE = "classpath:feature/simple_failed.feature"; private final String launchUuid = CommonUtils.namedId("launch_"); private final String featureId = CommonUtils.namedId("feature_"); @@ -90,6 +94,6 @@ public void test_error_log_in_description(boolean report) { List scenarios = scenarioCaptorFinish.getAllValues(); FinishTestItemRQ scenario = scenarios.getFirst(); - assertThat(scenario.getDescription(), allOf(notNullValue(), equalTo(DESCRIPTION_ERROR_LOG))); + assertThat(scenario.getDescription(), allOf(notNullValue(), startsWith(DESCRIPTION_ERROR_LOG), endsWith(ERROR))); } } diff --git a/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithDescriptionAndExamplesTest.java b/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithDescriptionAndExamplesTest.java index 504e3c0..3138cb0 100644 --- a/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithDescriptionAndExamplesTest.java +++ b/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithDescriptionAndExamplesTest.java @@ -39,38 +39,28 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import static com.epam.reportportal.karate.ReportPortalUtils.MARKDOWN_DELIMITER_PATTERN; import static com.epam.reportportal.karate.utils.TestUtils.*; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.endsWith; +import static org.hamcrest.Matchers.startsWith; import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.*; public class ScenarioDescriptionErrorLogWithDescriptionAndExamplesTest { - public static final String MARKDOWN_DELIMITER_PATTERN_THREE_ARGS = "%s\n\n---\n\n%s\n\n---\n\n%s"; - public static final String ERROR = "did not evaluate to 'true': mathResult == 5\nclasspath:feature/simple_failed_description_examples.feature:8"; - public static final String ERROR_MESSAGE = "Then assert mathResult == 5\n" + ERROR; - public static final String DESCRIPTION_ERROR_LOG = "Error:\n" + ERROR; - public static final String DESCRIPTION = "This is my Scenario description."; + public static final String ERROR_END = "feature/simple_failed_description_examples.feature:8 mathResult == 5"; + public static final String ERROR_MESSAGE = """ + Then mathResult == 5 + assert failed: mathResult == 5"""; + public static final String DESCRIPTION_STRING = "This is my Scenario description."; + public static final String ERROR = "Error:\n"; private static final String EXAMPLE_PARAMETERS_DESCRIPTION_PATTERN = "Parameters:\n\n" + MarkdownUtils.TABLE_INDENT + "| vara | varb | result |\n" + MarkdownUtils.TABLE_INDENT + "|------|------|--------|\n" + MarkdownUtils.TABLE_INDENT; public static final String FIRST_EXAMPLE_DESCRIPTION = EXAMPLE_PARAMETERS_DESCRIPTION_PATTERN + "|  2   |  2   |   4    |"; public static final String SECOND_EXAMPLE_DESCRIPTION = EXAMPLE_PARAMETERS_DESCRIPTION_PATTERN + "|  1   |  2   |   5    |"; - public static final String FIRST_EXAMPLE_DESCRIPTION_WITHOUT_ERROR_LOG = String.format( - MARKDOWN_DELIMITER_PATTERN, - FIRST_EXAMPLE_DESCRIPTION, - DESCRIPTION - ); - public static final String SECOND_EXAMPLE_DESCRIPTION_WITH_ERROR_LOG = String.format( - MARKDOWN_DELIMITER_PATTERN_THREE_ARGS, - SECOND_EXAMPLE_DESCRIPTION, - DESCRIPTION, - DESCRIPTION_ERROR_LOG - ); - private static final String TEST_FEATURE = "classpath:feature/simple_failed_description_examples.feature"; private final String featureId = CommonUtils.namedId("feature_"); private final List exampleIds = Stream.generate(() -> CommonUtils.namedId("example_")).limit(2).toList(); @@ -125,10 +115,22 @@ public void test_error_log_and_examples_in_description(boolean report) { FinishTestItemRQ firstScenarioRq = scenarioCaptor.getAllValues().getFirst(); assertThat(firstScenarioRq.getStatus(), allOf(notNullValue(), equalTo(ItemStatus.PASSED.name()))); - assertThat(firstScenarioRq.getDescription(), allOf(notNullValue(), equalTo(FIRST_EXAMPLE_DESCRIPTION_WITHOUT_ERROR_LOG))); + assertThat( + firstScenarioRq.getDescription(), + allOf(notNullValue(), equalTo(MarkdownUtils.asTwoParts(FIRST_EXAMPLE_DESCRIPTION, DESCRIPTION_STRING))) + ); FinishTestItemRQ secondScenarioRq = scenarioCaptor.getAllValues().get(1); assertThat(secondScenarioRq.getStatus(), allOf(notNullValue(), equalTo(ItemStatus.FAILED.name()))); - assertThat(secondScenarioRq.getDescription(), allOf(notNullValue(), equalTo(SECOND_EXAMPLE_DESCRIPTION_WITH_ERROR_LOG))); + assertThat( + secondScenarioRq.getDescription(), allOf( + notNullValue(), + startsWith(MarkdownUtils.asTwoParts( + SECOND_EXAMPLE_DESCRIPTION, + MarkdownUtils.asTwoParts(DESCRIPTION_STRING, ERROR) + )), + endsWith(ERROR_END) + ) + ); } } diff --git a/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithDescriptionTest.java b/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithDescriptionTest.java index e917722..f7827a2 100644 --- a/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithDescriptionTest.java +++ b/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithDescriptionTest.java @@ -21,6 +21,7 @@ import com.epam.reportportal.service.ReportPortal; import com.epam.reportportal.service.ReportPortalClient; import com.epam.reportportal.util.test.CommonUtils; +import com.epam.reportportal.utils.formatting.MarkdownUtils; import com.epam.ta.reportportal.ws.model.FinishTestItemRQ; import com.epam.ta.reportportal.ws.model.log.SaveLogRQ; import io.karatelabs.core.SuiteResult; @@ -34,24 +35,22 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import static com.epam.reportportal.karate.ReportPortalUtils.MARKDOWN_DELIMITER_PATTERN; import static com.epam.reportportal.karate.utils.TestUtils.*; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.startsWith; +import static org.hamcrest.Matchers.endsWith; import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.*; public class ScenarioDescriptionErrorLogWithDescriptionTest { - public static final String ERROR = "did not evaluate to 'true': actualFour != four\nclasspath:feature/simple_failed_description.feature:9"; - public static final String ERROR_MESSAGE = "Then assert actualFour != four\n" + ERROR; - public static final String DESCRIPTION_ERROR_LOG = "Error:\n" + ERROR; + public static final String ERROR = "/feature/simple_failed_description.feature:9 actualFour != four"; + public static final String ERROR_MESSAGE = """ + Then actualFour != four + assert failed: actualFour != four"""; + public static final String DESCRIPTION_ERROR_LOG = "Error:\n"; public static final String DESCRIPTION = "This is my Scenario description."; - public static final String DESCRIPTION_ERROR_LOG_WITH_DESCRIPTION = String.format( - MARKDOWN_DELIMITER_PATTERN, - DESCRIPTION, - DESCRIPTION_ERROR_LOG - ); private static final String TEST_FEATURE = "classpath:feature/simple_failed_description.feature"; private final String launchUuid = CommonUtils.namedId("launch_"); private final String featureId = CommonUtils.namedId("feature_"); @@ -98,6 +97,9 @@ public void test_error_log_and_description_in_description(boolean report) { List scenarios = scenarioCaptorFinish.getAllValues(); FinishTestItemRQ scenario = scenarios.getFirst(); - assertThat(scenario.getDescription(), allOf(notNullValue(), equalTo(DESCRIPTION_ERROR_LOG_WITH_DESCRIPTION))); + assertThat( + scenario.getDescription(), + allOf(notNullValue(), startsWith(MarkdownUtils.asTwoParts(DESCRIPTION, DESCRIPTION_ERROR_LOG)), endsWith(ERROR)) + ); } } diff --git a/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithExamplesTest.java b/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithExamplesTest.java index 87d5fd8..22c0ba6 100644 --- a/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithExamplesTest.java +++ b/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithExamplesTest.java @@ -39,31 +39,28 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import static com.epam.reportportal.karate.ReportPortalUtils.MARKDOWN_DELIMITER_PATTERN; import static com.epam.reportportal.karate.utils.TestUtils.*; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.endsWith; +import static org.hamcrest.Matchers.startsWith; import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.*; public class ScenarioDescriptionErrorLogWithExamplesTest { - public static final String ERROR = "did not evaluate to 'true': mathResult == 5\nclasspath:feature/simple_failed_examples.feature:5"; - public static final String ERROR_MESSAGE = "Then assert mathResult == 5\n" + ERROR; - public static final String DESCRIPTION_ERROR_LOG = "Error:\n" + ERROR; + public static final String ERROR = "/feature/simple_failed_examples.feature:5 mathResult == 5"; + public static final String ERROR_MESSAGE = """ + Then mathResult == 5 + assert failed: mathResult == 5"""; private static final String EXAMPLE_PARAMETERS_DESCRIPTION_PATTERN = "Parameters:\n\n" + MarkdownUtils.TABLE_INDENT + "| vara | varb | result |\n" + MarkdownUtils.TABLE_INDENT + "|------|------|--------|\n" + MarkdownUtils.TABLE_INDENT; public static final String FIRST_EXAMPLE_DESCRIPTION = EXAMPLE_PARAMETERS_DESCRIPTION_PATTERN + "|  2   |  2   |   4    |"; public static final String SECOND_EXAMPLE_DESCRIPTION = EXAMPLE_PARAMETERS_DESCRIPTION_PATTERN + "|  1   |  2   |   5    |"; - public static final String SECOND_EXAMPLE_DESCRIPTION_WITH_ERROR_LOG = String.format( - MARKDOWN_DELIMITER_PATTERN, - SECOND_EXAMPLE_DESCRIPTION, - DESCRIPTION_ERROR_LOG - ); - private static final String TEST_FEATURE = "classpath:feature/simple_failed_examples.feature"; + public static final String DESCRIPTION_ERROR_LOG = "Error:\n"; private final String featureId = CommonUtils.namedId("feature_"); private final List exampleIds = Stream.generate(() -> CommonUtils.namedId("example_")).limit(2).toList(); private final List>> stepIds = exampleIds.stream() @@ -121,6 +118,12 @@ public void test_error_log_and_examples_in_description(boolean report) { FinishTestItemRQ secondScenarioRq = scenarioCaptor.getAllValues().get(1); assertThat(secondScenarioRq.getStatus(), allOf(notNullValue(), equalTo(ItemStatus.FAILED.name()))); - assertThat(secondScenarioRq.getDescription(), allOf(notNullValue(), equalTo(SECOND_EXAMPLE_DESCRIPTION_WITH_ERROR_LOG))); + assertThat( + secondScenarioRq.getDescription(), allOf( + notNullValue(), + startsWith(MarkdownUtils.asTwoParts(SECOND_EXAMPLE_DESCRIPTION, DESCRIPTION_ERROR_LOG)), + endsWith(ERROR) + ) + ); } } diff --git a/src/test/java/com/epam/reportportal/karate/logging/SimpleFailureLoggingTest.java b/src/test/java/com/epam/reportportal/karate/logging/SimpleFailureLoggingTest.java index 8144e5e..0bbbdaf 100644 --- a/src/test/java/com/epam/reportportal/karate/logging/SimpleFailureLoggingTest.java +++ b/src/test/java/com/epam/reportportal/karate/logging/SimpleFailureLoggingTest.java @@ -80,9 +80,8 @@ public void test_simple_one_step_failed_error_log(boolean report) { assertThat(log.getLaunchUuid(), equalTo(launchUuid)); assertThat( log.getMessage(), equalTo(""" - Then assert actualFour != four - did not evaluate to 'true': actualFour != four - classpath:feature/simple_failed.feature:6""") + Then actualFour != four + assert failed: actualFour != four""") ); } } diff --git a/src/test/java/com/epam/reportportal/karate/name/SimpleItemNameTest.java b/src/test/java/com/epam/reportportal/karate/name/SimpleItemNameTest.java index 669937a..09074a5 100644 --- a/src/test/java/com/epam/reportportal/karate/name/SimpleItemNameTest.java +++ b/src/test/java/com/epam/reportportal/karate/name/SimpleItemNameTest.java @@ -39,8 +39,7 @@ public class SimpleItemNameTest { private static final String TEST_FEATURE = "classpath:feature/simple.feature"; - private static final String[] STEP_NAMES = new String[] { "Given def four = 4", "When def actualFour = 2 * 2", - "Then assert actualFour == four" }; + private static final String[] STEP_NAMES = new String[] { "Given four = 4", "When actualFour = 2 * 2", "Then actualFour == four" }; 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()); diff --git a/src/test/java/com/epam/reportportal/karate/timing/SimpleTimingTest.java b/src/test/java/com/epam/reportportal/karate/timing/SimpleTimingTest.java index 6d9ec85..ed05471 100644 --- a/src/test/java/com/epam/reportportal/karate/timing/SimpleTimingTest.java +++ b/src/test/java/com/epam/reportportal/karate/timing/SimpleTimingTest.java @@ -107,10 +107,10 @@ public void test_each_item_has_correct_start_date(boolean report, boolean useMic ); List steps = stepCaptor.getAllValues(); - StartTestItemRQ firstStep = steps.stream().filter(s -> "Given def four = 4".equals(s.getName())).findAny().orElseThrow(); - StartTestItemRQ secondStep = steps.stream().filter(s -> "When def actualFour = 2 * 2".equals(s.getName())).findAny().orElseThrow(); + StartTestItemRQ firstStep = steps.stream().filter(s -> "Given four = 4".equals(s.getName())).findAny().orElseThrow(); + StartTestItemRQ secondStep = steps.stream().filter(s -> "When actualFour = 2 * 2".equals(s.getName())).findAny().orElseThrow(); StartTestItemRQ thirdStep = steps.stream() - .filter(s -> "Then assert actualFour == four".equals(s.getName())) + .filter(s -> "Then actualFour == four".equals(s.getName())) .findAny() .orElseThrow(); From 564bab0ed8fc4f70cdd7c75dd41b5f1241f5bba3 Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Mon, 27 Apr 2026 20:59:12 +0300 Subject: [PATCH 10/19] Fix tests --- .../karate/ReportPortalResultListener.java | 23 ++++++++++++++--- .../karate/ReportPortalUtils.java | 25 +++++++++++++++---- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java b/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java index 2679c38..781163c 100644 --- a/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java +++ b/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java @@ -63,6 +63,7 @@ public class ReportPortalResultListener implements ResultListener { protected final MemoizingSupplier launch; private final BlockingConcurrentHashMap>> featureIdMap = new BlockingConcurrentHashMap<>(); private final Map> scenarioIdMap = new ConcurrentHashMap<>(); + private final Map stepStartTimeMap = new HashMap<>(); private final Map> backgroundIdMap = new ConcurrentHashMap<>(); private final Map backgroundStatusMap = new ConcurrentHashMap<>(); private final Map> stepIdMap = new ConcurrentHashMap<>(); @@ -238,7 +239,7 @@ protected StartTestItemRQ buildStartScenarioRq(@Nonnull Scenario sr) { /** * Starts a scenario item in ReportPortal. * - * @param scenario scenario descriptor + * @param scenario Karate scenario descriptor */ @Override public void onScenarioStart(Scenario scenario) { @@ -353,8 +354,9 @@ protected void embedAttachment(@Nonnull Instant time, @Nonnull Maybe ite */ @Override public void onScenarioEnd(ScenarioResult sr) { - Scenario scenario = sr.getScenario(); - Maybe scenarioId = scenarioIdMap.get(scenario.getUniqueId()); + String scenarioUniqueId = sr.getScenario().getUniqueId(); + Maybe scenarioId = scenarioIdMap.get(scenarioUniqueId); + stepStartTimeMap.remove(scenarioUniqueId); finishBackground(null, sr); if (scenarioId == null) { @@ -373,6 +375,18 @@ public void onScenarioEnd(ScenarioResult sr) { parentScenarios.get().removeFirst(); } + /** + * Get step start time. To keep the steps order in case previous step startTime == current step startTime or + * previous step startTime > current step startTime. + * + * @param scenarioUniqueId Karate's Scenario Unique ID + * @return step new startTime in Instant format. + */ + @Nonnull + private Instant getStepStartTime(@Nullable String scenarioUniqueId, Instant stepStartTime) { + return ReportPortalUtils.getStepStartTime(scenarioUniqueId, stepStartTimeMap, stepStartTime, launch.get().useMicroseconds()); + } + /** * Customize start Step test item event/request. * @@ -384,7 +398,8 @@ public void onScenarioEnd(ScenarioResult sr) { @Nonnull protected StartTestItemRQ buildStartStepRq(Instant startTime, @Nonnull Step step, @Nonnull Scenario sr) { StartTestItemRQ rq = ReportPortalUtils.buildStartStepRq(step, sr); - rq.setStartTime(startTime); + Instant newStartTime = getStepStartTime(sr.getUniqueId(), startTime); + rq.setStartTime(newStartTime); return rq; } diff --git a/src/main/java/com/epam/reportportal/karate/ReportPortalUtils.java b/src/main/java/com/epam/reportportal/karate/ReportPortalUtils.java index e077f21..b95e9bc 100644 --- a/src/main/java/com/epam/reportportal/karate/ReportPortalUtils.java +++ b/src/main/java/com/epam/reportportal/karate/ReportPortalUtils.java @@ -602,14 +602,14 @@ public static String getInnerFeatureName(String name) { * Get step start time. To keep the steps order in case previous step startTime == current step startTime or * previous step startTime > current step startTime. * - * @param scenarioUniqueId Karate's Scenario Unique ID, a key for stepStartTimeMap - * @param stepStartTimeMap a holder for start times for every particular scenario - * @param useMicroseconds if server supports microseconds + * @param scenarioUniqueId Karate's Scenario Unique ID, a key for stepStartTimeMap + * @param stepStartTimeMap a holder for start times for every particular scenario + * @param currentStepStartTime scenario start time to use as baseline + * @param useMicroseconds if server supports microseconds * @return step new startTime in Instant format. */ public static Instant getStepStartTime(@Nullable String scenarioUniqueId, Map stepStartTimeMap, - boolean useMicroseconds) { - Instant currentStepStartTime = Instant.now().truncatedTo(ChronoUnit.MICROS); + Instant currentStepStartTime, boolean useMicroseconds) { if (scenarioUniqueId == null || stepStartTimeMap.isEmpty()) { stepStartTimeMap.put(scenarioUniqueId, currentStepStartTime); return currentStepStartTime; @@ -631,4 +631,19 @@ public static Instant getStepStartTime(@Nullable String scenarioUniqueId, Map stepStartTimeMap, + boolean useMicroseconds) { + Instant currentStepStartTime = Instant.now().truncatedTo(ChronoUnit.MICROS); + return getStepStartTime(scenarioUniqueId, stepStartTimeMap, currentStepStartTime, useMicroseconds); + } } From e86323fced124f1a55cc63f92d99a0d4aba7ac8f Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Mon, 27 Apr 2026 21:15:05 +0300 Subject: [PATCH 11/19] Fix tests --- .../karate/ReportPortalRunListener.java | 28 +++++++++++-------- ...lTheSameFeatureWithParametersHookTest.java | 2 +- .../call/CallWithParametersHookTest.java | 2 +- .../feature/call_same_feature.feature | 2 +- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/epam/reportportal/karate/ReportPortalRunListener.java b/src/main/java/com/epam/reportportal/karate/ReportPortalRunListener.java index 00b425c..9d82b74 100644 --- a/src/main/java/com/epam/reportportal/karate/ReportPortalRunListener.java +++ b/src/main/java/com/epam/reportportal/karate/ReportPortalRunListener.java @@ -145,15 +145,17 @@ public void finishLaunch() { @Nonnull protected StartTestItemRQ buildStartFeatureRq(@Nonnull FeatureRuntime fr) { StartTestItemRQ rq = ReportPortalUtils.buildStartFeatureRq(fr.getFeature()); - ofNullable(fr.getCaller()).map(FeatureRuntime::getCallArg).filter(args -> !args.isEmpty()).ifPresent(args -> { - String parameters = String.format(PARAMETERS_PATTERN, formatParametersAsTable(getParameters(args))); - String description = rq.getDescription(); - if (isNotBlank(description)) { - rq.setDescription(MarkdownUtils.asTwoParts(parameters, description)); - } else { - rq.setDescription(parameters); - } - }); + ofNullable(fr.getCallArg()) + .filter(args -> !args.isEmpty()) + .ifPresent(args -> { + String parameters = String.format(PARAMETERS_PATTERN, formatParametersAsTable(getParameters(args))); + String description = rq.getDescription(); + if (isNotBlank(description)) { + rq.setDescription(MarkdownUtils.asTwoParts(parameters, description)); + } else { + rq.setDescription(parameters); + } + }); return rq; } @@ -171,7 +173,11 @@ private int getDepth(FeatureRuntime fr) { int depth = 0; while (caller != null) { depth++; - caller = caller.getFeatureRuntime().getCallerScenario(); + FeatureRuntime myFr = caller.getFeatureRuntime(); + if (myFr == null) { + break; + } + caller = myFr.getCallerScenario(); } return depth; } @@ -199,7 +205,7 @@ public void beforeFeature(FeatureRuntime fr) { if (getDepth(fr) == 0) { return launch.get().startTestItem(rq); } else { - Maybe scenarioId = scenarioIdMap.get(fr.getCaller().getCallerScenario().getScenario().getUniqueId()); + Maybe scenarioId = scenarioIdMap.get(fr.getCallerScenario().getScenario().getUniqueId()); if (scenarioId == null) { LOGGER.error("ERROR: Trying to post unspecified scenario."); return launch.get().startTestItem(rq); diff --git a/src/test/java/com/epam/reportportal/karate/call/CallTheSameFeatureWithParametersHookTest.java b/src/test/java/com/epam/reportportal/karate/call/CallTheSameFeatureWithParametersHookTest.java index 420de96..595c185 100644 --- a/src/test/java/com/epam/reportportal/karate/call/CallTheSameFeatureWithParametersHookTest.java +++ b/src/test/java/com/epam/reportportal/karate/call/CallTheSameFeatureWithParametersHookTest.java @@ -54,7 +54,7 @@ public class CallTheSameFeatureWithParametersHookTest { private final String innerScenarioId = CommonUtils.namedId("scenario_step_"); private final List innerStepIds = Stream.generate(() -> CommonUtils.namedId("inner_step_")) .limit(4) - .collect(Collectors.toList()); + .toList(); private final List>>>> features = Stream.of(Pair.of( featureId, diff --git a/src/test/java/com/epam/reportportal/karate/call/CallWithParametersHookTest.java b/src/test/java/com/epam/reportportal/karate/call/CallWithParametersHookTest.java index 5164967..da14507 100644 --- a/src/test/java/com/epam/reportportal/karate/call/CallWithParametersHookTest.java +++ b/src/test/java/com/epam/reportportal/karate/call/CallWithParametersHookTest.java @@ -56,7 +56,7 @@ public class CallWithParametersHookTest { private final String innerScenarioId = CommonUtils.namedId("scenario_step_"); private final List innerStepIds = Stream.generate(() -> CommonUtils.namedId("inner_step_")) .limit(3) - .collect(Collectors.toList()); + .toList(); private final List>>>> features = Stream.of(Pair.of( featureId, diff --git a/src/test/resources/feature/call_same_feature.feature b/src/test/resources/feature/call_same_feature.feature index dc4524f..b7785de 100644 --- a/src/test/resources/feature/call_same_feature.feature +++ b/src/test/resources/feature/call_same_feature.feature @@ -10,4 +10,4 @@ Feature: the very basic test to run by Karate Scenario: Verify math * def expectedValue = 4 * def testValue = 2 - * call read('@execute-test') { expectedValue: #(expectedValue), testValue: #(testValue) } + * call read('@execute-test') { expectedValue: expectedValue, testValue: testValue } From d4af12a6dfa29ba54a292486f279c62d75b82ff2 Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Mon, 27 Apr 2026 21:38:02 +0300 Subject: [PATCH 12/19] Fix tests --- .../reportportal/karate/call/CallWithParametersHookTest.java | 2 +- .../epam/reportportal/karate/coderef/ExamplesCodeRefTest.java | 2 +- .../epam/reportportal/karate/coderef/ScenarioCodeRefTest.java | 2 +- .../epam/reportportal/karate/description/NoDescriptionTest.java | 2 +- ...enarioDescriptionErrorLogWithDescriptionAndExamplesTest.java | 2 +- .../reportportal/karate/description/SimpleDescriptionTest.java | 2 +- .../com/epam/reportportal/karate/id/ExamplesTestCaseIdTest.java | 2 +- .../com/epam/reportportal/karate/id/ScenarioTestCaseIdTest.java | 2 +- .../com/epam/reportportal/karate/name/NoFeatureNameTest.java | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/test/java/com/epam/reportportal/karate/call/CallWithParametersHookTest.java b/src/test/java/com/epam/reportportal/karate/call/CallWithParametersHookTest.java index da14507..ecee14f 100644 --- a/src/test/java/com/epam/reportportal/karate/call/CallWithParametersHookTest.java +++ b/src/test/java/com/epam/reportportal/karate/call/CallWithParametersHookTest.java @@ -102,6 +102,6 @@ public void test_call_feature_with_parameters_hook_reporting() { .findAny() .orElseThrow(); - assertThat(calledFeature.getDescription(), allOf(endsWith("feature/called.feature"), startsWith(PARAMETERS_DESCRIPTION_PATTERN))); + assertThat(calledFeature.getDescription(), allOf(endsWith("build/resources/test/feature/called.feature"), startsWith(PARAMETERS_DESCRIPTION_PATTERN))); } } diff --git a/src/test/java/com/epam/reportportal/karate/coderef/ExamplesCodeRefTest.java b/src/test/java/com/epam/reportportal/karate/coderef/ExamplesCodeRefTest.java index 6e8de8e..d8fdf62 100644 --- a/src/test/java/com/epam/reportportal/karate/coderef/ExamplesCodeRefTest.java +++ b/src/test/java/com/epam/reportportal/karate/coderef/ExamplesCodeRefTest.java @@ -41,7 +41,7 @@ public class ExamplesCodeRefTest { private static final String TEST_FEATURE = "classpath:feature/examples.feature"; - private static final String EXAMPLE_CODE_REFERENCE_PATTERN = "feature/examples.feature/[EXAMPLE:Verify different maths[%s]]"; + private static final String EXAMPLE_CODE_REFERENCE_PATTERN = "build/resources/test/feature/examples.feature/[EXAMPLE:Verify different maths[%s]]"; private static final String FIRST_EXAMPLE_CODE_REFERENCE = String.format(EXAMPLE_CODE_REFERENCE_PATTERN, "result:4;vara:2;varb:2"); private static final String SECOND_EXAMPLE_CODE_REFERENCE = String.format(EXAMPLE_CODE_REFERENCE_PATTERN, "result:3;vara:1;varb:2"); private final String featureId = CommonUtils.namedId("feature_"); diff --git a/src/test/java/com/epam/reportportal/karate/coderef/ScenarioCodeRefTest.java b/src/test/java/com/epam/reportportal/karate/coderef/ScenarioCodeRefTest.java index a37e20a..1c20fd9 100644 --- a/src/test/java/com/epam/reportportal/karate/coderef/ScenarioCodeRefTest.java +++ b/src/test/java/com/epam/reportportal/karate/coderef/ScenarioCodeRefTest.java @@ -40,7 +40,7 @@ public class ScenarioCodeRefTest { private static final String TEST_FEATURE = "classpath:feature/simple.feature"; - private static final String SIMPLE_CODE_REFERENCE = "feature/simple.feature/[SCENARIO:Verify math]"; + private static final String SIMPLE_CODE_REFERENCE = "build/resources/test/feature/simple.feature/[SCENARIO:Verify math]"; 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()); diff --git a/src/test/java/com/epam/reportportal/karate/description/NoDescriptionTest.java b/src/test/java/com/epam/reportportal/karate/description/NoDescriptionTest.java index f5b5f32..dd57aa6 100644 --- a/src/test/java/com/epam/reportportal/karate/description/NoDescriptionTest.java +++ b/src/test/java/com/epam/reportportal/karate/description/NoDescriptionTest.java @@ -72,7 +72,7 @@ public void test_description_for_all_possible_items(boolean report) { verify(client, times(3)).startTestItem(same(scenarioId), stepCaptor.capture()); StartTestItemRQ featureStart = featureCaptor.getValue(); - assertThat(featureStart.getDescription(), endsWith("feature/simple.feature")); + assertThat(featureStart.getDescription(), endsWith("build/resources/test/feature/simple.feature")); StartTestItemRQ scenarioStart = scenarioCaptor.getValue(); assertThat(scenarioStart.getDescription(), emptyString()); diff --git a/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithDescriptionAndExamplesTest.java b/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithDescriptionAndExamplesTest.java index 3138cb0..b27ceab 100644 --- a/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithDescriptionAndExamplesTest.java +++ b/src/test/java/com/epam/reportportal/karate/description/ScenarioDescriptionErrorLogWithDescriptionAndExamplesTest.java @@ -49,7 +49,7 @@ public class ScenarioDescriptionErrorLogWithDescriptionAndExamplesTest { - public static final String ERROR_END = "feature/simple_failed_description_examples.feature:8 mathResult == 5"; + public static final String ERROR_END = "build/resources/test/feature/simple_failed_description_examples.feature:8 mathResult == 5"; public static final String ERROR_MESSAGE = """ Then mathResult == 5 assert failed: mathResult == 5"""; diff --git a/src/test/java/com/epam/reportportal/karate/description/SimpleDescriptionTest.java b/src/test/java/com/epam/reportportal/karate/description/SimpleDescriptionTest.java index e5123fd..002679c 100644 --- a/src/test/java/com/epam/reportportal/karate/description/SimpleDescriptionTest.java +++ b/src/test/java/com/epam/reportportal/karate/description/SimpleDescriptionTest.java @@ -78,7 +78,7 @@ public void test_description_for_all_possible_items(boolean report) { verify(client, times(3)).startTestItem(same(scenarioId), stepCaptor.capture()); StartTestItemRQ featureStart = featureCaptor.getValue(); - assertThat(featureStart.getDescription(), endsWith("feature/description.feature\n\n---\n\nThis is my Feature description.")); + assertThat(featureStart.getDescription(), endsWith("build/resources/test/feature/description.feature\n\n---\n\nThis is my Feature description.")); StartTestItemRQ scenarioStart = scenarioCaptor.getValue(); assertThat(scenarioStart.getDescription(), equalTo(SCENARIO_DESCRIPTION)); diff --git a/src/test/java/com/epam/reportportal/karate/id/ExamplesTestCaseIdTest.java b/src/test/java/com/epam/reportportal/karate/id/ExamplesTestCaseIdTest.java index 15c550f..82c2d09 100644 --- a/src/test/java/com/epam/reportportal/karate/id/ExamplesTestCaseIdTest.java +++ b/src/test/java/com/epam/reportportal/karate/id/ExamplesTestCaseIdTest.java @@ -40,7 +40,7 @@ public class ExamplesTestCaseIdTest { private static final String TEST_FEATURE = "classpath:feature/examples.feature"; - private static final String EXAMPLE_TEST_CASE_ID_PATTERN = "feature/examples.feature/[EXAMPLE:Verify different maths[%s]]"; + private static final String EXAMPLE_TEST_CASE_ID_PATTERN = "build/resources/test/feature/examples.feature/[EXAMPLE:Verify different maths[%s]]"; private static final String FIRST_EXAMPLE_TEST_CASE_ID = String.format(EXAMPLE_TEST_CASE_ID_PATTERN, "result:4;vara:2;varb:2"); private static final String SECOND_EXAMPLE_TEST_CASE_ID = String.format(EXAMPLE_TEST_CASE_ID_PATTERN, "result:3;vara:1;varb:2"); private final String featureId = CommonUtils.namedId("feature_"); diff --git a/src/test/java/com/epam/reportportal/karate/id/ScenarioTestCaseIdTest.java b/src/test/java/com/epam/reportportal/karate/id/ScenarioTestCaseIdTest.java index d9c85a7..4ca8c4a 100644 --- a/src/test/java/com/epam/reportportal/karate/id/ScenarioTestCaseIdTest.java +++ b/src/test/java/com/epam/reportportal/karate/id/ScenarioTestCaseIdTest.java @@ -39,7 +39,7 @@ public class ScenarioTestCaseIdTest { private static final String TEST_FEATURE = "classpath:feature/simple.feature"; - private static final String SIMPLE_TEST_CASE_ID = "feature/simple.feature/[SCENARIO:Verify math]"; + private static final String SIMPLE_TEST_CASE_ID = "build/resources/test/feature/simple.feature/[SCENARIO:Verify math]"; 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()); diff --git a/src/test/java/com/epam/reportportal/karate/name/NoFeatureNameTest.java b/src/test/java/com/epam/reportportal/karate/name/NoFeatureNameTest.java index a160cdb..03772e2 100644 --- a/src/test/java/com/epam/reportportal/karate/name/NoFeatureNameTest.java +++ b/src/test/java/com/epam/reportportal/karate/name/NoFeatureNameTest.java @@ -65,6 +65,6 @@ public void test_item_names_simple(boolean report) { verify(client, times(1)).startTestItem(featureCaptor.capture()); StartTestItemRQ featureRq = featureCaptor.getValue(); - assertThat(featureRq.getName(), allOf(notNullValue(), equalTo("feature/no_name_feature.feature"))); + assertThat(featureRq.getName(), allOf(notNullValue(), equalTo("build/resources/test/feature/no_name_feature.feature"))); } } From 1a001a14f04d305bca7d8bf043a52298166ed596 Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Tue, 28 Apr 2026 11:50:05 +0300 Subject: [PATCH 13/19] Update codeRef generation logic --- .../reportportal/karate/ReportPortalRunListener.java | 2 ++ .../epam/reportportal/karate/ReportPortalUtils.java | 10 +++++++++- .../karate/coderef/ExamplesCodeRefTest.java | 2 +- .../karate/coderef/ScenarioCodeRefTest.java | 2 +- .../reportportal/karate/id/ExamplesTestCaseIdTest.java | 2 +- .../reportportal/karate/id/ScenarioTestCaseIdTest.java | 2 +- .../reportportal/karate/name/NoFeatureNameTest.java | 2 +- 7 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/epam/reportportal/karate/ReportPortalRunListener.java b/src/main/java/com/epam/reportportal/karate/ReportPortalRunListener.java index 9d82b74..86b980b 100644 --- a/src/main/java/com/epam/reportportal/karate/ReportPortalRunListener.java +++ b/src/main/java/com/epam/reportportal/karate/ReportPortalRunListener.java @@ -556,6 +556,7 @@ public void sendErrorResults(long timestamp, Throwable error, ScenarioRuntime sr */ @SuppressWarnings("unused") public void beforeHttpCall(HttpRequest request, ScenarioRuntime sr) { + } /** @@ -567,6 +568,7 @@ public void beforeHttpCall(HttpRequest request, ScenarioRuntime sr) { */ @SuppressWarnings("unused") public void afterHttpCall(HttpRequest request, HttpResponse response, ScenarioRuntime sr) { + } /** diff --git a/src/main/java/com/epam/reportportal/karate/ReportPortalUtils.java b/src/main/java/com/epam/reportportal/karate/ReportPortalUtils.java index b95e9bc..b40bcd6 100644 --- a/src/main/java/com/epam/reportportal/karate/ReportPortalUtils.java +++ b/src/main/java/com/epam/reportportal/karate/ReportPortalUtils.java @@ -109,6 +109,8 @@ public class ReportPortalUtils { private static final String PARAMETER_ITEMS_DELIMITER = ";"; private static final String KEY_VALUE_SEPARATOR = ":"; + private static final List CODE_REF_PREFIXES_TO_REMOVE = List.of("build/resources/test/", "build/resources/main/"); + private ReportPortalUtils() { throw new RuntimeException("No instances should exist for the class!"); } @@ -215,7 +217,13 @@ public static FinishExecutionRQ buildFinishLaunchRq(@Nonnull ListenerParameters */ @Nonnull public static String getCodeRef(@Nonnull Feature feature) { - return feature.getResource().getRelativePath(); + String relativePath = feature.getResource().getRelativePath(); + for (String prefix : CODE_REF_PREFIXES_TO_REMOVE) { + if (relativePath.startsWith(prefix)) { + return relativePath.substring(prefix.length()); + } + } + return relativePath; } /** diff --git a/src/test/java/com/epam/reportportal/karate/coderef/ExamplesCodeRefTest.java b/src/test/java/com/epam/reportportal/karate/coderef/ExamplesCodeRefTest.java index d8fdf62..6e8de8e 100644 --- a/src/test/java/com/epam/reportportal/karate/coderef/ExamplesCodeRefTest.java +++ b/src/test/java/com/epam/reportportal/karate/coderef/ExamplesCodeRefTest.java @@ -41,7 +41,7 @@ public class ExamplesCodeRefTest { private static final String TEST_FEATURE = "classpath:feature/examples.feature"; - private static final String EXAMPLE_CODE_REFERENCE_PATTERN = "build/resources/test/feature/examples.feature/[EXAMPLE:Verify different maths[%s]]"; + private static final String EXAMPLE_CODE_REFERENCE_PATTERN = "feature/examples.feature/[EXAMPLE:Verify different maths[%s]]"; private static final String FIRST_EXAMPLE_CODE_REFERENCE = String.format(EXAMPLE_CODE_REFERENCE_PATTERN, "result:4;vara:2;varb:2"); private static final String SECOND_EXAMPLE_CODE_REFERENCE = String.format(EXAMPLE_CODE_REFERENCE_PATTERN, "result:3;vara:1;varb:2"); private final String featureId = CommonUtils.namedId("feature_"); diff --git a/src/test/java/com/epam/reportportal/karate/coderef/ScenarioCodeRefTest.java b/src/test/java/com/epam/reportportal/karate/coderef/ScenarioCodeRefTest.java index 1c20fd9..a37e20a 100644 --- a/src/test/java/com/epam/reportportal/karate/coderef/ScenarioCodeRefTest.java +++ b/src/test/java/com/epam/reportportal/karate/coderef/ScenarioCodeRefTest.java @@ -40,7 +40,7 @@ public class ScenarioCodeRefTest { private static final String TEST_FEATURE = "classpath:feature/simple.feature"; - private static final String SIMPLE_CODE_REFERENCE = "build/resources/test/feature/simple.feature/[SCENARIO:Verify math]"; + private static final String SIMPLE_CODE_REFERENCE = "feature/simple.feature/[SCENARIO:Verify math]"; 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()); diff --git a/src/test/java/com/epam/reportportal/karate/id/ExamplesTestCaseIdTest.java b/src/test/java/com/epam/reportportal/karate/id/ExamplesTestCaseIdTest.java index 82c2d09..15c550f 100644 --- a/src/test/java/com/epam/reportportal/karate/id/ExamplesTestCaseIdTest.java +++ b/src/test/java/com/epam/reportportal/karate/id/ExamplesTestCaseIdTest.java @@ -40,7 +40,7 @@ public class ExamplesTestCaseIdTest { private static final String TEST_FEATURE = "classpath:feature/examples.feature"; - private static final String EXAMPLE_TEST_CASE_ID_PATTERN = "build/resources/test/feature/examples.feature/[EXAMPLE:Verify different maths[%s]]"; + private static final String EXAMPLE_TEST_CASE_ID_PATTERN = "feature/examples.feature/[EXAMPLE:Verify different maths[%s]]"; private static final String FIRST_EXAMPLE_TEST_CASE_ID = String.format(EXAMPLE_TEST_CASE_ID_PATTERN, "result:4;vara:2;varb:2"); private static final String SECOND_EXAMPLE_TEST_CASE_ID = String.format(EXAMPLE_TEST_CASE_ID_PATTERN, "result:3;vara:1;varb:2"); private final String featureId = CommonUtils.namedId("feature_"); diff --git a/src/test/java/com/epam/reportportal/karate/id/ScenarioTestCaseIdTest.java b/src/test/java/com/epam/reportportal/karate/id/ScenarioTestCaseIdTest.java index 4ca8c4a..d9c85a7 100644 --- a/src/test/java/com/epam/reportportal/karate/id/ScenarioTestCaseIdTest.java +++ b/src/test/java/com/epam/reportportal/karate/id/ScenarioTestCaseIdTest.java @@ -39,7 +39,7 @@ public class ScenarioTestCaseIdTest { private static final String TEST_FEATURE = "classpath:feature/simple.feature"; - private static final String SIMPLE_TEST_CASE_ID = "build/resources/test/feature/simple.feature/[SCENARIO:Verify math]"; + private static final String SIMPLE_TEST_CASE_ID = "feature/simple.feature/[SCENARIO:Verify math]"; 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()); diff --git a/src/test/java/com/epam/reportportal/karate/name/NoFeatureNameTest.java b/src/test/java/com/epam/reportportal/karate/name/NoFeatureNameTest.java index 03772e2..a160cdb 100644 --- a/src/test/java/com/epam/reportportal/karate/name/NoFeatureNameTest.java +++ b/src/test/java/com/epam/reportportal/karate/name/NoFeatureNameTest.java @@ -65,6 +65,6 @@ public void test_item_names_simple(boolean report) { verify(client, times(1)).startTestItem(featureCaptor.capture()); StartTestItemRQ featureRq = featureCaptor.getValue(); - assertThat(featureRq.getName(), allOf(notNullValue(), equalTo("build/resources/test/feature/no_name_feature.feature"))); + assertThat(featureRq.getName(), allOf(notNullValue(), equalTo("feature/no_name_feature.feature"))); } } From 6f42a0d0d7572ceee6ded7951c212216bc98ba45 Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Tue, 28 Apr 2026 12:05:07 +0300 Subject: [PATCH 14/19] Add more forbidden prefixes --- .../com/epam/reportportal/karate/ReportPortalUtils.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/epam/reportportal/karate/ReportPortalUtils.java b/src/main/java/com/epam/reportportal/karate/ReportPortalUtils.java index b40bcd6..0e96f8e 100644 --- a/src/main/java/com/epam/reportportal/karate/ReportPortalUtils.java +++ b/src/main/java/com/epam/reportportal/karate/ReportPortalUtils.java @@ -109,7 +109,12 @@ public class ReportPortalUtils { private static final String PARAMETER_ITEMS_DELIMITER = ";"; private static final String KEY_VALUE_SEPARATOR = ":"; - private static final List CODE_REF_PREFIXES_TO_REMOVE = List.of("build/resources/test/", "build/resources/main/"); + private static final List CODE_REF_PREFIXES_TO_REMOVE = List.of( + "build/resources/test/", + "build/resources/main/", + "target/test-classes/", + "target/classes/" + ); private ReportPortalUtils() { throw new RuntimeException("No instances should exist for the class!"); From e69653aacfdb27ca20374aac94a871b4c43d0cdc Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Tue, 28 Apr 2026 13:01:06 +0300 Subject: [PATCH 15/19] Fix tag filtering --- .../karate/ReportPortalResultListener.java | 29 +++++++-------- .../karate/ReportPortalRunListener.java | 37 +++++++++---------- 2 files changed, 31 insertions(+), 35 deletions(-) diff --git a/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java b/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java index 781163c..f3c5045 100644 --- a/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java +++ b/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java @@ -61,7 +61,7 @@ public class ReportPortalResultListener implements ResultListener { * Lazily initialized ReportPortal launch facade used for all item operations. */ protected final MemoizingSupplier launch; - private final BlockingConcurrentHashMap>> featureIdMap = new BlockingConcurrentHashMap<>(); + private final BlockingConcurrentHashMap>> featureIdMap = new BlockingConcurrentHashMap<>(); private final Map> scenarioIdMap = new ConcurrentHashMap<>(); private final Map stepStartTimeMap = new HashMap<>(); private final Map> backgroundIdMap = new ConcurrentHashMap<>(); @@ -206,15 +206,14 @@ protected FinishTestItemRQ buildFinishFeatureRq(@Nonnull FeatureResult fr) { */ @Override public void onFeatureEnd(FeatureResult fr) { - Optional> optionalId = ofNullable(featureIdMap.get(getFeatureNameForReport(fr.getFeature()))).map(Supplier::get); - if (optionalId.isEmpty()) { - LOGGER.error("ERROR: Trying to finish unspecified feature."); + MemoizingSupplier> supplier = featureIdMap.get(getFeatureNameForReport(fr.getFeature())); + if (supplier == null || !supplier.isInitialized()) { + return; } - optionalId.ifPresent(featureId -> { - //noinspection ReactiveStreamsUnusedPublisher - launch.get().finishTestItem(featureId, buildFinishFeatureRq(fr)); - innerFeatures.remove(featureId); - }); + Maybe featureId = supplier.get(); + //noinspection ReactiveStreamsUnusedPublisher + launch.get().finishTestItem(featureId, buildFinishFeatureRq(fr)); + innerFeatures.remove(featureId); } /** @@ -277,8 +276,8 @@ protected FinishTestItemRQ buildFinishScenarioRq(@Nonnull ScenarioResult sr) { * Build ReportPortal request for start Background event. * * @param startTime background start time - * @param step Karate step descriptor - * @param sr Karate scenario descriptor + * @param step Karate step descriptor + * @param sr Karate scenario descriptor * @return request to ReportPortal */ @Nonnull @@ -290,8 +289,8 @@ protected StartTestItemRQ buildStartBackgroundRq(Instant startTime, @Nonnull Ste * Start sending Background data to ReportPortal. * * @param startTime background start time - * @param step Karate step descriptor - * @param sr Karate scenario descriptor + * @param step Karate step descriptor + * @param sr Karate scenario descriptor * @return item ID Future */ public Maybe startBackground(Instant startTime, @Nonnull Step step, @Nonnull Scenario sr) { @@ -391,8 +390,8 @@ private Instant getStepStartTime(@Nullable String scenarioUniqueId, Instant step * Customize start Step test item event/request. * * @param startTime step start time - * @param step Karate step descriptor - * @param sr Karate scenario descriptor + * @param step Karate step descriptor + * @param sr Karate scenario descriptor * @return request to ReportPortal */ @Nonnull diff --git a/src/main/java/com/epam/reportportal/karate/ReportPortalRunListener.java b/src/main/java/com/epam/reportportal/karate/ReportPortalRunListener.java index 86b980b..681d41d 100644 --- a/src/main/java/com/epam/reportportal/karate/ReportPortalRunListener.java +++ b/src/main/java/com/epam/reportportal/karate/ReportPortalRunListener.java @@ -64,7 +64,7 @@ public class ReportPortalRunListener implements RunListener { * Lazily initialized ReportPortal launch facade used for all item operations. */ protected final MemoizingSupplier launch; - private final BlockingConcurrentHashMap>> featureIdMap = new BlockingConcurrentHashMap<>(); + private final BlockingConcurrentHashMap>> featureIdMap = new BlockingConcurrentHashMap<>(); private final Map> scenarioIdMap = new ConcurrentHashMap<>(); private final Map> backgroundIdMap = new ConcurrentHashMap<>(); private final Map backgroundStatusMap = new ConcurrentHashMap<>(); @@ -145,17 +145,15 @@ public void finishLaunch() { @Nonnull protected StartTestItemRQ buildStartFeatureRq(@Nonnull FeatureRuntime fr) { StartTestItemRQ rq = ReportPortalUtils.buildStartFeatureRq(fr.getFeature()); - ofNullable(fr.getCallArg()) - .filter(args -> !args.isEmpty()) - .ifPresent(args -> { - String parameters = String.format(PARAMETERS_PATTERN, formatParametersAsTable(getParameters(args))); - String description = rq.getDescription(); - if (isNotBlank(description)) { - rq.setDescription(MarkdownUtils.asTwoParts(parameters, description)); - } else { - rq.setDescription(parameters); - } - }); + ofNullable(fr.getCallArg()).filter(args -> !args.isEmpty()).ifPresent(args -> { + String parameters = String.format(PARAMETERS_PATTERN, formatParametersAsTable(getParameters(args))); + String description = rq.getDescription(); + if (isNotBlank(description)) { + rq.setDescription(MarkdownUtils.asTwoParts(parameters, description)); + } else { + rq.setDescription(parameters); + } + }); return rq; } @@ -241,15 +239,14 @@ protected FinishTestItemRQ buildFinishFeatureRq(@Nonnull FeatureRuntime fr) { * @param fr feature runtime */ public void afterFeature(FeatureRuntime fr) { - Optional> optionalId = ofNullable(featureIdMap.get(getFeatureNameForReport(fr))).map(Supplier::get); - if (optionalId.isEmpty()) { - LOGGER.error("ERROR: Trying to finish unspecified feature."); + MemoizingSupplier> supplier = featureIdMap.get(getFeatureNameForReport(fr)); + if (supplier == null || !supplier.isInitialized()) { + return; } - optionalId.ifPresent(featureId -> { - //noinspection ReactiveStreamsUnusedPublisher - launch.get().finishTestItem(featureId, buildFinishFeatureRq(fr)); - innerFeatures.remove(featureId); - }); + Maybe featureId = supplier.get(); + //noinspection ReactiveStreamsUnusedPublisher + launch.get().finishTestItem(featureId, buildFinishFeatureRq(fr)); + innerFeatures.remove(featureId); } /** From b02d968a290f3388a3b4fd23987ba6d7f112cce3 Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Tue, 28 Apr 2026 20:35:22 +0300 Subject: [PATCH 16/19] Fix http logging --- build.gradle | 1 + .../karate/ReportPortalResultListener.java | 4 +- .../karate/ReportPortalRunListener.java | 273 +++++++++++++++++- .../karate/ReportPortalUtils.java | 15 + .../karate/utils/HttpEntityFactory.java | 256 ++++++++++++++++ .../logging/HttpRequestLoggingTest.java | 61 ++-- 6 files changed, 572 insertions(+), 38 deletions(-) create mode 100644 src/main/java/com/epam/reportportal/karate/utils/HttpEntityFactory.java diff --git a/build.gradle b/build.gradle index a836345..e26b754 100644 --- a/build.gradle +++ b/build.gradle @@ -42,6 +42,7 @@ repositories { dependencies { api "com.epam.reportportal:client-java:${client_version}" + api 'com.epam.reportportal:utils-java-formatting:5.4.0' compileOnly "io.karatelabs:karate-core:${karate_version}" implementation "org.slf4j:slf4j-api:${slf4j_api_version}" implementation "org.apache.commons:commons-lang3:3.19.0" diff --git a/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java b/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java index f3c5045..0ff7b79 100644 --- a/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java +++ b/src/main/java/com/epam/reportportal/karate/ReportPortalResultListener.java @@ -450,7 +450,7 @@ public void beforeStep(StepResult stepResult, ScenarioResult sr) { )); String docString = step.getDocString(); if (isNotBlank(docString)) { - sendLog(startTime.plusMillis(3), stepId, "Docstring:\n\n" + asMarkdownCode(step.getDocString()), LogLevel.INFO); + sendLog(startTime.plusMillis(3), stepId, "Docstring:\n\n" + asMarkdownCode(docString), LogLevel.INFO); } } @@ -479,7 +479,7 @@ public void sendStepResults(StepResult stepResult, ScenarioResult sr) { if (log != null) { itemTime = itemTime.plusNanos(duration); - sendLog(itemTime, stepId, log, LogLevel.INFO); + sendLog(itemTime, stepId, stripConsoleColors(log), LogLevel.INFO); } if (stepResult.isFailed()) { diff --git a/src/main/java/com/epam/reportportal/karate/ReportPortalRunListener.java b/src/main/java/com/epam/reportportal/karate/ReportPortalRunListener.java index 681d41d..bb37176 100644 --- a/src/main/java/com/epam/reportportal/karate/ReportPortalRunListener.java +++ b/src/main/java/com/epam/reportportal/karate/ReportPortalRunListener.java @@ -16,7 +16,16 @@ package com.epam.reportportal.karate; +import com.epam.reportportal.formatting.AbstractHttpFormatter; +import com.epam.reportportal.formatting.http.converters.DefaultCookieConverter; +import com.epam.reportportal.formatting.http.converters.DefaultFormParamConverter; +import com.epam.reportportal.formatting.http.converters.DefaultHttpHeaderConverter; +import com.epam.reportportal.formatting.http.converters.DefaultUriConverter; +import com.epam.reportportal.formatting.http.entities.Cookie; +import com.epam.reportportal.formatting.http.entities.Header; +import com.epam.reportportal.formatting.http.entities.Param; import com.epam.reportportal.karate.utils.BlockingConcurrentHashMap; +import com.epam.reportportal.karate.utils.HttpEntityFactory; import com.epam.reportportal.listeners.ItemStatus; import com.epam.reportportal.listeners.ItemType; import com.epam.reportportal.listeners.ListenerParameters; @@ -31,6 +40,7 @@ import com.epam.ta.reportportal.ws.model.StartTestItemRQ; import com.epam.ta.reportportal.ws.model.launch.StartLaunchRQ; import io.karatelabs.core.*; +import io.karatelabs.gherkin.Scenario; import io.karatelabs.gherkin.Step; import io.karatelabs.http.HttpRequest; import io.karatelabs.http.HttpResponse; @@ -47,6 +57,7 @@ import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; import java.util.function.Supplier; import static com.epam.reportportal.karate.ReportPortalUtils.*; @@ -58,12 +69,17 @@ /** * ReportPortal run listener for Karate that streams runtime events directly to ReportPortal. */ -public class ReportPortalRunListener implements RunListener { +public class ReportPortalRunListener extends AbstractHttpFormatter implements RunListener { private static final Logger LOGGER = LoggerFactory.getLogger(ReportPortalRunListener.class); + private static final String NULL_RESPONSE = "NULL response from Karate"; /** * Lazily initialized ReportPortal launch facade used for all item operations. */ protected final MemoizingSupplier launch; + /** + * Converter used to render Karate form parameters for HTTP logging. + */ + protected final Function paramConverter; private final BlockingConcurrentHashMap>> featureIdMap = new BlockingConcurrentHashMap<>(); private final Map> scenarioIdMap = new ConcurrentHashMap<>(); private final Map> backgroundIdMap = new ConcurrentHashMap<>(); @@ -74,11 +90,27 @@ public class ReportPortalRunListener implements RunListener { private volatile Thread shutDownHook; /** - * Creates a listener instance backed by the provided ReportPortal client. - * - * @param reportPortal ReportPortal client instance - */ - public ReportPortalRunListener(ReportPortal reportPortal) { + * Creates a Karate run listener with configurable HTTP converters. + * + * @param reportPortal ReportPortal client instance + * @param defaultLogLevel log level on which Karate HTTP requests/responses will appear in ReportPortal + * @param headerConvertFunction if you want to preprocess your HTTP Headers before they appear on Report Portal + * provide this custom function for the class, default function formats it like + * that: header.getName() + ": " + header.getValue() + * @param partHeaderConvertFunction the same as for HTTP headers, but for parts in multipart requests + * @param cookieConvertFunction the same as 'headerConvertFunction' param but for Cookies, default function + * formats Cookies with toString method + * @param uriConverterFunction the same as 'headerConvertFunction' param but for URI, default function returns + * URI "as is" + * @param paramConverter the same as 'headerConvertFunction' param but for Web Form Params, default function returns + * param.getName() + ": " + param.getValue() + */ + public ReportPortalRunListener(ReportPortal reportPortal, @Nonnull LogLevel defaultLogLevel, + @Nullable Function headerConvertFunction, @Nullable Function partHeaderConvertFunction, + @Nullable Function cookieConvertFunction, @Nullable Function uriConverterFunction, + @Nullable Function paramConverter) { + super(defaultLogLevel, headerConvertFunction, partHeaderConvertFunction, cookieConvertFunction, uriConverterFunction); + this.paramConverter = paramConverter != null ? paramConverter : DefaultFormParamConverter.INSTANCE; ListenerParameters params = reportPortal.getParameters(); StartLaunchRQ rq = buildStartLaunchRq(params); launch = new MemoizingSupplier<>(() -> { @@ -90,6 +122,93 @@ public ReportPortalRunListener(ReportPortal reportPortal) { }); } + /** + * Creates a Karate run listener with configurable HTTP converters. + * + * @param reportPortal ReportPortal client instance + * @param defaultLogLevel log level on which Karate HTTP requests/responses will appear in ReportPortal + * @param headerConvertFunction if you want to preprocess your HTTP Headers before they appear on Report Portal + * provide this custom function for the class, default function formats it like + * that: header.getName() + ": " + header.getValue() + * @param partHeaderConvertFunction the same as for HTTP headers, but for parts in multipart requests + * @param cookieConvertFunction the same as 'headerConvertFunction' param but for Cookies, default function + * formats Cookies with toString method + * @param uriConverterFunction the same as 'headerConvertFunction' param but for URI, default function returns + * URI "as is" + */ + public ReportPortalRunListener(ReportPortal reportPortal, @Nonnull LogLevel defaultLogLevel, + @Nullable Function headerConvertFunction, @Nullable Function partHeaderConvertFunction, + @Nullable Function cookieConvertFunction, @Nullable Function uriConverterFunction) { + this( + reportPortal, + defaultLogLevel, + headerConvertFunction, + partHeaderConvertFunction, + cookieConvertFunction, + uriConverterFunction, + DefaultFormParamConverter.INSTANCE + ); + } + + /** + * Creates a Karate run listener with configurable HTTP converters. + * + * @param reportPortal ReportPortal client instance + * @param defaultLogLevel log level on which Karate HTTP requests/responses will appear in ReportPortal + * @param headerConvertFunction if you want to preprocess your HTTP Headers before they appear on Report Portal + * provide this custom function for the class, default function formats it like + * that: header.getName() + ": " + header.getValue() + * @param partHeaderConvertFunction the same as for HTTP headers, but for parts in multipart requests + * @param cookieConvertFunction the same as 'headerConvertFunction' param but for Cookies, default function + * formats Cookies with toString method + */ + public ReportPortalRunListener(ReportPortal reportPortal, @Nonnull LogLevel defaultLogLevel, + @Nullable Function headerConvertFunction, @Nullable Function partHeaderConvertFunction, + @Nullable Function cookieConvertFunction) { + this( + reportPortal, + defaultLogLevel, + headerConvertFunction, + partHeaderConvertFunction, + cookieConvertFunction, + DefaultUriConverter.INSTANCE + ); + } + + /** + * Creates a Karate run listener with configurable header converters. + * + * @param reportPortal ReportPortal client instance + * @param defaultLogLevel log level on which Karate HTTP requests/responses will appear in ReportPortal + * @param headerConvertFunction if you want to preprocess your HTTP Headers before they appear on Report Portal + * provide this custom function for the class, default function formats it like + * that: header.getName() + ": " + header.getValue() + * @param partHeaderConvertFunction the same as for HTTP headers, but for parts in multipart requests + */ + public ReportPortalRunListener(ReportPortal reportPortal, @Nonnull LogLevel defaultLogLevel, + @Nullable Function headerConvertFunction, @Nullable Function partHeaderConvertFunction) { + this(reportPortal, defaultLogLevel, headerConvertFunction, partHeaderConvertFunction, DefaultCookieConverter.INSTANCE); + } + + /** + * Creates a Karate run listener with the specified HTTP log level. + * + * @param reportPortal ReportPortal client instance + * @param httpLogLevel log level on which Karate HTTP requests/responses will appear in ReportPortal + */ + public ReportPortalRunListener(ReportPortal reportPortal, @Nonnull LogLevel httpLogLevel) { + this(reportPortal, httpLogLevel, DefaultHttpHeaderConverter.INSTANCE, DefaultHttpHeaderConverter.INSTANCE); + } + + /** + * Creates a listener instance backed by the provided ReportPortal client. + * + * @param reportPortal ReportPortal client instance + */ + public ReportPortalRunListener(ReportPortal reportPortal) { + this(reportPortal, LogLevel.INFO); + } + /** * Creates a listener with a default ReportPortal client configuration. */ @@ -98,6 +217,109 @@ public ReportPortalRunListener() { this(ReportPortal.builder().build()); } + /** + * Creates a Karate run listener with configurable HTTP converters. + * + * @param launchSupplier launch supplier used to lazily initialize launch interactions + * @param defaultLogLevel log level on which Karate HTTP requests/responses will appear in ReportPortal + * @param headerConvertFunction if you want to preprocess your HTTP Headers before they appear on Report Portal + * provide this custom function for the class, default function formats it like + * that: header.getName() + ": " + header.getValue() + * @param partHeaderConvertFunction the same as for HTTP headers, but for parts in multipart requests + * @param cookieConvertFunction the same as 'headerConvertFunction' param but for Cookies, default function + * formats Cookies with toString method + * @param uriConverterFunction the same as 'headerConvertFunction' param but for URI, default function returns + * URI "as is" + * @param paramConverter the same as 'headerConvertFunction' param but for Web Form Params, default function returns + * param.getName() + ": " + param.getValue() + */ + public ReportPortalRunListener(Supplier launchSupplier, @Nonnull LogLevel defaultLogLevel, + @Nullable Function headerConvertFunction, @Nullable Function partHeaderConvertFunction, + @Nullable Function cookieConvertFunction, @Nullable Function uriConverterFunction, + @Nullable Function paramConverter) { + super(defaultLogLevel, headerConvertFunction, partHeaderConvertFunction, cookieConvertFunction, uriConverterFunction); + this.paramConverter = paramConverter != null ? paramConverter : DefaultFormParamConverter.INSTANCE; + launch = new MemoizingSupplier<>(launchSupplier); + } + + /** + * Creates a Karate run listener with configurable HTTP converters. + * + * @param launchSupplier launch supplier used to lazily initialize launch interactions + * @param defaultLogLevel log level on which Karate HTTP requests/responses will appear in ReportPortal + * @param headerConvertFunction if you want to preprocess your HTTP Headers before they appear on Report Portal + * provide this custom function for the class, default function formats it like + * that: header.getName() + ": " + header.getValue() + * @param partHeaderConvertFunction the same as for HTTP headers, but for parts in multipart requests + * @param cookieConvertFunction the same as 'headerConvertFunction' param but for Cookies, default function + * formats Cookies with toString method + * @param uriConverterFunction the same as 'headerConvertFunction' param but for URI, default function returns + * URI "as is" + */ + public ReportPortalRunListener(Supplier launchSupplier, @Nonnull LogLevel defaultLogLevel, + @Nullable Function headerConvertFunction, @Nullable Function partHeaderConvertFunction, + @Nullable Function cookieConvertFunction, @Nullable Function uriConverterFunction) { + this( + launchSupplier, + defaultLogLevel, + headerConvertFunction, + partHeaderConvertFunction, + cookieConvertFunction, + uriConverterFunction, + DefaultFormParamConverter.INSTANCE + ); + } + + /** + * Creates a Karate run listener with configurable HTTP converters. + * + * @param launchSupplier launch supplier used to lazily initialize launch interactions + * @param defaultLogLevel log level on which Karate HTTP requests/responses will appear in ReportPortal + * @param headerConvertFunction if you want to preprocess your HTTP Headers before they appear on Report Portal + * provide this custom function for the class, default function formats it like + * that: header.getName() + ": " + header.getValue() + * @param partHeaderConvertFunction the same as for HTTP headers, but for parts in multipart requests + * @param cookieConvertFunction the same as 'headerConvertFunction' param but for Cookies, default function + * formats Cookies with toString method + */ + public ReportPortalRunListener(Supplier launchSupplier, @Nonnull LogLevel defaultLogLevel, + @Nullable Function headerConvertFunction, @Nullable Function partHeaderConvertFunction, + @Nullable Function cookieConvertFunction) { + this( + launchSupplier, + defaultLogLevel, + headerConvertFunction, + partHeaderConvertFunction, + cookieConvertFunction, + DefaultUriConverter.INSTANCE + ); + } + + /** + * Creates a Karate run listener with configurable header converters. + * + * @param launchSupplier launch supplier used to lazily initialize launch interactions + * @param defaultLogLevel log level on which Karate HTTP requests/responses will appear in ReportPortal + * @param headerConvertFunction if you want to preprocess your HTTP Headers before they appear on Report Portal + * provide this custom function for the class, default function formats it like + * that: header.getName() + ": " + header.getValue() + * @param partHeaderConvertFunction the same as for HTTP headers, but for parts in multipart requests + */ + public ReportPortalRunListener(Supplier launchSupplier, @Nonnull LogLevel defaultLogLevel, + @Nullable Function headerConvertFunction, @Nullable Function partHeaderConvertFunction) { + this(launchSupplier, defaultLogLevel, headerConvertFunction, partHeaderConvertFunction, DefaultCookieConverter.INSTANCE); + } + + /** + * Creates a Karate run listener with the specified HTTP log level. + * + * @param launchSupplier launch supplier used to lazily initialize launch interactions + * @param httpLogLevel log level on which Karate HTTP requests/responses will appear in ReportPortal + */ + public ReportPortalRunListener(Supplier launchSupplier, @Nonnull LogLevel httpLogLevel) { + this(launchSupplier, httpLogLevel, DefaultHttpHeaderConverter.INSTANCE, DefaultHttpHeaderConverter.INSTANCE); + } + /** * Creates a listener with a preconfigured launch supplier. * @@ -105,7 +327,7 @@ public ReportPortalRunListener() { */ @SuppressWarnings("unused") public ReportPortalRunListener(Supplier launchSupplier) { - launch = new MemoizingSupplier<>(launchSupplier); + this(launchSupplier, LogLevel.INFO); } /** @@ -553,7 +775,23 @@ public void sendErrorResults(long timestamp, Throwable error, ScenarioRuntime sr */ @SuppressWarnings("unused") public void beforeHttpCall(HttpRequest request, ScenarioRuntime sr) { - + if (request == null) { + return; + } + try { + emitLog(HttpEntityFactory.createHttpRequestFormatter( + request, + uriConverter, + headerConverter, + cookieConverter, + paramConverter, + getContentPrettifiers(), + partHeaderConverter, + getBodyTypeMap() + )); + } catch (Exception e) { + LOGGER.warn("Unable to log HTTP request for scenario '{}'", getScenarioUniqueId(sr), e); + } } /** @@ -565,7 +803,26 @@ public void beforeHttpCall(HttpRequest request, ScenarioRuntime sr) { */ @SuppressWarnings("unused") public void afterHttpCall(HttpRequest request, HttpResponse response, ScenarioRuntime sr) { + if (response == null) { + sendLog(stepIdMap.get(sr.getScenario().getUniqueId()), NULL_RESPONSE, LogLevel.WARN); + return; + } + try { + emitLog(HttpEntityFactory.createHttpResponseFormatter( + response, + headerConverter, + cookieConverter, + getContentPrettifiers(), + getBodyTypeMap() + )); + } catch (Exception e) { + LOGGER.warn("Unable to log HTTP response for scenario '{}'", getScenarioUniqueId(sr), e); + } + } + @Nonnull + private String getScenarioUniqueId(@Nullable ScenarioRuntime sr) { + return ofNullable(sr).map(ScenarioRuntime::getScenario).map(Scenario::getUniqueId).orElse("unknown"); } /** diff --git a/src/main/java/com/epam/reportportal/karate/ReportPortalUtils.java b/src/main/java/com/epam/reportportal/karate/ReportPortalUtils.java index 0e96f8e..fa92fbe 100644 --- a/src/main/java/com/epam/reportportal/karate/ReportPortalUtils.java +++ b/src/main/java/com/epam/reportportal/karate/ReportPortalUtils.java @@ -108,6 +108,7 @@ public class ReportPortalUtils { private static final String PARAMETER_ITEMS_END = "]"; private static final String PARAMETER_ITEMS_DELIMITER = ";"; private static final String KEY_VALUE_SEPARATOR = ":"; + private static final Pattern CONSOLE_COLORS_PATTERN = Pattern.compile("\\u001B\\[[0-?]*[ -/]*[@-~]"); private static final List CODE_REF_PREFIXES_TO_REMOVE = List.of( "build/resources/test/", @@ -591,6 +592,20 @@ public static String asMarkdownCode(String code) { return String.format(MARKDOWN_CODE_PATTERN, code); } + /** + * Remove ANSI color/control escape codes from console output. + * + * @param text text potentially containing ANSI escape codes + * @return plain text without ANSI escape codes + */ + @Nullable + public static String stripConsoleColors(@Nullable String text) { + if (text == null) { + return null; + } + return CONSOLE_COLORS_PATTERN.matcher(text).replaceAll(""); + } + /** * Build name of inner scenario (called by another scenario). * diff --git a/src/main/java/com/epam/reportportal/karate/utils/HttpEntityFactory.java b/src/main/java/com/epam/reportportal/karate/utils/HttpEntityFactory.java new file mode 100644 index 0000000..2910415 --- /dev/null +++ b/src/main/java/com/epam/reportportal/karate/utils/HttpEntityFactory.java @@ -0,0 +1,256 @@ +/* + * Copyright 2026 EPAM Systems + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.epam.reportportal.karate.utils; + +import com.epam.reportportal.formatting.http.HttpFormatUtils; +import com.epam.reportportal.formatting.http.HttpPartFormatter; +import com.epam.reportportal.formatting.http.HttpRequestFormatter; +import com.epam.reportportal.formatting.http.HttpResponseFormatter; +import com.epam.reportportal.formatting.http.entities.BodyType; +import com.epam.reportportal.formatting.http.entities.Cookie; +import com.epam.reportportal.formatting.http.entities.Header; +import com.epam.reportportal.formatting.http.entities.Param; +import io.karatelabs.http.HttpRequest; +import io.karatelabs.http.HttpResponse; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; + +import java.nio.charset.StandardCharsets; +import java.time.Instant; +import java.time.format.DateTimeParseException; +import java.util.*; +import java.util.function.Function; + +import static java.util.Optional.ofNullable; +import static org.apache.commons.lang3.StringUtils.isNotBlank; + +/** + * Utility factory methods that convert Karate HTTP entities into ReportPortal formatters. + */ +public final class HttpEntityFactory { + + private HttpEntityFactory() { + throw new IllegalStateException("Utility class should not be instantiated"); + } + + /** + * Builds a request formatter from Karate {@link HttpRequest}. + * + * @param request Karate HTTP request + * @param uriConverter URI converter override + * @param headerConverter header converter override + * @param cookieConverter cookie converter override + * @param paramConverter form parameter converter override + * @param prettifiers payload prettifiers by MIME type + * @param partHeaderConverter multipart part header converter override + * @param bodyTypeMap body type mapping by MIME type + * @return populated request formatter + */ + @Nonnull + public static HttpRequestFormatter createHttpRequestFormatter(@Nonnull HttpRequest request, + @Nullable Function uriConverter, @Nullable Function headerConverter, + @Nullable Function cookieConverter, @Nullable Function paramConverter, + @Nullable Map> prettifiers, @Nullable Function partHeaderConverter, + @Nonnull Map bodyTypeMap) { + HttpRequestFormatter.Builder builder = new HttpRequestFormatter.Builder(request.getMethod(), request.getUrlAndPath()); + ofNullable(request.getHeaders()).ifPresent(headers -> headers.forEach((key, values) -> ofNullable(values).orElseGet(Collections::emptyList) + .forEach(value -> builder.addHeader(key, value)))); + ofNullable(request.getCookies()).orElseGet(Collections::emptyMap) + .forEach((key, value) -> builder.addCookie(key, value == null ? null : value.get("value"))); + builder.uriConverter(uriConverter) + .headerConverter(headerConverter) + .cookieConverter(cookieConverter) + .paramConverter(paramConverter) + .prettifiers(prettifiers); + + String contentType = request.getContentType(); + String mimeType = HttpFormatUtils.getMimeType(contentType); + BodyType bodyType = request.isMultiPart() ? BodyType.MULTIPART : HttpFormatUtils.getBodyType(contentType, bodyTypeMap); + byte[] body = request.getBody(); + if (body == null && !BodyType.MULTIPART.equals(bodyType)) { + return builder.build(); + } + switch (bodyType) { + case TEXT -> builder.bodyText(mimeType, ofNullable(request.getBodyDisplay()).orElseGet(request::getBodyString)); + case FORM -> builder.bodyParams(ofNullable(request.getBodyDisplay()).orElseGet(request::getBodyString)); + case MULTIPART -> toParts(request, bodyTypeMap, partHeaderConverter).forEach(builder::addBodyPart); + default -> builder.bodyBytes(mimeType, body); + } + return builder.build(); + } + + /** + * Builds a response formatter from Karate {@link HttpResponse}. + * + * @param response Karate HTTP response + * @param headerConverter header converter override + * @param cookieConverter cookie converter override + * @param prettifiers payload prettifiers by MIME type + * @param bodyTypeMap body type mapping by MIME type + * @return populated response formatter + */ + @Nonnull + public static HttpResponseFormatter createHttpResponseFormatter(@Nonnull HttpResponse response, + @Nullable Function headerConverter, @Nullable Function cookieConverter, + @Nullable Map> prettifiers, @Nonnull Map bodyTypeMap) { + HttpResponseFormatter.Builder builder = new HttpResponseFormatter.Builder(response.getStatus(), getStatusLine(response)); + ofNullable(response.getHeaders()).ifPresent(headers -> headers.forEach((key, values) -> ofNullable(values).orElseGet(Collections::emptyList) + .forEach(value -> builder.addHeader(key, value)))); + ofNullable(response.getCookies()).orElseGet(Collections::emptyMap).forEach((name, cookie) -> builder.addCookie( + name, + toStringValue(cookie.get("value")), + toStringValue(cookie.get("comment")), + toStringValue(cookie.get("path")), + toStringValue(cookie.get("domain")), + toLongValue(cookie.get("maxAge")), + toBooleanValue(cookie.get("secure")), + toBooleanValue(cookie.get("httpOnly")), + toInstantValue(cookie.get("expires")), + toIntegerValue(cookie.get("version")), + toStringValue(cookie.get("sameSite")) + )); + builder.headerConverter(headerConverter).cookieConverter(cookieConverter).prettifiers(prettifiers); + Object body = response.getBody(); + if (body == null) { + return builder.build(); + } + String contentType = response.getContentType(); + String mimeType = HttpFormatUtils.getMimeType(contentType); + BodyType bodyType = HttpFormatUtils.getBodyType(contentType, bodyTypeMap); + if (BodyType.TEXT == bodyType) { + builder.bodyText(mimeType, response.getBodyString()); + } else { + builder.bodyBytes(mimeType, response.getBodyBytes()); + } + return builder.build(); + } + + @Nonnull + private static List toParts(@Nonnull HttpRequest request, @Nonnull Map bodyTypeMap, + @Nullable Function partHeaderConverter) { + Map>> multipartMap = request.getMultiParts(); + if (multipartMap == null || multipartMap.isEmpty()) { + return Collections.emptyList(); + } + List parts = new ArrayList<>(); + multipartMap.values().stream().filter(Objects::nonNull).flatMap(List::stream).forEach(part -> { + String partMimeType = ofNullable(part.get("contentType")).map(Object::toString).orElse("application/octet-stream"); + Object value = part.get("value"); + BodyType partBodyType = HttpFormatUtils.getBodyType(partMimeType, bodyTypeMap); + HttpPartFormatter.PartType partType = + BodyType.TEXT == partBodyType ? HttpPartFormatter.PartType.TEXT : HttpPartFormatter.PartType.BINARY; + Object payload = partType == HttpPartFormatter.PartType.TEXT ? toTextValue(value) : toBinaryValue(value); + HttpPartFormatter.Builder partBuilder = new HttpPartFormatter.Builder(partType, partMimeType, payload); + partBuilder.controlName(ofNullable(part.get("name")).map(Object::toString).orElse(null)); + partBuilder.charset(ofNullable(part.get("charset")).map(Object::toString).orElse(null)); + partBuilder.fileName(ofNullable(part.get("filename")).map(Object::toString).orElse(null)); + partBuilder.headerConverter(partHeaderConverter); + parts.add(partBuilder.build()); + }); + return parts; + } + + @Nonnull + private static String getStatusLine(@Nonnull HttpResponse response) { + return isNotBlank(response.getStatusText()) ? + response.getStatus() + " " + response.getStatusText() : + Integer.toString(response.getStatus()); + } + + @Nonnull + private static String toTextValue(@Nullable Object value) { + if (value == null) { + return ""; + } + if (value instanceof byte[] bytes) { + return new String(bytes, StandardCharsets.UTF_8); + } + return value.toString(); + } + + @Nonnull + private static byte[] toBinaryValue(@Nullable Object value) { + if (value == null) { + return new byte[0]; + } + if (value instanceof byte[] bytes) { + return bytes; + } + return value.toString().getBytes(StandardCharsets.UTF_8); + } + + @Nullable + private static String toStringValue(@Nullable Object value) { + return value == null ? null : value.toString(); + } + + @Nullable + private static Long toLongValue(@Nullable Object value) { + if (value == null) { + return null; + } + if (value instanceof Number number) { + return number.longValue(); + } + try { + return Long.parseLong(value.toString()); + } catch (NumberFormatException ignored) { + return null; + } + } + + @Nullable + private static Integer toIntegerValue(@Nullable Object value) { + if (value == null) { + return null; + } + if (value instanceof Number number) { + return number.intValue(); + } + try { + return Integer.parseInt(value.toString()); + } catch (NumberFormatException ignored) { + return null; + } + } + + @Nullable + private static Boolean toBooleanValue(@Nullable Object value) { + if (value == null) { + return null; + } + if (value instanceof Boolean b) { + return b; + } + return Boolean.parseBoolean(value.toString()); + } + + @Nullable + private static Instant toInstantValue(@Nullable Object value) { + if (value == null) { + return null; + } + if (value instanceof Instant instant) { + return instant; + } + try { + return Instant.parse(value.toString()); + } catch (DateTimeParseException ignored) { + return null; + } + } +} diff --git a/src/test/java/com/epam/reportportal/karate/logging/HttpRequestLoggingTest.java b/src/test/java/com/epam/reportportal/karate/logging/HttpRequestLoggingTest.java index d91b673..4684488 100644 --- a/src/test/java/com/epam/reportportal/karate/logging/HttpRequestLoggingTest.java +++ b/src/test/java/com/epam/reportportal/karate/logging/HttpRequestLoggingTest.java @@ -25,8 +25,7 @@ import io.karatelabs.core.SuiteResult; import okhttp3.MultipartBody; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; +import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import java.util.List; @@ -40,6 +39,16 @@ public class HttpRequestLoggingTest { private static final String TEST_FEATURE = "classpath:feature/http_request.feature"; + private static final String DOCSTRING_LOG_ENTRY = """ + Docstring: + + ``` + { + username: 'user', + password: 'password', + grant_type: 'password' + } + ```"""; private final String launchUuid = CommonUtils.namedId("launch_"); private final String featureId = CommonUtils.namedId("feature_"); private final String scenarioId = CommonUtils.namedId("scenario_"); @@ -54,18 +63,8 @@ public void setupMock() { mockBatchLogging(client); } - @ParameterizedTest - @ValueSource(booleans = { true, false }) @SuppressWarnings({ "unchecked", "rawtypes" }) - public void test_http_request_logging(boolean report) { - SuiteResult results; - if (report) { - results = TestUtils.runAsResultListener(rp, TEST_FEATURE); - } else { - results = TestUtils.runAsEventListener(rp, TEST_FEATURE); - } - assertThat(results.getFeatureFailedCount(), equalTo(1)); - + private List extractMessages() { ArgumentCaptor logCaptor = ArgumentCaptor.forClass(List.class); verify(client, atLeastOnce()).log(logCaptor.capture()); List logs = logCaptor.getAllValues() @@ -75,20 +74,26 @@ public void test_http_request_logging(boolean report) { .collect(Collectors.toList()); assertThat(logs, hasSize(greaterThanOrEqualTo(2))); - List messages = logs.stream().map(SaveLogRQ::getMessage).collect(Collectors.toList()); - assertThat( - messages, hasItems( - equalTo(""" - Docstring: - - ``` - { - username: 'user', - password: 'password', - grant_type: 'password' - } - ```"""), containsString("{\"username\":\"user\",\"password\":\"password\",\"grant_type\":\"password\"}") - ) - ); + return logs.stream().map(SaveLogRQ::getMessage).collect(Collectors.toList()); + } + + @Test + public void test_http_request_logging_result_listener() { + SuiteResult results = TestUtils.runAsResultListener(rp, TEST_FEATURE); + assertThat(results.getFeatureFailedCount(), equalTo(1)); + List messages = extractMessages(); + assertThat(messages, hasItem(equalTo(DOCSTRING_LOG_ENTRY))); + assertThat(messages, hasItem(containsString("{\"username\":\"user\",\"password\":\"password\",\"grant_type\":\"password\"}"))); + } + + @Test + public void test_http_request_logging_run_listener() { + SuiteResult results = TestUtils.runAsEventListener(rp, TEST_FEATURE); + assertThat(results.getFeatureFailedCount(), equalTo(1)); + List messages = extractMessages(); + assertThat(messages, hasItem(equalTo(DOCSTRING_LOG_ENTRY))); + assertThat(messages, hasItem(containsString("**>>> REQUEST**"))); + assertThat(messages, hasItem(containsString("**<<< RESPONSE**"))); + assertThat(messages, hasItem(containsString("\"username\" : \"user\""))); } } From 3295c5dd0ec94d34dc8e3868c4394ac81f9ae556 Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Tue, 28 Apr 2026 22:17:57 +0300 Subject: [PATCH 17/19] CHANGELOG.md update --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5b6d05..eb7ed8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog ## [Unreleased] +### Added +- Karate 2.x support, by @HardNorth +### Removed +- Java 17-20 support, by @HardNorth +- Karate 1.x support, by @HardNorth ## [5.4.0] ### Changed From 245baae2236e9e5bde3dd5bc6518f17c4e057684 Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Tue, 28 Apr 2026 22:20:57 +0300 Subject: [PATCH 18/19] CHANGELOG.md update --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index eb7ed8c..74cd032 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## [Unreleased] ### Added - Karate 2.x support, by @HardNorth +- Fancy HTTP logging, by @HardNorth ### Removed - Java 17-20 support, by @HardNorth - Karate 1.x support, by @HardNorth From 7fdf8196c8825c68c08be1b4bda790b5e127a18f Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Tue, 28 Apr 2026 22:51:35 +0300 Subject: [PATCH 19/19] README_TEMPLATE.md update --- README_TEMPLATE.md | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/README_TEMPLATE.md b/README_TEMPLATE.md index 650d3e1..e2840a3 100644 --- a/README_TEMPLATE.md +++ b/README_TEMPLATE.md @@ -1,4 +1,4 @@ -# ReportPortal runtime Hook for Karate tests +# ReportPortal Listeners for Karate tests Karate reporters which uploads the results to a ReportPortal server. @@ -98,29 +98,30 @@ dependencies { ### Runtime Runtime publisher uploads Karate tests on ReportPortal during the test execution, providing real-time monitoring capabilities. To publish -test results in this case, the test project should use by `ReportPortalHook` class, an instance of which you should pass to Karate runner. +test results in this case, the test project should use `ReportPortalRunListener` class, an instance of which you should pass to Karate +runner. E.G.: ```java -import com.epam.reportportal.karate.ReportPortalResultListener; -import com.intuit.karate.Results; -import com.intuit.karate.Runner; +import com.epam.reportportal.karate.ReportPortalRunListener; +import io.karatelabs.core.Runner; +import io.karatelabs.core.SuiteResult; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; class ScenarioRunnerTest { @Test void testParallel() { - ReportPortalHook karateRuntimeHook = new ReportPortalHook(); // Initialize ReportPortal runtime Karate hook - Results results = Runner // Regular Karate runner + ReportPortalRunListener karateRuntimeListener = new ReportPortalRunListener(); // Initialize ReportPortal runtime Karate listener + SuiteResult results = Runner // Regular Karate runner .path("classpath:features") // Path with feature files - .hook(karateRuntimeHook) // Add Karate hook + .listener(karateRuntimeListener) // Add Karate run listener .outputCucumberJson(true) // Generate cucumber report .tags("~@ignore") // Ignore tests marked with the tag .parallel(2); // Run in 2 Threads // Here you can additionally run tests, retries, etc. - karateRuntimeHook.finishLaunch(); // Finish execution on ReportPortal - Assertions.assertEquals(0, results.getFailCount(), "Non-zero fail count.\n Errors:\n" + results.getErrorMessages()); + karateRuntimeListener.finishLaunch(); // Finish execution on ReportPortal + Assertions.assertEquals(0, results.getFeatureFailedCount(), "Non-zero fail count.\n Errors:\n" + results.getErrors()); } } ``` @@ -129,12 +130,13 @@ class ScenarioRunnerTest { Post-running publisher uploads Karate tests on ReportPortal after the test execution. It uses Karate result object to get data about tests. It might be useful if your tests make heavy load both on ReportPortal server or on the running node. To publish test results in this case, -the test project should run by `KarateReportPortalRunner` instead of Karate runner. +the test project should add `ReportPortalResultListener` to Karate runner. E.G.: ```java -import com.epam.reportportal.karate.KarateReportPortalRunner; -import com.intuit.karate.Results; +import com.epam.reportportal.karate.ReportPortalResultListener; +import io.karatelabs.core.Runner; +import io.karatelabs.core.SuiteResult; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -142,12 +144,15 @@ public class KarateRunnerTest { @Test public void testAll() { - Results results = KarateReportPortalRunner // Our runner with a Karate Publisher + ReportPortalResultListener resultListener = new ReportPortalResultListener(); // Initialize ReportPortal result listener + SuiteResult results = Runner // Regular Karate runner with ReportPortal result listener .path("classpath:features") // Path with feature files + .resultListener(resultListener) // Add Karate result listener .outputCucumberJson(true) // Generate cucumber report .tags("~@ignore") // Ignore tests marked with the tag .parallel(2); // Run in 2 Threads - Assertions.assertEquals(0, results.getFailCount(), "Non-zero fail count.\n Errors:\n" + results.getErrorMessages()); + resultListener.finishLaunch(); // Finish execution on ReportPortal + Assertions.assertEquals(0, results.getFeatureFailedCount(), "Non-zero fail count.\n Errors:\n" + results.getErrors()); } } ```