From 8e23d949cd9680e96e18a43e2589314e6aa8fb1d Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Wed, 30 Oct 2024 15:20:17 +0300 Subject: [PATCH 01/16] Client version update --- CHANGELOG.md | 2 ++ build.gradle | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b8be897..8da53b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Changelog ## [Unreleased] +### Changed +- Client version updated on [5.2.16](https://github.com/reportportal/client-java/releases/tag/5.2.16), by @HardNorth ## [5.3.3] ### Added diff --git a/build.gradle b/build.gradle index 8613d4a..8a0d32d 100644 --- a/build.gradle +++ b/build.gradle @@ -37,7 +37,7 @@ repositories { } dependencies { - api 'com.epam.reportportal:client-java:5.2.14' + api 'com.epam.reportportal:client-java:5.2.16' compileOnly "org.junit.jupiter:junit-jupiter-api:${junit_version}" implementation 'org.slf4j:slf4j-api:2.0.7' From d0c887347ad1bc7c2b3c13eed27aea4b0b1e9796 Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Wed, 30 Oct 2024 17:09:13 +0300 Subject: [PATCH 02/16] Remove throwable storing --- .../reportportal/junit5/ReportPortalExtension.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java b/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java index 4b5a0da..7b5f716 100644 --- a/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java +++ b/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java @@ -93,7 +93,6 @@ public class ReportPortalExtension private final Map> testTemplates = new ConcurrentHashMap<>(); private final Set failedClassInits = Collections.newSetFromMap(new ConcurrentHashMap<>()); public static final String DESCRIPTION_TEST_ERROR_FORMAT = "%s\nError: \n%s"; - private final Map testThrowable = new ConcurrentHashMap<>(); @Nonnull protected Optional> getItemId(@Nonnull ExtensionContext context) { return ofNullable(idMapping.get(context)); @@ -292,12 +291,12 @@ public T interceptTestFactoryMethod(Invocation invocation, * @param throwable test exception * @return an {@link ItemStatus} */ + @SuppressWarnings("unused") @Nonnull protected ItemStatus getExecutionStatus(@Nonnull final ExtensionContext context, @Nullable final Throwable throwable) { if (throwable == null) { return PASSED; } - testThrowable.put(context, throwable); sendStackTraceToRP(throwable); return IS_ASSUMPTION.test(throwable) ? SKIPPED : FAILED; } @@ -372,7 +371,6 @@ public void testFailed(ExtensionContext context, Throwable cause) { if(failedClassInits.contains(parent)) { startTestItem(context, STEP); sendStackTraceToRP(cause); - testThrowable.put(context, cause); finishTest(context, FAILED); } }); @@ -762,16 +760,16 @@ protected void createSkippedSteps(ExtensionContext context, Throwable cause) { @Nonnull protected FinishTestItemRQ buildFinishTestRq(@Nonnull ExtensionContext context, @Nullable ItemStatus status) { FinishTestItemRQ rq = new FinishTestItemRQ(); - if (status != ItemStatus.PASSED && testThrowable.containsKey(context)) { - ItemType itemType = STEP; + ItemStatus myStatus = ofNullable(status).orElseGet(() -> getExecutionStatus(context)); + Optional myException = context.getExecutionException(); + if (status != ItemStatus.PASSED && myException.isPresent()) { String description = String.format(DESCRIPTION_TEST_ERROR_FORMAT, - createStepDescription(context, itemType), - ExceptionUtils.getStackTrace(testThrowable.get(context))); + createStepDescription(context, STEP), + ExceptionUtils.getStackTrace(myException.get())); rq.setDescription(description); } ofNullable(status).ifPresent(s -> rq.setStatus(s.name())); rq.setEndTime(Calendar.getInstance().getTime()); - testThrowable.remove(context); return rq; } From 00a6fc0c899e3a40a346b06e9aaabdd02da04415 Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Wed, 30 Oct 2024 17:29:11 +0300 Subject: [PATCH 03/16] Minor refactoring --- .../junit5/ReportPortalExtension.java | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java b/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java index 7b5f716..fced6cc 100644 --- a/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java +++ b/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java @@ -36,7 +36,6 @@ import com.epam.ta.reportportal.ws.model.log.SaveLogRQ; import io.reactivex.Maybe; import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.exception.ExceptionUtils; import org.junit.jupiter.api.*; import org.junit.jupiter.api.extension.*; import org.opentest4j.TestAbortedException; @@ -301,6 +300,17 @@ protected ItemStatus getExecutionStatus(@Nonnull final ExtensionContext context, return IS_ASSUMPTION.test(throwable) ? SKIPPED : FAILED; } + /** + * Returns a status of a test based on whether or not it contains an execution exception + * + * @param context JUnit's test context + * @return an {@link ItemStatus} + */ + @Nonnull + protected ItemStatus getExecutionStatus(@Nonnull final ExtensionContext context) { + return context.getExecutionException().map(t -> getExecutionStatus(context, t)).orElse(PASSED); + } + @Override public void interceptDynamicTest(Invocation invocation, DynamicTestInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { @@ -335,16 +345,7 @@ public void interceptTestTemplateMethod(Invocation invocation, invocation.proceed(); } - /** - * Returns a status of a test based on whether or not it contains an execution exception - * - * @param context JUnit's test context - * @return an {@link ItemStatus} - */ - @Nonnull - protected ItemStatus getExecutionStatus(@Nonnull final ExtensionContext context) { - return context.getExecutionException().map(t -> getExecutionStatus(context, t)).orElse(PASSED); - } + @Override public void afterTestExecution(ExtensionContext context) { @@ -765,7 +766,7 @@ protected FinishTestItemRQ buildFinishTestRq(@Nonnull ExtensionContext context, if (status != ItemStatus.PASSED && myException.isPresent()) { String description = String.format(DESCRIPTION_TEST_ERROR_FORMAT, createStepDescription(context, STEP), - ExceptionUtils.getStackTrace(myException.get())); + getStackTrace(myException.get())); rq.setDescription(description); } ofNullable(status).ifPresent(s -> rq.setStatus(s.name())); From 632c44278fa87e6977209aef9b42bab8abf7ebb4 Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Fri, 1 Nov 2024 17:13:39 +0300 Subject: [PATCH 04/16] Client version update --- CHANGELOG.md | 2 +- build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8da53b4..c6b16a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## [Unreleased] ### Changed -- Client version updated on [5.2.16](https://github.com/reportportal/client-java/releases/tag/5.2.16), by @HardNorth +- Client version updated on [5.2.18](https://github.com/reportportal/client-java/releases/tag/5.2.18), by @HardNorth ## [5.3.3] ### Added diff --git a/build.gradle b/build.gradle index 8a0d32d..f0eac20 100644 --- a/build.gradle +++ b/build.gradle @@ -37,7 +37,7 @@ repositories { } dependencies { - api 'com.epam.reportportal:client-java:5.2.16' + api 'com.epam.reportportal:client-java:5.2.18' compileOnly "org.junit.jupiter:junit-jupiter-api:${junit_version}" implementation 'org.slf4j:slf4j-api:2.0.7' From 5680b830533b262a9b34c84a3b30d31a6d43e680 Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Fri, 1 Nov 2024 17:14:04 +0300 Subject: [PATCH 05/16] Improve stack traces formatting --- CHANGELOG.md | 2 ++ .../reportportal/junit5/ReportPortalExtension.java | 14 +++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c6b16a5..8444e4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Changelog ## [Unreleased] +### Added +- Common Stack Trace frames skip in description and logs, by @HardNorth ### Changed - Client version updated on [5.2.18](https://github.com/reportportal/client-java/releases/tag/5.2.18), by @HardNorth diff --git a/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java b/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java index fced6cc..c769072 100644 --- a/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java +++ b/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java @@ -29,7 +29,7 @@ import com.epam.reportportal.utils.AttributeParser; import com.epam.reportportal.utils.ParameterUtils; import com.epam.reportportal.utils.TestCaseIdUtils; -import com.epam.reportportal.utils.markdown.MarkdownUtils; +import com.epam.reportportal.utils.formatting.MarkdownUtils; import com.epam.ta.reportportal.ws.model.*; import com.epam.ta.reportportal.ws.model.attribute.ItemAttributesRQ; import com.epam.ta.reportportal.ws.model.launch.StartLaunchRQ; @@ -59,7 +59,7 @@ import static com.epam.reportportal.service.tree.TestItemTree.createTestItemLeaf; import static java.util.Optional.of; import static java.util.Optional.ofNullable; -import static org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace; +import static com.epam.reportportal.utils.formatting.ExceptionUtils.getStackTrace; /* * ReportPortal Extension sends the results of test execution to ReportPortal in RealTime @@ -91,7 +91,7 @@ public class ReportPortalExtension private final Map> idMapping = new ConcurrentHashMap<>(); private final Map> testTemplates = new ConcurrentHashMap<>(); private final Set failedClassInits = Collections.newSetFromMap(new ConcurrentHashMap<>()); - public static final String DESCRIPTION_TEST_ERROR_FORMAT = "%s\nError: \n%s"; + public static final String DESCRIPTION_TEST_ERROR_FORMAT = "Error: \n%s"; @Nonnull protected Optional> getItemId(@Nonnull ExtensionContext context) { return ofNullable(idMapping.get(context)); @@ -764,9 +764,9 @@ protected FinishTestItemRQ buildFinishTestRq(@Nonnull ExtensionContext context, ItemStatus myStatus = ofNullable(status).orElseGet(() -> getExecutionStatus(context)); Optional myException = context.getExecutionException(); if (status != ItemStatus.PASSED && myException.isPresent()) { - String description = String.format(DESCRIPTION_TEST_ERROR_FORMAT, - createStepDescription(context, STEP), - getStackTrace(myException.get())); + String stepDescription = createStepDescription(context, STEP); + String stackTrace = String.format(DESCRIPTION_TEST_ERROR_FORMAT, getStackTrace(myException.get(), new Throwable())); + String description = !stepDescription.trim().isEmpty() ? MarkdownUtils.asTwoParts(stepDescription, stackTrace) : stackTrace; rq.setDescription(description); } ofNullable(status).ifPresent(s -> rq.setStatus(s.name())); @@ -960,7 +960,7 @@ protected void sendStackTraceToRP(final Throwable cause) { rq.setLevel("ERROR"); rq.setLogTime(Calendar.getInstance().getTime()); if (cause != null) { - rq.setMessage(getStackTrace(cause)); + rq.setMessage(getStackTrace(cause, new Throwable())); } else { rq.setMessage("Test has failed without exception"); } From f558699a1ddd60f914c14f7fc184f246e52088f0 Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Fri, 1 Nov 2024 17:22:59 +0300 Subject: [PATCH 06/16] Fix tests --- .../reportportal/junit5/ErrorLastLogTest.java | 181 ++++++++++-------- 1 file changed, 96 insertions(+), 85 deletions(-) diff --git a/src/test/java/com/epam/reportportal/junit5/ErrorLastLogTest.java b/src/test/java/com/epam/reportportal/junit5/ErrorLastLogTest.java index 734eb42..1f3fb19 100644 --- a/src/test/java/com/epam/reportportal/junit5/ErrorLastLogTest.java +++ b/src/test/java/com/epam/reportportal/junit5/ErrorLastLogTest.java @@ -8,6 +8,7 @@ import com.epam.reportportal.service.Launch; import com.epam.reportportal.service.ReportPortal; import com.epam.reportportal.service.ReportPortalClient; +import com.epam.reportportal.utils.formatting.MarkdownUtils; import com.epam.ta.reportportal.ws.model.FinishTestItemRQ; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; @@ -30,122 +31,132 @@ @TestInstance(TestInstance.Lifecycle.PER_CLASS) public class ErrorLastLogTest { - private final String testErrorMessagePattern = "%s\nError: \n%s"; - private final String assertErrorMessage = "org.opentest4j.AssertionFailedError: expected: <0> but was: <1>"; - private final String exceptionStepErrorMessage = "java.util.NoSuchElementException: Error message"; - private final String testExceptionMessage = "java.lang.RuntimeException: Critical error"; - private final String assertDescriptionMessage = "0 and 1 is not equal"; - private final String stepDescriptionMessage = "Login issue"; - private final String failedStatus = "FAILED"; - private final String passedStatus = "PASSED"; - static final String testClassUuid = namedId("class"); - static final String testMethodUuid = namedId("test"); - public static class ErrorDescriptionTestExtension extends ReportPortalExtension { + private static final String TEST_ERROR_MESSAGE_PATTERN = "Error: \n%s"; + private static final String ASSERT_ERROR_MESSAGE = "org.opentest4j.AssertionFailedError: expected: <0> but was: <1>"; + private static final String EXCEPTION_STEP_ERROR_MESSAGE = "java.util.NoSuchElementException: Error message"; + private static final String TEST_EXCEPTION_MESSAGE = "java.lang.RuntimeException: Critical error"; + private static final String ASSERT_DESCRIPTION_MESSAGE = "0 and 1 is not equal"; + private static final String STEP_DESCRIPTION_MESSAGE = "Login issue"; + private static final String FAILED_STATUS = "FAILED"; + private static final String PASSED_STATUS = "PASSED"; + private static final String TEST_CLASS_UUID = namedId("class"); + private static final String TEST_METHOD_UUID = namedId("test"); - static final ThreadLocal client = new ThreadLocal<>(); - static final ThreadLocal launch = new ThreadLocal<>(); - public static void init() { - client.set(mock(ReportPortalClient.class)); - TestUtils.mockLaunch(client.get(), "launchUuid", testClassUuid, testMethodUuid); - TestUtils.mockLogging(client.get()); - ReportPortal reportPortal = ReportPortal.create(client.get(), TestUtils.standardParameters()); - launch.set(reportPortal.newLaunch(TestUtils.launchRQ(reportPortal.getParameters()))); + public static class ErrorDescriptionTestExtension extends ReportPortalExtension { - } + static final ThreadLocal client = new ThreadLocal<>(); + static final ThreadLocal launch = new ThreadLocal<>(); - @Override - protected Launch getLaunch(ExtensionContext context) { - return launch.get(); - } + public static void init() { + client.set(mock(ReportPortalClient.class)); + TestUtils.mockLaunch(client.get(), "launchUuid", TEST_CLASS_UUID, TEST_METHOD_UUID); + TestUtils.mockLogging(client.get()); + ReportPortal reportPortal = ReportPortal.create(client.get(), TestUtils.standardParameters()); + launch.set(reportPortal.newLaunch(TestUtils.launchRQ(reportPortal.getParameters()))); - } + } - public static class Listener implements TestExecutionListener { - public Deque results = new ConcurrentLinkedDeque<>(); + @Override + protected Launch getLaunch(ExtensionContext context) { + return launch.get(); + } - @Override - public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) { - if (testIdentifier.isTest()) { - results.add(testExecutionResult); - } - } - } + } - @Test - public void verify_last_error_log_exception() { - ErrorDescriptionTestExtension.init(); - Listener listener = new Listener(); - TestUtils.runClasses(listener, ErrorLastLogFeatureWithExceptionTest.class); + public static class Listener implements TestExecutionListener { + public Deque results = new ConcurrentLinkedDeque<>(); - ReportPortalClient client = ErrorDescriptionTestExtension.client.get(); + @Override + public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) { + if (testIdentifier.isTest()) { + results.add(testExecutionResult); + } + } + } - ArgumentCaptor finishTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); - verify(client, timeout(1000).atLeastOnce()).finishTestItem(same(testMethodUuid), finishTestCaptor.capture()); + @Test + public void verify_last_error_log_exception() { + ErrorDescriptionTestExtension.init(); + Listener listener = new Listener(); + TestUtils.runClasses(listener, ErrorLastLogFeatureWithExceptionTest.class); + ReportPortalClient client = ErrorDescriptionTestExtension.client.get(); - List finishTests = finishTestCaptor.getAllValues(); + ArgumentCaptor finishTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); + verify(client, timeout(1000).atLeastOnce()).finishTestItem(same(TEST_METHOD_UUID), finishTestCaptor.capture()); - FinishTestItemRQ testCaseWithException = finishTests.get(0); + List finishTests = finishTestCaptor.getAllValues(); - assertThat(testCaseWithException.getDescription(), startsWith(String.format(testErrorMessagePattern, "", testExceptionMessage))); - assertThat(testCaseWithException.getStatus(), equalTo(failedStatus)); + FinishTestItemRQ testCaseWithException = finishTests.get(0); - } + assertThat(testCaseWithException.getDescription(), startsWith(String.format(TEST_ERROR_MESSAGE_PATTERN, TEST_EXCEPTION_MESSAGE))); + assertThat(testCaseWithException.getStatus(), equalTo(FAILED_STATUS)); - @Test - public void verify_last_error_log_step() { - ErrorDescriptionTestExtension.init(); - Listener listener = new Listener(); - TestUtils.runClasses(listener, ErrorLastLogFeatureWithStepTest.class); + } - ReportPortalClient client = ErrorDescriptionTestExtension.client.get(); + @Test + public void verify_last_error_log_step() { + ErrorDescriptionTestExtension.init(); + Listener listener = new Listener(); + TestUtils.runClasses(listener, ErrorLastLogFeatureWithStepTest.class); - ArgumentCaptor finishTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); - verify(client, timeout(1000).atLeastOnce()).finishTestItem(same(testMethodUuid), finishTestCaptor.capture()); + ReportPortalClient client = ErrorDescriptionTestExtension.client.get(); - List finishTests = finishTestCaptor.getAllValues(); + ArgumentCaptor finishTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); + verify(client, timeout(1000).atLeastOnce()).finishTestItem(same(TEST_METHOD_UUID), finishTestCaptor.capture()); - FinishTestItemRQ testCaseWithDescriptionAndStepError = finishTests.get(0); + List finishTests = finishTestCaptor.getAllValues(); - assertThat(testCaseWithDescriptionAndStepError.getDescription(), startsWith(String.format(testErrorMessagePattern, stepDescriptionMessage, exceptionStepErrorMessage))); - assertThat(testCaseWithDescriptionAndStepError.getStatus(), equalTo(failedStatus)); - } + FinishTestItemRQ testCaseWithDescriptionAndStepError = finishTests.get(0); - @Test - public void verify_last_error_log_assertion_error() { - ErrorDescriptionTestExtension.init(); - Listener listener = new Listener(); - TestUtils.runClasses(listener, ErrorLastLogFeatureWithAssertionErrorTest.class); + assertThat(testCaseWithDescriptionAndStepError.getDescription(), + startsWith(MarkdownUtils.asTwoParts(STEP_DESCRIPTION_MESSAGE, + String.format(TEST_ERROR_MESSAGE_PATTERN, EXCEPTION_STEP_ERROR_MESSAGE) + )) + ); + assertThat(testCaseWithDescriptionAndStepError.getStatus(), equalTo(FAILED_STATUS)); + } - ReportPortalClient client = ErrorDescriptionTestExtension.client.get(); + @Test + public void verify_last_error_log_assertion_error() { + ErrorDescriptionTestExtension.init(); + Listener listener = new Listener(); + TestUtils.runClasses(listener, ErrorLastLogFeatureWithAssertionErrorTest.class); - ArgumentCaptor finishTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); - verify(client, timeout(1000).atLeastOnce()).finishTestItem(same(testMethodUuid), finishTestCaptor.capture()); + ReportPortalClient client = ErrorDescriptionTestExtension.client.get(); - List finishTests = finishTestCaptor.getAllValues(); + ArgumentCaptor finishTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); + verify(client, timeout(1000).atLeastOnce()).finishTestItem(same(TEST_METHOD_UUID), finishTestCaptor.capture()); - FinishTestItemRQ testCaseAssertException = finishTests.get(0); + List finishTests = finishTestCaptor.getAllValues(); - assertThat(testCaseAssertException.getDescription(), startsWith(String.format(testErrorMessagePattern, assertDescriptionMessage, assertErrorMessage))); - assertThat(testCaseAssertException.getStatus(), equalTo(failedStatus)); - } + FinishTestItemRQ testCaseAssertException = finishTests.get(0); - @Test - public void verify_last_error_log_assertion_passed() { - ErrorDescriptionTestExtension.init(); - Listener listener = new Listener(); - TestUtils.runClasses(listener, ErrorLastLogFeatureWithAssertionPassedTest.class); + assertThat(testCaseAssertException.getDescription(), + startsWith(MarkdownUtils.asTwoParts( + ASSERT_DESCRIPTION_MESSAGE, + String.format(TEST_ERROR_MESSAGE_PATTERN, ASSERT_ERROR_MESSAGE) + )) + ); + assertThat(testCaseAssertException.getStatus(), equalTo(FAILED_STATUS)); + } - ReportPortalClient client = ErrorDescriptionTestExtension.client.get(); + @Test + public void verify_last_error_log_assertion_passed() { + ErrorDescriptionTestExtension.init(); + Listener listener = new Listener(); + TestUtils.runClasses(listener, ErrorLastLogFeatureWithAssertionPassedTest.class); - ArgumentCaptor finishTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); - verify(client, timeout(1000).atLeastOnce()).finishTestItem(same(testMethodUuid), finishTestCaptor.capture()); + ReportPortalClient client = ErrorDescriptionTestExtension.client.get(); - List finishTests = finishTestCaptor.getAllValues(); + ArgumentCaptor finishTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); + verify(client, timeout(1000).atLeastOnce()).finishTestItem(same(TEST_METHOD_UUID), finishTestCaptor.capture()); - FinishTestItemRQ testCaseWithDescriptionAndPassed = finishTests.get(0); + List finishTests = finishTestCaptor.getAllValues(); - assertThat(testCaseWithDescriptionAndPassed.getStatus(), equalTo(passedStatus)); + FinishTestItemRQ testCaseWithDescriptionAndPassed = finishTests.get(0); - } + assertThat(testCaseWithDescriptionAndPassed.getStatus(), equalTo(PASSED_STATUS)); + + } } From d5d779accead01836318247bbda675a2c748e7ea Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Mon, 4 Nov 2024 09:40:11 +0300 Subject: [PATCH 07/16] Fix status calculation --- .../com/epam/reportportal/junit5/ReportPortalExtension.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java b/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java index c769072..80066e1 100644 --- a/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java +++ b/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java @@ -757,13 +757,12 @@ protected void createSkippedSteps(ExtensionContext context, Throwable cause) { * @param status a test item execution result * @return Request to ReportPortal */ - @SuppressWarnings("unused") @Nonnull protected FinishTestItemRQ buildFinishTestRq(@Nonnull ExtensionContext context, @Nullable ItemStatus status) { FinishTestItemRQ rq = new FinishTestItemRQ(); ItemStatus myStatus = ofNullable(status).orElseGet(() -> getExecutionStatus(context)); Optional myException = context.getExecutionException(); - if (status != ItemStatus.PASSED && myException.isPresent()) { + if (myStatus != ItemStatus.PASSED && myException.isPresent()) { String stepDescription = createStepDescription(context, STEP); String stackTrace = String.format(DESCRIPTION_TEST_ERROR_FORMAT, getStackTrace(myException.get(), new Throwable())); String description = !stepDescription.trim().isEmpty() ? MarkdownUtils.asTwoParts(stepDescription, stackTrace) : stackTrace; From 0163c32cf714957f7761a5b7657dc53d99c59efa Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Mon, 4 Nov 2024 09:45:59 +0300 Subject: [PATCH 08/16] Use `StringUtils.isNotBlank` for text checking --- .../epam/reportportal/junit5/ReportPortalExtension.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java b/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java index 80066e1..f1d6596 100644 --- a/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java +++ b/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java @@ -135,7 +135,7 @@ protected StartLaunchRQ buildStartLaunchRq(ListenerParameters parameters) { rq.setAttributes(attributes); rq.setStartTime(Calendar.getInstance().getTime()); rq.setRerun(parameters.isRerun()); - rq.setRerunOf(StringUtils.isEmpty(parameters.getRerunOf()) ? null : parameters.getRerunOf()); + rq.setRerunOf(StringUtils.isNotBlank(parameters.getRerunOf()) ? parameters.getRerunOf() : null); return rq; } @@ -604,7 +604,7 @@ private static String getCodeRef(@Nonnull final Method method) { } private static String appendSuffixIfNotEmpty(final String str, @Nonnull final String suffix) { - return str + (suffix.isEmpty() ? "" : "$" + suffix); + return str + (StringUtils.isNotBlank(suffix) ? "$" + suffix : ""); } @Nonnull @@ -765,7 +765,9 @@ protected FinishTestItemRQ buildFinishTestRq(@Nonnull ExtensionContext context, if (myStatus != ItemStatus.PASSED && myException.isPresent()) { String stepDescription = createStepDescription(context, STEP); String stackTrace = String.format(DESCRIPTION_TEST_ERROR_FORMAT, getStackTrace(myException.get(), new Throwable())); - String description = !stepDescription.trim().isEmpty() ? MarkdownUtils.asTwoParts(stepDescription, stackTrace) : stackTrace; + String description = StringUtils.isNotBlank(stepDescription) ? + MarkdownUtils.asTwoParts(stepDescription, stackTrace) : + stackTrace; rq.setDescription(description); } ofNullable(status).ifPresent(s -> rq.setStatus(s.name())); From b752cc1ae3fe955e6dd5fe6647bfb5332a76be8e Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Tue, 5 Nov 2024 13:58:52 +0300 Subject: [PATCH 09/16] Client version update --- CHANGELOG.md | 2 +- build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8444e4d..763612b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ ### Added - Common Stack Trace frames skip in description and logs, by @HardNorth ### Changed -- Client version updated on [5.2.18](https://github.com/reportportal/client-java/releases/tag/5.2.18), by @HardNorth +- Client version updated on [5.2.19](https://github.com/reportportal/client-java/releases/tag/5.2.19), by @HardNorth ## [5.3.3] ### Added diff --git a/build.gradle b/build.gradle index f0eac20..29574bb 100644 --- a/build.gradle +++ b/build.gradle @@ -37,7 +37,7 @@ repositories { } dependencies { - api 'com.epam.reportportal:client-java:5.2.18' + api 'com.epam.reportportal:client-java:5.2.19' compileOnly "org.junit.jupiter:junit-jupiter-api:${junit_version}" implementation 'org.slf4j:slf4j-api:2.0.7' From eec2f5091db1f9ef5fb8a929fe886208a9be1fc8 Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Tue, 5 Nov 2024 15:59:16 +0300 Subject: [PATCH 10/16] `@Issue` and `@Issues` annotations support --- CHANGELOG.md | 1 + .../junit5/ReportPortalExtension.java | 271 +++++++++--------- 2 files changed, 132 insertions(+), 140 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 763612b..3784240 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## [Unreleased] ### Added - Common Stack Trace frames skip in description and logs, by @HardNorth +- `@Issue` and `@Issues` annotations support, by @HardNorth ### Changed - Client version updated on [5.2.19](https://github.com/reportportal/client-java/releases/tag/5.2.19), by @HardNorth diff --git a/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java b/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java index f1d6596..7177fa7 100644 --- a/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java +++ b/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java @@ -16,9 +16,7 @@ package com.epam.reportportal.junit5; -import com.epam.reportportal.annotations.Description; -import com.epam.reportportal.annotations.ParameterKey; -import com.epam.reportportal.annotations.TestCaseId; +import com.epam.reportportal.annotations.*; import com.epam.reportportal.annotations.attribute.Attributes; import com.epam.reportportal.listeners.ItemStatus; import com.epam.reportportal.listeners.ListenerParameters; @@ -27,6 +25,7 @@ import com.epam.reportportal.service.item.TestCaseIdEntry; import com.epam.reportportal.service.tree.TestItemTree; import com.epam.reportportal.utils.AttributeParser; +import com.epam.reportportal.utils.IssueUtils; import com.epam.reportportal.utils.ParameterUtils; import com.epam.reportportal.utils.TestCaseIdUtils; import com.epam.reportportal.utils.formatting.MarkdownUtils; @@ -36,6 +35,7 @@ import com.epam.ta.reportportal.ws.model.log.SaveLogRQ; import io.reactivex.Maybe; import org.apache.commons.lang3.StringUtils; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.*; import org.junit.jupiter.api.extension.*; import org.opentest4j.TestAbortedException; @@ -57,16 +57,16 @@ import static com.epam.reportportal.junit5.utils.ItemTreeUtils.createItemTreeKey; import static com.epam.reportportal.listeners.ItemStatus.*; import static com.epam.reportportal.service.tree.TestItemTree.createTestItemLeaf; +import static com.epam.reportportal.utils.formatting.ExceptionUtils.getStackTrace; import static java.util.Optional.of; import static java.util.Optional.ofNullable; -import static com.epam.reportportal.utils.formatting.ExceptionUtils.getStackTrace; /* * ReportPortal Extension sends the results of test execution to ReportPortal in RealTime */ public class ReportPortalExtension - implements Extension, BeforeAllCallback, BeforeEachCallback, InvocationInterceptor, AfterTestExecutionCallback, - AfterAllCallback, TestWatcher { + implements Extension, BeforeAllCallback, BeforeEachCallback, InvocationInterceptor, AfterTestExecutionCallback, AfterAllCallback, + TestWatcher { private static final Logger LOGGER = LoggerFactory.getLogger(ReportPortalExtension.class); @@ -90,8 +90,10 @@ public class ReportPortalExtension private static final Map launchMap = new ConcurrentHashMap<>(); private final Map> idMapping = new ConcurrentHashMap<>(); private final Map> testTemplates = new ConcurrentHashMap<>(); + private final Map> testParameters = new ConcurrentHashMap<>(); private final Set failedClassInits = Collections.newSetFromMap(new ConcurrentHashMap<>()); public static final String DESCRIPTION_TEST_ERROR_FORMAT = "Error: \n%s"; + @Nonnull protected Optional> getItemId(@Nonnull ExtensionContext context) { return ofNullable(idMapping.get(context)); @@ -218,21 +220,15 @@ public void beforeEach(ExtensionContext context) { } @Override - public void interceptBeforeAllMethod(Invocation invocation, - ReflectiveInvocationContext invocationContext, ExtensionContext parentContext) throws Throwable { - Maybe id = startBeforeAfter( - invocationContext.getExecutable(), - parentContext, - parentContext, - BEFORE_CLASS - ); + public void interceptBeforeAllMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, + ExtensionContext parentContext) throws Throwable { + Maybe id = startBeforeAfter(invocationContext.getExecutable(), parentContext, parentContext, BEFORE_CLASS); finishBeforeAll(invocation, invocationContext, parentContext, id); } @Override - public T interceptTestClassConstructor(Invocation invocation, - ReflectiveInvocationContext> invocationContext, - ExtensionContext parentContext) throws Throwable { + public T interceptTestClassConstructor(Invocation invocation, ReflectiveInvocationContext> invocationContext, + ExtensionContext parentContext) throws Throwable { try { return invocation.proceed(); } catch (Throwable cause) { @@ -242,28 +238,23 @@ public T interceptTestClassConstructor(Invocation invocation, } @Override - public void interceptBeforeEachMethod(Invocation invocation, - ReflectiveInvocationContext invocationContext, ExtensionContext context) throws Throwable { + public void interceptBeforeEachMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, + ExtensionContext context) throws Throwable { ExtensionContext parentContext = context.getParent().orElse(context.getRoot()); Maybe id = startBeforeAfter(invocationContext.getExecutable(), parentContext, context, BEFORE_METHOD); finishBeforeEach(invocation, invocationContext, context, id); } @Override - public void interceptAfterAllMethod(Invocation invocation, - ReflectiveInvocationContext invocationContext, ExtensionContext parentContext) throws Throwable { - Maybe id = startBeforeAfter( - invocationContext.getExecutable(), - parentContext, - parentContext, - AFTER_CLASS - ); + public void interceptAfterAllMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, + ExtensionContext parentContext) throws Throwable { + Maybe id = startBeforeAfter(invocationContext.getExecutable(), parentContext, parentContext, AFTER_CLASS); finishBeforeAfter(invocation, parentContext, id); } @Override - public void interceptAfterEachMethod(Invocation invocation, - ReflectiveInvocationContext invocationContext, ExtensionContext context) throws Throwable { + public void interceptAfterEachMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, + ExtensionContext context) throws Throwable { ExtensionContext parentContext = context.getParent().orElse(context.getRoot()); Maybe id = startBeforeAfter(invocationContext.getExecutable(), parentContext, context, AFTER_METHOD); finishBeforeAfter(invocation, context, id); @@ -277,8 +268,8 @@ public void interceptTestMethod(Invocation invocation, ReflectiveInvocatio } @Override - public T interceptTestFactoryMethod(Invocation invocation, - ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { + public T interceptTestFactoryMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, + ExtensionContext extensionContext) throws Throwable { startTestItem(extensionContext, invocationContext.getArguments(), SUITE); return invocation.proceed(); } @@ -286,7 +277,7 @@ public T interceptTestFactoryMethod(Invocation invocation, /** * Returns a status of a test based on execution exception * - * @param context JUnit's test context + * @param context JUnit's test context * @param throwable test exception * @return an {@link ItemStatus} */ @@ -313,7 +304,7 @@ protected ItemStatus getExecutionStatus(@Nonnull final ExtensionContext context) @Override public void interceptDynamicTest(Invocation invocation, DynamicTestInvocationContext invocationContext, - ExtensionContext extensionContext) throws Throwable { + ExtensionContext extensionContext) throws Throwable { Optional parent = extensionContext.getParent(); if (parent.map(p -> !idMapping.containsKey(p)).orElse(false)) { List parents = new ArrayList<>(); @@ -339,14 +330,12 @@ public void interceptDynamicTest(Invocation invocation, DynamicTestInvocat } @Override - public void interceptTestTemplateMethod(Invocation invocation, - ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { + public void interceptTestTemplateMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, + ExtensionContext extensionContext) throws Throwable { startTestItem(extensionContext, invocationContext.getArguments(), STEP); invocation.proceed(); } - - @Override public void afterTestExecution(ExtensionContext context) { finishTemplates(context); @@ -369,7 +358,7 @@ public void testDisabled(ExtensionContext context, Optional reason) { @Override public void testFailed(ExtensionContext context, Throwable cause) { context.getParent().ifPresent(parent -> { - if(failedClassInits.contains(parent)) { + if (failedClassInits.contains(parent)) { startTestItem(context, STEP); sendStackTraceToRP(cause); finishTest(context, FAILED); @@ -419,8 +408,7 @@ protected void finishBeforeEach(Invocation invocation, ReflectiveInvocatio } } - private void finishBeforeAfter(Invocation invocation, ExtensionContext context, Maybe id) - throws Throwable { + private void finishBeforeAfter(Invocation invocation, ExtensionContext context, Maybe id) throws Throwable { try { invocation.proceed(); } catch (Throwable throwable) { @@ -471,33 +459,28 @@ protected void startTestItem(ExtensionContext context, List arguments, I /** * Starts a test item of arbitrary type * - * @param context JUnit's test context - * @param arguments a list of test parameters - * @param itemType a type of the item + * @param context JUnit's test context + * @param arguments a list of test parameters + * @param itemType a type of the item */ protected void startTestItem(@Nonnull final ExtensionContext context, @Nonnull final List arguments, @Nonnull final ItemType itemType, @Nullable final String description, @Nullable final Date startTime) { idMapping.computeIfAbsent(context, c -> { StartTestItemRQ rq = buildStartStepRq(c, arguments, itemType, description, startTime); Launch launch = getLaunch(c); - Maybe itemId = c.getParent() - .flatMap(parent -> Optional.ofNullable(idMapping.get(parent))) - .map(parentTest -> { - Maybe item = launch.startTestItem(parentTest, rq); - if (getReporter().getParameters().isCallbackReportingEnabled()) { - TEST_ITEM_TREE.getTestItems() - .put(createItemTreeKey(rq.getName()), createTestItemLeaf(parentTest, item)); - } - return item; - }) - .orElseGet(() -> { - Maybe item = launch.startTestItem(rq); - if (getReporter().getParameters().isCallbackReportingEnabled()) { - TEST_ITEM_TREE.getTestItems() - .put(createItemTreeKey(rq.getName()), createTestItemLeaf(item)); - } - return item; - }); + Maybe itemId = c.getParent().flatMap(parent -> Optional.ofNullable(idMapping.get(parent))).map(parentTest -> { + Maybe item = launch.startTestItem(parentTest, rq); + if (getReporter().getParameters().isCallbackReportingEnabled()) { + TEST_ITEM_TREE.getTestItems().put(createItemTreeKey(rq.getName()), createTestItemLeaf(parentTest, item)); + } + return item; + }).orElseGet(() -> { + Maybe item = launch.startTestItem(rq); + if (getReporter().getParameters().isCallbackReportingEnabled()) { + TEST_ITEM_TREE.getTestItems().put(createItemTreeKey(rq.getName()), createTestItemLeaf(item)); + } + return item; + }); if (TEMPLATE == itemType) { testTemplates.put(c, itemId); } @@ -514,12 +497,10 @@ protected void startTestItem(@Nonnull final ExtensionContext context, @Nonnull f * @param itemType a method's item type (to display on RP) * @return an ID of the method */ - protected Maybe startBeforeAfter(Method method, ExtensionContext parentContext, ExtensionContext context, - ItemType itemType) { + protected Maybe startBeforeAfter(Method method, ExtensionContext parentContext, ExtensionContext context, ItemType itemType) { Launch launch = getLaunch(context); StartTestItemRQ rq = buildStartConfigurationRq(method, parentContext, context, itemType); - return getItemId(parentContext).map(pid -> launch.startTestItem(pid, rq)) - .orElseGet(() -> launch.startTestItem(rq)); + return getItemId(parentContext).map(pid -> launch.startTestItem(pid, rq)).orElseGet(() -> launch.startTestItem(rq)); } /** @@ -575,8 +556,8 @@ protected void finishTestItem(@Nonnull final ExtensionContext context, @Nonnull Maybe id = idMapping.remove(context); Maybe finishResponse = launch.finishTestItem(id, rq); if (getReporter().getParameters().isCallbackReportingEnabled()) { - ofNullable(TEST_ITEM_TREE.getTestItems() - .get(createItemTreeKey(context))).ifPresent(itemLeaf -> itemLeaf.setFinishResponse(finishResponse)); + ofNullable(TEST_ITEM_TREE.getTestItems().get(createItemTreeKey(context))).ifPresent(itemLeaf -> itemLeaf.setFinishResponse( + finishResponse)); } } @@ -638,8 +619,7 @@ protected String getCodeRef(@Nonnull final ExtensionContext context) { * @return an {@link Optional} of a {@link Method} */ protected Optional getTestMethod(ExtensionContext context) { - return ofNullable(context.getTestMethod() - .orElseGet(() -> context.getParent().flatMap(this::getTestMethod).orElse(null))); + return ofNullable(context.getTestMethod().orElseGet(() -> context.getParent().flatMap(this::getTestMethod).orElse(null))); } /** @@ -660,24 +640,74 @@ protected Optional getTestMethod(ExtensionContext context) { * @param arguments a list of parameter values * @return a list of parameters */ - protected @Nonnull List getParameters(@Nonnull final Method method, - final List arguments) { + protected @Nonnull List getParameters(@Nonnull final Method method, final List arguments) { return ParameterUtils.getParameters(method, arguments); } + private Optional getOptionalTestMethod(ExtensionContext context) { + Optional optionalMethod = context.getTestMethod(); + if (!optionalMethod.isPresent()) { + //if not present means that we are in the dynamic test, in this case we need to move to the parent context + Optional parentContext = context.getParent(); + if (!parentContext.isPresent()) { + return Optional.empty(); + } + return parentContext.get().getTestMethod(); + } + return optionalMethod; + } + + private String getMethodName(String value) { + return value.length() > 1024 ? value.substring(0, 1021) + "..." : value; + } + + /** + * Extension point to customize test step name + * + * @param context JUnit's test context + * @param itemType a test method item type + * @return Test/Step Name being sent to ReportPortal + */ + protected String createStepName(ExtensionContext context, ItemType itemType) { + String name = context.getDisplayName(); + String defaultValue = getMethodName(name); + + if (itemType != STEP) { + return defaultValue; + } + + Optional optionalMethod = getOptionalTestMethod(context); + if (!optionalMethod.isPresent()) { + return defaultValue; + } + Method method = optionalMethod.get(); + + com.epam.reportportal.annotations.DisplayName displayNameFromMethod = method.getAnnotation(com.epam.reportportal.annotations.DisplayName.class); + if (displayNameFromMethod != null) { + return getMethodName(displayNameFromMethod.value()); + } + + com.epam.reportportal.annotations.DisplayName displayNameFromClass = method.getDeclaringClass() + .getAnnotation(com.epam.reportportal.annotations.DisplayName.class); + if (displayNameFromClass != null) { + return getMethodName(displayNameFromClass.value()); + } + + return defaultValue; + } + /** * Extension point to customize test step creation event/request * - * @param context JUnit's test context - * @param arguments a test arguments list - * @param itemType a test method item type - * @param startTime a start time of the test + * @param context JUnit's test context + * @param arguments a test arguments list + * @param itemType a test method item type + * @param startTime a start time of the test * @return Request to ReportPortal */ @Nonnull - protected StartTestItemRQ buildStartStepRq(@Nonnull final ExtensionContext context, - @Nonnull final List arguments, @Nonnull final ItemType itemType, @Nullable final String description, - @Nullable final Date startTime) { + protected StartTestItemRQ buildStartStepRq(@Nonnull final ExtensionContext context, @Nonnull final List arguments, + @Nonnull final ItemType itemType, @Nullable final String description, @Nullable final Date startTime) { StartTestItemRQ rq = new StartTestItemRQ(); rq.setStartTime(ofNullable(startTime).orElseGet(Calendar.getInstance()::getTime)); rq.setName(createStepName(context, itemType)); @@ -685,10 +715,7 @@ protected StartTestItemRQ buildStartStepRq(@Nonnull final ExtensionContext conte rq.setType(itemType == TEMPLATE ? SUITE.name() : itemType.name()); String codeRef = getCodeRef(context); rq.setCodeRef(codeRef); - rq.setAttributes(context.getTags() - .stream() - .map(it -> new ItemAttributesRQ(null, it)) - .collect(Collectors.toSet())); + rq.setAttributes(context.getTags().stream().map(it -> new ItemAttributesRQ(null, it)).collect(Collectors.toSet())); if (SUITE == itemType) { context.getTestClass().ifPresent(c -> rq.getAttributes().addAll(getAttributes(c))); } @@ -699,6 +726,9 @@ protected StartTestItemRQ buildStartStepRq(@Nonnull final ExtensionContext conte rq.setParameters(getParameters(m, arguments)); return getTestCaseId(m, codeRef, arguments, context.getTestInstance().orElse(null)); }).orElseGet(() -> TestCaseIdUtils.getTestCaseId(codeRef, arguments)); + if (STEP == itemType) { + testParameters.put(context, rq.getParameters()); + } rq.setTestCaseId(ofNullable(caseId).map(TestCaseIdEntry::getId).orElse(null)); return rq; } @@ -770,11 +800,23 @@ protected FinishTestItemRQ buildFinishTestRq(@Nonnull ExtensionContext context, stackTrace; rq.setDescription(description); } + rq.setIssue(getIssue(context)); ofNullable(status).ifPresent(s -> rq.setStatus(s.name())); rq.setEndTime(Calendar.getInstance().getTime()); return rq; } + @Nullable + protected com.epam.ta.reportportal.ws.model.issue.Issue getIssue(@Nonnull ExtensionContext context) { + String stepName = createStepName(context, STEP); + List parameters = testParameters.containsKey(context) ? testParameters.remove(context) : Collections.emptyList(); + return getOptionalTestMethod(context).map(m -> ofNullable(m.getAnnotation(Issues.class)).map(i -> IssueUtils.createIssue(i, + stepName, + parameters + )).orElseGet(() -> IssueUtils.createIssue(m.getAnnotation(Issue.class), stepName, parameters))) + .orElse(null); + } + /** * Extension point to customize a test item result on it's finish * @@ -791,44 +833,6 @@ protected FinishTestItemRQ buildFinishTestItemRq(@Nonnull ExtensionContext conte return rq; } - /** - * Extension point to customize test step name - * - * @param context JUnit's test context - * @param itemType a test method item type - * @return Test/Step Name being sent to ReportPortal - */ - protected String createStepName(ExtensionContext context, ItemType itemType) { - String name = context.getDisplayName(); - String defaultValue = getMethodName(name); - - if (itemType != STEP) { - return defaultValue; - } - - Optional optionalMethod = getOptionalTestMethod(context); - if (!optionalMethod.isPresent()) { - return defaultValue; - } - Method method = optionalMethod.get(); - - com.epam.reportportal.annotations.DisplayName displayNameFromMethod = method.getAnnotation(com.epam.reportportal.annotations.DisplayName.class); - if (displayNameFromMethod != null) { - return getMethodName(displayNameFromMethod.value()); - } - - com.epam.reportportal.annotations.DisplayName displayNameFromClass = method.getDeclaringClass().getAnnotation(com.epam.reportportal.annotations.DisplayName.class); - if (displayNameFromClass != null) { - return getMethodName(displayNameFromClass.value()); - } - - return defaultValue; - } - - private String getMethodName(String value) { - return value.length() > 1024 ? value.substring(0, 1021) + "..." : value; - } - /** * Extension point to customize beforeXXX step name * @@ -871,37 +875,24 @@ protected String createStepDescription(ExtensionContext context, final ItemType return defaultValue; } Optional optionalMethod = getOptionalTestMethod(context); - if (!optionalMethod.isPresent()){ + if (!optionalMethod.isPresent()) { return defaultValue; } Method method = optionalMethod.get(); Description descriptionFromMethod = method.getAnnotation(Description.class); - if(descriptionFromMethod != null){ + if (descriptionFromMethod != null) { return descriptionFromMethod.value(); } Description descriptionFromClass = method.getDeclaringClass().getAnnotation(Description.class); - if(descriptionFromClass != null){ + if (descriptionFromClass != null) { return descriptionFromClass.value(); } return defaultValue; } - private Optional getOptionalTestMethod(ExtensionContext context){ - Optional optionalMethod = context.getTestMethod(); - if(!optionalMethod.isPresent()){ - //if not present means that we are in the dynamic test, in this case we need to move to the parent context - Optional parentContext = context.getParent(); - if(!parentContext.isPresent()){ - return Optional.empty(); - } - return parentContext.get().getTestMethod(); - } - return optionalMethod; - } - /** * Extension point to customize beforeXXX step description * @@ -922,8 +913,8 @@ protected String createConfigurationDescription(Class testClass, Method metho * @param throwable An exception which caused the skip * @param eventTime @BeforeEach start time */ - protected void reportSkippedStep(ReflectiveInvocationContext invocationContext, ExtensionContext context, - Throwable throwable, Date eventTime) { + protected void reportSkippedStep(ReflectiveInvocationContext invocationContext, ExtensionContext context, Throwable throwable, + Date eventTime) { Date skipStartTime = Calendar.getInstance().getTime(); if (skipStartTime.after(eventTime)) { // to fix item ordering when @AfterEach starts in the same millisecond as skipped test @@ -945,8 +936,8 @@ protected void reportSkippedStep(ReflectiveInvocationContext invocationC * @param eventTime @BeforeAll start time */ @SuppressWarnings("unused") - protected void reportSkippedClassTests(ReflectiveInvocationContext invocationContext, - ExtensionContext context, Date eventTime) { + protected void reportSkippedClassTests(ReflectiveInvocationContext invocationContext, ExtensionContext context, + Date eventTime) { } /** From c6c6ea7556da59e50c195c4bdbee0da10b0c6b23 Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Tue, 5 Nov 2024 17:39:30 +0300 Subject: [PATCH 11/16] Add the first Issue annotation test --- .../epam/reportportal/junit5/BasicTest.java | 2 +- .../junit5/IssueReportingTest.java | 83 +++++++++++++++++++ .../features/{basic => }/TestFailure.java | 6 +- .../features/issue/DynamicIssueTest.java | 24 ++++++ .../issue/ParameterizedWithOneIssueTest.java | 38 +++++++++ .../issue/ParameterizedWithTwoIssueTest.java | 39 +++++++++ .../features/issue/SimpleIssueTest.java | 34 ++++++++ .../features/issue/SimpleTwoIssuesTest.java | 34 ++++++++ .../features/issue/TwoDynamicIssueTest.java | 26 ++++++ .../issue/TwoDynamicTwoIssueTest.java | 29 +++++++ 10 files changed, 311 insertions(+), 4 deletions(-) create mode 100644 src/test/java/com/epam/reportportal/junit5/IssueReportingTest.java rename src/test/java/com/epam/reportportal/junit5/features/{basic => }/TestFailure.java (87%) create mode 100644 src/test/java/com/epam/reportportal/junit5/features/issue/DynamicIssueTest.java create mode 100644 src/test/java/com/epam/reportportal/junit5/features/issue/ParameterizedWithOneIssueTest.java create mode 100644 src/test/java/com/epam/reportportal/junit5/features/issue/ParameterizedWithTwoIssueTest.java create mode 100644 src/test/java/com/epam/reportportal/junit5/features/issue/SimpleIssueTest.java create mode 100644 src/test/java/com/epam/reportportal/junit5/features/issue/SimpleTwoIssuesTest.java create mode 100644 src/test/java/com/epam/reportportal/junit5/features/issue/TwoDynamicIssueTest.java create mode 100644 src/test/java/com/epam/reportportal/junit5/features/issue/TwoDynamicTwoIssueTest.java diff --git a/src/test/java/com/epam/reportportal/junit5/BasicTest.java b/src/test/java/com/epam/reportportal/junit5/BasicTest.java index b201217..a803465 100644 --- a/src/test/java/com/epam/reportportal/junit5/BasicTest.java +++ b/src/test/java/com/epam/reportportal/junit5/BasicTest.java @@ -16,7 +16,7 @@ package com.epam.reportportal.junit5; -import com.epam.reportportal.junit5.features.basic.TestFailure; +import com.epam.reportportal.junit5.features.TestFailure; import com.epam.reportportal.junit5.util.TestUtils; import com.epam.reportportal.listeners.ItemStatus; import com.epam.reportportal.service.Launch; diff --git a/src/test/java/com/epam/reportportal/junit5/IssueReportingTest.java b/src/test/java/com/epam/reportportal/junit5/IssueReportingTest.java new file mode 100644 index 0000000..9412a79 --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/IssueReportingTest.java @@ -0,0 +1,83 @@ +/* + * 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.junit5; + +import com.epam.reportportal.junit5.features.issue.SimpleIssueTest; +import com.epam.reportportal.junit5.util.TestUtils; +import com.epam.reportportal.listeners.ItemStatus; +import com.epam.reportportal.service.Launch; +import com.epam.reportportal.util.test.CommonUtils; +import com.epam.ta.reportportal.ws.model.FinishTestItemRQ; +import com.epam.ta.reportportal.ws.model.OperationCompletionRS; +import com.epam.ta.reportportal.ws.model.issue.Issue; +import io.reactivex.Maybe; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.mockito.ArgumentCaptor; +import org.mockito.stubbing.Answer; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.notNullValue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public class IssueReportingTest { + public static class TestExtension extends ReportPortalExtension { + static Launch LAUNCH; + + @Override + protected Launch getLaunch(ExtensionContext context) { + return LAUNCH; + } + } + + private final String SUITE_ID = CommonUtils.namedId("suite_"); + private final Maybe SUITE_MAYBE = Maybe.just(SUITE_ID); + private final String STEP_ID = CommonUtils.namedId("step_"); + private final Maybe STEP_MAYBE = Maybe.just(STEP_ID); + + @BeforeEach + public void setupMock() { + Launch launch = mock(Launch.class); + IssueReportingTest.TestExtension.LAUNCH = launch; + when(launch.startTestItem(any())).thenAnswer((Answer>) invocation -> SUITE_MAYBE); + when(launch.startTestItem(same(SUITE_MAYBE), any())).thenAnswer((Answer>) invocation -> STEP_MAYBE); + when(launch.finishTestItem(any(), + any() + )).thenAnswer((Answer>) invocation -> Maybe.just(new OperationCompletionRS("OK"))); + } + + @Test + public void verify_simple_test_failure() { + TestUtils.runClasses(SimpleIssueTest.class); + + Launch launch = IssueReportingTest.TestExtension.LAUNCH; + ArgumentCaptor testCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); + verify(launch).finishTestItem(same(STEP_MAYBE), testCaptor.capture()); + + FinishTestItemRQ finishTestItemRQ = testCaptor.getValue(); + assertThat(finishTestItemRQ.getStatus(), equalTo(ItemStatus.FAILED.name())); + assertThat(finishTestItemRQ.getIssue(), notNullValue()); + Issue issue = finishTestItemRQ.getIssue(); + assertThat(issue.getIssueType(), equalTo("pb001")); + assertThat(issue.getComment(), equalTo(SimpleIssueTest.FAILURE_MESSAGE)); + } +} diff --git a/src/test/java/com/epam/reportportal/junit5/features/basic/TestFailure.java b/src/test/java/com/epam/reportportal/junit5/features/TestFailure.java similarity index 87% rename from src/test/java/com/epam/reportportal/junit5/features/basic/TestFailure.java rename to src/test/java/com/epam/reportportal/junit5/features/TestFailure.java index 159ba85..31159aa 100644 --- a/src/test/java/com/epam/reportportal/junit5/features/basic/TestFailure.java +++ b/src/test/java/com/epam/reportportal/junit5/features/TestFailure.java @@ -1,11 +1,11 @@ /* - * Copyright 2022 EPAM Systems + * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.epam.reportportal.junit5.features.basic; +package com.epam.reportportal.junit5.features; import com.epam.reportportal.junit5.BasicTest; import org.junit.jupiter.api.Assertions; diff --git a/src/test/java/com/epam/reportportal/junit5/features/issue/DynamicIssueTest.java b/src/test/java/com/epam/reportportal/junit5/features/issue/DynamicIssueTest.java new file mode 100644 index 0000000..1ba9688 --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/features/issue/DynamicIssueTest.java @@ -0,0 +1,24 @@ +package com.epam.reportportal.junit5.features.issue; + +import com.epam.reportportal.annotations.Issue; +import com.epam.reportportal.junit5.DisplayNameTest; +import org.junit.jupiter.api.DynamicTest; +import org.junit.jupiter.api.TestFactory; +import org.junit.jupiter.api.extension.ExtendWith; + +import java.util.stream.Stream; + +import static org.junit.jupiter.api.DynamicTest.dynamicTest; + +@ExtendWith(DisplayNameTest.TestExtension.class) +public class DynamicIssueTest { + public static final String FAILURE_MESSAGE = "This test is expected to fail"; + + @TestFactory + @Issue(value = "ab001", comment = FAILURE_MESSAGE) + Stream testForTestFactory() { + return Stream.of(dynamicTest("My dynamic test", () -> { + throw new IllegalStateException(FAILURE_MESSAGE); + })); + } +} diff --git a/src/test/java/com/epam/reportportal/junit5/features/issue/ParameterizedWithOneIssueTest.java b/src/test/java/com/epam/reportportal/junit5/features/issue/ParameterizedWithOneIssueTest.java new file mode 100644 index 0000000..e345dac --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/features/issue/ParameterizedWithOneIssueTest.java @@ -0,0 +1,38 @@ +/* + * 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.junit5.features.issue; + +import com.epam.reportportal.annotations.Issue; +import com.epam.reportportal.annotations.TestFilter; +import com.epam.reportportal.annotations.TestParamFilter; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +@ExtendWith(com.epam.reportportal.junit5.ReportPortalExtension.class) +public class ParameterizedWithOneIssueTest { + + public static final String FAILURE_MESSAGE = "This parameterized test is expected to fail: "; + + @ParameterizedTest + @ValueSource(booleans = { true, false }) + @Issue(value = "ab001", comment = "This test is expected to fail", filter = @TestFilter(param = { + @TestParamFilter(valueStartsWith = "true") })) + public void failureTest(boolean param) { + throw new IllegalStateException(FAILURE_MESSAGE + param); + } +} diff --git a/src/test/java/com/epam/reportportal/junit5/features/issue/ParameterizedWithTwoIssueTest.java b/src/test/java/com/epam/reportportal/junit5/features/issue/ParameterizedWithTwoIssueTest.java new file mode 100644 index 0000000..c368b8e --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/features/issue/ParameterizedWithTwoIssueTest.java @@ -0,0 +1,39 @@ +/* + * 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.junit5.features.issue; + +import com.epam.reportportal.annotations.Issue; +import com.epam.reportportal.annotations.TestFilter; +import com.epam.reportportal.annotations.TestParamFilter; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +@ExtendWith(com.epam.reportportal.junit5.ReportPortalExtension.class) +public class ParameterizedWithTwoIssueTest { + + public static final String FAILURE_MESSAGE = "This parameterized test is expected to fail: "; + public static final String ISSUE_MESSAGE = "This test is expected to fail"; + + @ParameterizedTest + @ValueSource(booleans = { true, false }) + @Issue(value = "ab001", comment = ISSUE_MESSAGE, filter = @TestFilter(param = { @TestParamFilter(valueStartsWith = "true") })) + @Issue(value = "pb001", comment = ISSUE_MESSAGE, filter = @TestFilter(param = { @TestParamFilter(valueStartsWith = "false") })) + public void failureTest(boolean param) { + throw new IllegalStateException(FAILURE_MESSAGE + param); + } +} diff --git a/src/test/java/com/epam/reportportal/junit5/features/issue/SimpleIssueTest.java b/src/test/java/com/epam/reportportal/junit5/features/issue/SimpleIssueTest.java new file mode 100644 index 0000000..6b754be --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/features/issue/SimpleIssueTest.java @@ -0,0 +1,34 @@ +/* + * 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.junit5.features.issue; + +import com.epam.reportportal.annotations.Issue; +import com.epam.reportportal.junit5.IssueReportingTest; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +@ExtendWith(IssueReportingTest.TestExtension.class) +public class SimpleIssueTest { + + public static final String FAILURE_MESSAGE = "This test is expected to fail"; + + @Test + @Issue(value = "pb001", comment = FAILURE_MESSAGE) + public void failureTest() { + throw new IllegalStateException(FAILURE_MESSAGE); + } +} diff --git a/src/test/java/com/epam/reportportal/junit5/features/issue/SimpleTwoIssuesTest.java b/src/test/java/com/epam/reportportal/junit5/features/issue/SimpleTwoIssuesTest.java new file mode 100644 index 0000000..1714ed1 --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/features/issue/SimpleTwoIssuesTest.java @@ -0,0 +1,34 @@ +/* + * 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.junit5.features.issue; + +import com.epam.reportportal.annotations.Issue; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +@ExtendWith(com.epam.reportportal.junit5.ReportPortalExtension.class) +public class SimpleTwoIssuesTest { + + public static final String FAILURE_MESSAGE = "This test is expected to fail"; + + @Test + @Issue(value = "pb001", comment = FAILURE_MESSAGE) + @Issue(value = "ab001", comment = FAILURE_MESSAGE) + public void failureTest() { + throw new IllegalStateException(FAILURE_MESSAGE); + } +} diff --git a/src/test/java/com/epam/reportportal/junit5/features/issue/TwoDynamicIssueTest.java b/src/test/java/com/epam/reportportal/junit5/features/issue/TwoDynamicIssueTest.java new file mode 100644 index 0000000..e9322a7 --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/features/issue/TwoDynamicIssueTest.java @@ -0,0 +1,26 @@ +package com.epam.reportportal.junit5.features.issue; + +import com.epam.reportportal.annotations.Issue; +import com.epam.reportportal.junit5.DisplayNameTest; +import org.junit.jupiter.api.DynamicTest; +import org.junit.jupiter.api.TestFactory; +import org.junit.jupiter.api.extension.ExtendWith; + +import java.util.stream.Stream; + +import static org.junit.jupiter.api.DynamicTest.dynamicTest; + +@ExtendWith(DisplayNameTest.TestExtension.class) +public class TwoDynamicIssueTest { + public static final String FAILURE_MESSAGE = "This test is expected to fail"; + + @TestFactory + @Issue(value = "ab001", comment = FAILURE_MESSAGE) + Stream testForTestFactory() { + return Stream.of(dynamicTest("My dynamic test", () -> { + throw new IllegalStateException(FAILURE_MESSAGE); + }), dynamicTest("My dynamic test 2", () -> { + throw new IllegalStateException(FAILURE_MESSAGE); + })); + } +} diff --git a/src/test/java/com/epam/reportportal/junit5/features/issue/TwoDynamicTwoIssueTest.java b/src/test/java/com/epam/reportportal/junit5/features/issue/TwoDynamicTwoIssueTest.java new file mode 100644 index 0000000..8667c0b --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/features/issue/TwoDynamicTwoIssueTest.java @@ -0,0 +1,29 @@ +package com.epam.reportportal.junit5.features.issue; + +import com.epam.reportportal.annotations.Issue; +import com.epam.reportportal.annotations.TestFilter; +import com.epam.reportportal.annotations.TestNameFilter; +import com.epam.reportportal.junit5.DisplayNameTest; +import org.junit.jupiter.api.DynamicTest; +import org.junit.jupiter.api.TestFactory; +import org.junit.jupiter.api.extension.ExtendWith; + +import java.util.stream.Stream; + +import static org.junit.jupiter.api.DynamicTest.dynamicTest; + +@ExtendWith(DisplayNameTest.TestExtension.class) +public class TwoDynamicTwoIssueTest { + public static final String FAILURE_MESSAGE = "This test is expected to fail"; + + @TestFactory + @Issue(value = "ab001", comment = FAILURE_MESSAGE, filter = {@TestFilter(name = @TestNameFilter(endsWith = "test")) }) + @Issue(value = "pb001", comment = FAILURE_MESSAGE, filter = {@TestFilter(name = @TestNameFilter(contains = "test 2")) }) + Stream testForTestFactory() { + return Stream.of(dynamicTest("My dynamic test", () -> { + throw new IllegalStateException(FAILURE_MESSAGE); + }), dynamicTest("My dynamic test 2", () -> { + throw new IllegalStateException(FAILURE_MESSAGE); + })); + } +} From ca6c8aa952f2897bf9127844a8bd498b34e9a764 Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Wed, 6 Nov 2024 15:03:56 +0300 Subject: [PATCH 12/16] Add more `@Issue` annotation tests --- .../junit5/ReportPortalExtension.java | 27 +-- .../junit5/IssueReportingTest.java | 161 ++++++++++++++++-- .../features/issue/DynamicIssueTest.java | 4 +- .../issue/ParameterizedWithOneIssueTest.java | 7 +- .../issue/ParameterizedWithTwoIssueTest.java | 3 +- .../features/issue/SimpleTwoIssuesTest.java | 5 +- .../features/issue/TwoDynamicIssueTest.java | 4 +- .../issue/TwoDynamicTwoIssueTest.java | 8 +- 8 files changed, 181 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java b/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java index 7177fa7..357343f 100644 --- a/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java +++ b/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java @@ -468,19 +468,20 @@ protected void startTestItem(@Nonnull final ExtensionContext context, @Nonnull f idMapping.computeIfAbsent(context, c -> { StartTestItemRQ rq = buildStartStepRq(c, arguments, itemType, description, startTime); Launch launch = getLaunch(c); - Maybe itemId = c.getParent().flatMap(parent -> Optional.ofNullable(idMapping.get(parent))).map(parentTest -> { - Maybe item = launch.startTestItem(parentTest, rq); - if (getReporter().getParameters().isCallbackReportingEnabled()) { - TEST_ITEM_TREE.getTestItems().put(createItemTreeKey(rq.getName()), createTestItemLeaf(parentTest, item)); - } - return item; - }).orElseGet(() -> { - Maybe item = launch.startTestItem(rq); - if (getReporter().getParameters().isCallbackReportingEnabled()) { - TEST_ITEM_TREE.getTestItems().put(createItemTreeKey(rq.getName()), createTestItemLeaf(item)); - } - return item; - }); + + Maybe parentId = c.getParent().flatMap(parent -> Optional.ofNullable(idMapping.get(parent))).orElse(null); + Maybe itemId; + TestItemTree.TestItemLeaf leaf; + if (parentId == null) { + itemId = launch.startTestItem(rq); + leaf = createTestItemLeaf(itemId); + } else { + itemId = launch.startTestItem(parentId, rq); + leaf = createTestItemLeaf(parentId, itemId); + } + if (getReporter().getParameters().isCallbackReportingEnabled()) { + TEST_ITEM_TREE.getTestItems().put(createItemTreeKey(rq.getName()), leaf); + } if (TEMPLATE == itemType) { testTemplates.put(c, itemId); } diff --git a/src/test/java/com/epam/reportportal/junit5/IssueReportingTest.java b/src/test/java/com/epam/reportportal/junit5/IssueReportingTest.java index 9412a79..e8c5e14 100644 --- a/src/test/java/com/epam/reportportal/junit5/IssueReportingTest.java +++ b/src/test/java/com/epam/reportportal/junit5/IssueReportingTest.java @@ -16,7 +16,7 @@ package com.epam.reportportal.junit5; -import com.epam.reportportal.junit5.features.issue.SimpleIssueTest; +import com.epam.reportportal.junit5.features.issue.*; import com.epam.reportportal.junit5.util.TestUtils; import com.epam.reportportal.listeners.ItemStatus; import com.epam.reportportal.service.Launch; @@ -32,13 +32,16 @@ import org.mockito.ArgumentCaptor; import org.mockito.stubbing.Answer; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.Queue; + import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.*; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; -@TestInstance(TestInstance.Lifecycle.PER_CLASS) +@TestInstance(TestInstance.Lifecycle.PER_METHOD) public class IssueReportingTest { public static class TestExtension extends ReportPortalExtension { static Launch LAUNCH; @@ -49,17 +52,24 @@ protected Launch getLaunch(ExtensionContext context) { } } - private final String SUITE_ID = CommonUtils.namedId("suite_"); - private final Maybe SUITE_MAYBE = Maybe.just(SUITE_ID); - private final String STEP_ID = CommonUtils.namedId("step_"); - private final Maybe STEP_MAYBE = Maybe.just(STEP_ID); + private final String suiteId = CommonUtils.namedId("suite_"); + private final Maybe suiteMaybe = Maybe.just(suiteId); + private final String stepOneId = CommonUtils.namedId("step_"); + private final Maybe stepOneMaybe = Maybe.just(stepOneId); + private final String stepTwoId = CommonUtils.namedId("step_"); + private final Maybe stepTwoMaybe = Maybe.just(stepTwoId); + private final String stepThreeId = CommonUtils.namedId("step_"); + private final Maybe stepThreeMaybe = Maybe.just(stepThreeId); + private final Queue> stepIds = new LinkedList<>(Arrays.asList(stepOneMaybe, stepTwoMaybe, stepThreeMaybe)); @BeforeEach public void setupMock() { Launch launch = mock(Launch.class); IssueReportingTest.TestExtension.LAUNCH = launch; - when(launch.startTestItem(any())).thenAnswer((Answer>) invocation -> SUITE_MAYBE); - when(launch.startTestItem(same(SUITE_MAYBE), any())).thenAnswer((Answer>) invocation -> STEP_MAYBE); + when(launch.startTestItem(any())).thenAnswer((Answer>) invocation -> suiteMaybe); + when(launch.startTestItem(any(), any())).thenAnswer((Answer>) invocation -> CommonUtils.createMaybeUuid()); + when(launch.startTestItem(same(suiteMaybe), any())).thenAnswer((Answer>) invocation -> stepIds.poll()); + when(launch.startTestItem(same(stepOneMaybe), any())).thenAnswer((Answer>) invocation -> stepIds.poll()); when(launch.finishTestItem(any(), any() )).thenAnswer((Answer>) invocation -> Maybe.just(new OperationCompletionRS("OK"))); @@ -71,7 +81,7 @@ public void verify_simple_test_failure() { Launch launch = IssueReportingTest.TestExtension.LAUNCH; ArgumentCaptor testCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); - verify(launch).finishTestItem(same(STEP_MAYBE), testCaptor.capture()); + verify(launch).finishTestItem(same(stepOneMaybe), testCaptor.capture()); FinishTestItemRQ finishTestItemRQ = testCaptor.getValue(); assertThat(finishTestItemRQ.getStatus(), equalTo(ItemStatus.FAILED.name())); @@ -80,4 +90,133 @@ public void verify_simple_test_failure() { assertThat(issue.getIssueType(), equalTo("pb001")); assertThat(issue.getComment(), equalTo(SimpleIssueTest.FAILURE_MESSAGE)); } + + @Test + public void verify_test_failure_with_two_issues() { + TestUtils.runClasses(SimpleTwoIssuesTest.class); + + Launch launch = IssueReportingTest.TestExtension.LAUNCH; + ArgumentCaptor testCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); + verify(launch).finishTestItem(same(stepOneMaybe), testCaptor.capture()); + + FinishTestItemRQ finishTestItemRQ = testCaptor.getValue(); + assertThat(finishTestItemRQ.getStatus(), equalTo(ItemStatus.FAILED.name())); + assertThat(finishTestItemRQ.getIssue(), notNullValue()); + Issue issue = finishTestItemRQ.getIssue(); + assertThat(issue.getIssueType(), equalTo("ab001")); + assertThat(issue.getComment(), equalTo(SimpleTwoIssuesTest.FAILURE_MESSAGE)); + } + + @Test + public void verify_parameterized_test_failure_with_one_issue() { + TestUtils.runClasses(ParameterizedWithOneIssueTest.class); + + Launch launch = IssueReportingTest.TestExtension.LAUNCH; + ArgumentCaptor firstTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); + verify(launch).finishTestItem(same(stepTwoMaybe), firstTestCaptor.capture()); + ArgumentCaptor secondTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); + verify(launch).finishTestItem(same(stepThreeMaybe), secondTestCaptor.capture()); + + FinishTestItemRQ finishTestItemRQ = firstTestCaptor.getValue(); + assertThat(finishTestItemRQ.getStatus(), equalTo(ItemStatus.FAILED.name())); + assertThat(finishTestItemRQ.getIssue(), nullValue()); + + finishTestItemRQ = secondTestCaptor.getValue(); + assertThat(finishTestItemRQ.getStatus(), equalTo(ItemStatus.FAILED.name())); + assertThat(finishTestItemRQ.getIssue(), notNullValue()); + Issue issue = finishTestItemRQ.getIssue(); + assertThat(issue.getIssueType(), equalTo("ab001")); + assertThat(issue.getComment(), equalTo(ParameterizedWithOneIssueTest.ISSUE_MESSAGE)); + } + + @Test + public void verify_parameterized_test_failure_with_two_issues() { + TestUtils.runClasses(ParameterizedWithTwoIssueTest.class); + + Launch launch = IssueReportingTest.TestExtension.LAUNCH; + ArgumentCaptor firstTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); + verify(launch).finishTestItem(same(stepTwoMaybe), firstTestCaptor.capture()); + ArgumentCaptor secondTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); + verify(launch).finishTestItem(same(stepThreeMaybe), secondTestCaptor.capture()); + + FinishTestItemRQ finishTestItemRQ = firstTestCaptor.getValue(); + assertThat(finishTestItemRQ.getStatus(), equalTo(ItemStatus.FAILED.name())); + assertThat(finishTestItemRQ.getIssue(), notNullValue()); + Issue issue = finishTestItemRQ.getIssue(); + assertThat(issue.getIssueType(), equalTo("ab001")); + assertThat(issue.getComment(), equalTo(ParameterizedWithTwoIssueTest.ISSUE_MESSAGE)); + + finishTestItemRQ = secondTestCaptor.getValue(); + assertThat(finishTestItemRQ.getStatus(), equalTo(ItemStatus.FAILED.name())); + assertThat(finishTestItemRQ.getIssue(), notNullValue()); + issue = finishTestItemRQ.getIssue(); + assertThat(issue.getIssueType(), equalTo("pb001")); + assertThat(issue.getComment(), equalTo(ParameterizedWithTwoIssueTest.ISSUE_MESSAGE)); + } + + @Test + public void verify_dynamic_test_failure() { + TestUtils.runClasses(DynamicIssueTest.class); + + Launch launch = IssueReportingTest.TestExtension.LAUNCH; + ArgumentCaptor testCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); + verify(launch).finishTestItem(same(stepTwoMaybe), testCaptor.capture()); + + FinishTestItemRQ finishTestItemRQ = testCaptor.getValue(); + assertThat(finishTestItemRQ.getStatus(), equalTo(ItemStatus.FAILED.name())); + assertThat(finishTestItemRQ.getIssue(), notNullValue()); + Issue issue = finishTestItemRQ.getIssue(); + assertThat(issue.getIssueType(), equalTo("ab001")); + assertThat(issue.getComment(), equalTo(DynamicIssueTest.FAILURE_MESSAGE)); + } + + @Test + public void verify_two_dynamic_test_failures() { + TestUtils.runClasses(TwoDynamicIssueTest.class); + + Launch launch = IssueReportingTest.TestExtension.LAUNCH; + ArgumentCaptor firstTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); + verify(launch).finishTestItem(same(stepTwoMaybe), firstTestCaptor.capture()); + ArgumentCaptor secondTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); + verify(launch).finishTestItem(same(stepThreeMaybe), secondTestCaptor.capture()); + + FinishTestItemRQ finishTestItemRQ = firstTestCaptor.getValue(); + assertThat(finishTestItemRQ.getStatus(), equalTo(ItemStatus.FAILED.name())); + assertThat(finishTestItemRQ.getIssue(), notNullValue()); + Issue issue = finishTestItemRQ.getIssue(); + assertThat(issue.getIssueType(), equalTo("ab001")); + assertThat(issue.getComment(), equalTo(TwoDynamicIssueTest.FAILURE_MESSAGE)); + + finishTestItemRQ = secondTestCaptor.getValue(); + assertThat(finishTestItemRQ.getStatus(), equalTo(ItemStatus.FAILED.name())); + assertThat(finishTestItemRQ.getIssue(), notNullValue()); + issue = finishTestItemRQ.getIssue(); + assertThat(issue.getIssueType(), equalTo("ab001")); + assertThat(issue.getComment(), equalTo(TwoDynamicIssueTest.FAILURE_MESSAGE)); + } + + @Test + public void verify_two_dynamic_test_failures_two_issues() { + TestUtils.runClasses(TwoDynamicTwoIssueTest.class); + + Launch launch = IssueReportingTest.TestExtension.LAUNCH; + ArgumentCaptor firstTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); + verify(launch).finishTestItem(same(stepTwoMaybe), firstTestCaptor.capture()); + ArgumentCaptor secondTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); + verify(launch).finishTestItem(same(stepThreeMaybe), secondTestCaptor.capture()); + + FinishTestItemRQ finishTestItemRQ = firstTestCaptor.getValue(); + assertThat(finishTestItemRQ.getStatus(), equalTo(ItemStatus.FAILED.name())); + assertThat(finishTestItemRQ.getIssue(), notNullValue()); + Issue issue = finishTestItemRQ.getIssue(); + assertThat(issue.getIssueType(), equalTo("ab001")); + assertThat(issue.getComment(), equalTo(TwoDynamicTwoIssueTest.FAILURE_MESSAGE)); + + finishTestItemRQ = secondTestCaptor.getValue(); + assertThat(finishTestItemRQ.getStatus(), equalTo(ItemStatus.FAILED.name())); + assertThat(finishTestItemRQ.getIssue(), notNullValue()); + issue = finishTestItemRQ.getIssue(); + assertThat(issue.getIssueType(), equalTo("pb001")); + assertThat(issue.getComment(), equalTo(TwoDynamicTwoIssueTest.FAILURE_MESSAGE)); + } } diff --git a/src/test/java/com/epam/reportportal/junit5/features/issue/DynamicIssueTest.java b/src/test/java/com/epam/reportportal/junit5/features/issue/DynamicIssueTest.java index 1ba9688..875cc43 100644 --- a/src/test/java/com/epam/reportportal/junit5/features/issue/DynamicIssueTest.java +++ b/src/test/java/com/epam/reportportal/junit5/features/issue/DynamicIssueTest.java @@ -1,7 +1,7 @@ package com.epam.reportportal.junit5.features.issue; import com.epam.reportportal.annotations.Issue; -import com.epam.reportportal.junit5.DisplayNameTest; +import com.epam.reportportal.junit5.IssueReportingTest; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.extension.ExtendWith; @@ -10,7 +10,7 @@ import static org.junit.jupiter.api.DynamicTest.dynamicTest; -@ExtendWith(DisplayNameTest.TestExtension.class) +@ExtendWith(IssueReportingTest.TestExtension.class) public class DynamicIssueTest { public static final String FAILURE_MESSAGE = "This test is expected to fail"; diff --git a/src/test/java/com/epam/reportportal/junit5/features/issue/ParameterizedWithOneIssueTest.java b/src/test/java/com/epam/reportportal/junit5/features/issue/ParameterizedWithOneIssueTest.java index e345dac..1010f5c 100644 --- a/src/test/java/com/epam/reportportal/junit5/features/issue/ParameterizedWithOneIssueTest.java +++ b/src/test/java/com/epam/reportportal/junit5/features/issue/ParameterizedWithOneIssueTest.java @@ -19,19 +19,20 @@ import com.epam.reportportal.annotations.Issue; import com.epam.reportportal.annotations.TestFilter; import com.epam.reportportal.annotations.TestParamFilter; +import com.epam.reportportal.junit5.IssueReportingTest; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -@ExtendWith(com.epam.reportportal.junit5.ReportPortalExtension.class) +@ExtendWith(IssueReportingTest.TestExtension.class) public class ParameterizedWithOneIssueTest { public static final String FAILURE_MESSAGE = "This parameterized test is expected to fail: "; + public static final String ISSUE_MESSAGE = "This test is expected to fail"; @ParameterizedTest @ValueSource(booleans = { true, false }) - @Issue(value = "ab001", comment = "This test is expected to fail", filter = @TestFilter(param = { - @TestParamFilter(valueStartsWith = "true") })) + @Issue(value = "ab001", comment = ISSUE_MESSAGE, filter = @TestFilter(param = { @TestParamFilter(valueStartsWith = "false") })) public void failureTest(boolean param) { throw new IllegalStateException(FAILURE_MESSAGE + param); } diff --git a/src/test/java/com/epam/reportportal/junit5/features/issue/ParameterizedWithTwoIssueTest.java b/src/test/java/com/epam/reportportal/junit5/features/issue/ParameterizedWithTwoIssueTest.java index c368b8e..4d156c4 100644 --- a/src/test/java/com/epam/reportportal/junit5/features/issue/ParameterizedWithTwoIssueTest.java +++ b/src/test/java/com/epam/reportportal/junit5/features/issue/ParameterizedWithTwoIssueTest.java @@ -19,11 +19,12 @@ import com.epam.reportportal.annotations.Issue; import com.epam.reportportal.annotations.TestFilter; import com.epam.reportportal.annotations.TestParamFilter; +import com.epam.reportportal.junit5.IssueReportingTest; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -@ExtendWith(com.epam.reportportal.junit5.ReportPortalExtension.class) +@ExtendWith(IssueReportingTest.TestExtension.class) public class ParameterizedWithTwoIssueTest { public static final String FAILURE_MESSAGE = "This parameterized test is expected to fail: "; diff --git a/src/test/java/com/epam/reportportal/junit5/features/issue/SimpleTwoIssuesTest.java b/src/test/java/com/epam/reportportal/junit5/features/issue/SimpleTwoIssuesTest.java index 1714ed1..562e2f8 100644 --- a/src/test/java/com/epam/reportportal/junit5/features/issue/SimpleTwoIssuesTest.java +++ b/src/test/java/com/epam/reportportal/junit5/features/issue/SimpleTwoIssuesTest.java @@ -17,17 +17,18 @@ package com.epam.reportportal.junit5.features.issue; import com.epam.reportportal.annotations.Issue; +import com.epam.reportportal.junit5.IssueReportingTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -@ExtendWith(com.epam.reportportal.junit5.ReportPortalExtension.class) +@ExtendWith(IssueReportingTest.TestExtension.class) public class SimpleTwoIssuesTest { public static final String FAILURE_MESSAGE = "This test is expected to fail"; @Test - @Issue(value = "pb001", comment = FAILURE_MESSAGE) @Issue(value = "ab001", comment = FAILURE_MESSAGE) + @Issue(value = "pb001", comment = FAILURE_MESSAGE) public void failureTest() { throw new IllegalStateException(FAILURE_MESSAGE); } diff --git a/src/test/java/com/epam/reportportal/junit5/features/issue/TwoDynamicIssueTest.java b/src/test/java/com/epam/reportportal/junit5/features/issue/TwoDynamicIssueTest.java index e9322a7..cda7051 100644 --- a/src/test/java/com/epam/reportportal/junit5/features/issue/TwoDynamicIssueTest.java +++ b/src/test/java/com/epam/reportportal/junit5/features/issue/TwoDynamicIssueTest.java @@ -1,7 +1,7 @@ package com.epam.reportportal.junit5.features.issue; import com.epam.reportportal.annotations.Issue; -import com.epam.reportportal.junit5.DisplayNameTest; +import com.epam.reportportal.junit5.IssueReportingTest; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.extension.ExtendWith; @@ -10,7 +10,7 @@ import static org.junit.jupiter.api.DynamicTest.dynamicTest; -@ExtendWith(DisplayNameTest.TestExtension.class) +@ExtendWith(IssueReportingTest.TestExtension.class) public class TwoDynamicIssueTest { public static final String FAILURE_MESSAGE = "This test is expected to fail"; diff --git a/src/test/java/com/epam/reportportal/junit5/features/issue/TwoDynamicTwoIssueTest.java b/src/test/java/com/epam/reportportal/junit5/features/issue/TwoDynamicTwoIssueTest.java index 8667c0b..442c6db 100644 --- a/src/test/java/com/epam/reportportal/junit5/features/issue/TwoDynamicTwoIssueTest.java +++ b/src/test/java/com/epam/reportportal/junit5/features/issue/TwoDynamicTwoIssueTest.java @@ -3,7 +3,7 @@ import com.epam.reportportal.annotations.Issue; import com.epam.reportportal.annotations.TestFilter; import com.epam.reportportal.annotations.TestNameFilter; -import com.epam.reportportal.junit5.DisplayNameTest; +import com.epam.reportportal.junit5.IssueReportingTest; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.extension.ExtendWith; @@ -12,13 +12,13 @@ import static org.junit.jupiter.api.DynamicTest.dynamicTest; -@ExtendWith(DisplayNameTest.TestExtension.class) +@ExtendWith(IssueReportingTest.TestExtension.class) public class TwoDynamicTwoIssueTest { public static final String FAILURE_MESSAGE = "This test is expected to fail"; @TestFactory - @Issue(value = "ab001", comment = FAILURE_MESSAGE, filter = {@TestFilter(name = @TestNameFilter(endsWith = "test")) }) - @Issue(value = "pb001", comment = FAILURE_MESSAGE, filter = {@TestFilter(name = @TestNameFilter(contains = "test 2")) }) + @Issue(value = "ab001", comment = FAILURE_MESSAGE, filter = { @TestFilter(name = @TestNameFilter(endsWith = "test")) }) + @Issue(value = "pb001", comment = FAILURE_MESSAGE, filter = { @TestFilter(name = @TestNameFilter(contains = "test 2")) }) Stream testForTestFactory() { return Stream.of(dynamicTest("My dynamic test", () -> { throw new IllegalStateException(FAILURE_MESSAGE); From dc65facc8aa3e86433d79e89f6d658bf13ccb95c Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Wed, 6 Nov 2024 15:40:59 +0300 Subject: [PATCH 13/16] Fix test --- .../junit5/features/step/ManualStepReporterFeatureTest.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/epam/reportportal/junit5/features/step/ManualStepReporterFeatureTest.java b/src/test/java/com/epam/reportportal/junit5/features/step/ManualStepReporterFeatureTest.java index 2539127..aaf2291 100644 --- a/src/test/java/com/epam/reportportal/junit5/features/step/ManualStepReporterFeatureTest.java +++ b/src/test/java/com/epam/reportportal/junit5/features/step/ManualStepReporterFeatureTest.java @@ -40,19 +40,22 @@ public class ManualStepReporterFeatureTest { private static final Logger LOGGER = LoggerFactory.getLogger(ManualStepReporterFeatureTest.class); @Test - public void manualStepTest() { + public void manualStepTest() throws InterruptedException { StepReporter stepReporter = Launch.currentLaunch().getStepReporter(); stepReporter.sendStep(FIRST_NAME); LOGGER.info("First info log of the first step"); LOGGER.info("Second info log of the first step"); + Thread.sleep(100); stepReporter.sendStep(SECOND_NAME); LOGGER.error("First error log of the second step"); + Thread.sleep(100); stepReporter.sendStep(ItemStatus.FAILED, THIRD_NAME, new File("pug/unlucky.jpg")); LOGGER.error("Second error log of the second step"); + Thread.sleep(100); stepReporter.finishPreviousStep(); LOGGER.error("Main test method error log"); From e0ed0e20d19d637fc86a302f24b8507c6b63f3d3 Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Wed, 6 Nov 2024 17:01:00 +0300 Subject: [PATCH 14/16] Add more `@Issue` annotation tests --- .../junit5/IssueReportingTest.java | 22 ++++++++++++ .../issue/SimpleSkippedIssueTest.java | 36 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 src/test/java/com/epam/reportportal/junit5/features/issue/SimpleSkippedIssueTest.java diff --git a/src/test/java/com/epam/reportportal/junit5/IssueReportingTest.java b/src/test/java/com/epam/reportportal/junit5/IssueReportingTest.java index e8c5e14..7547417 100644 --- a/src/test/java/com/epam/reportportal/junit5/IssueReportingTest.java +++ b/src/test/java/com/epam/reportportal/junit5/IssueReportingTest.java @@ -25,6 +25,7 @@ import com.epam.ta.reportportal.ws.model.OperationCompletionRS; import com.epam.ta.reportportal.ws.model.issue.Issue; import io.reactivex.Maybe; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; @@ -62,6 +63,11 @@ protected Launch getLaunch(ExtensionContext context) { private final Maybe stepThreeMaybe = Maybe.just(stepThreeId); private final Queue> stepIds = new LinkedList<>(Arrays.asList(stepOneMaybe, stepTwoMaybe, stepThreeMaybe)); + @BeforeAll + public static void setupProperty() { + System.setProperty("reportDisabledTests", Boolean.TRUE.toString()); + } + @BeforeEach public void setupMock() { Launch launch = mock(Launch.class); @@ -219,4 +225,20 @@ public void verify_two_dynamic_test_failures_two_issues() { assertThat(issue.getIssueType(), equalTo("pb001")); assertThat(issue.getComment(), equalTo(TwoDynamicTwoIssueTest.FAILURE_MESSAGE)); } + + @Test + public void verify_simple_test_skip() { + TestUtils.runClasses(SimpleSkippedIssueTest.class); + + Launch launch = IssueReportingTest.TestExtension.LAUNCH; + ArgumentCaptor testCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); + verify(launch).finishTestItem(same(stepOneMaybe), testCaptor.capture()); + + FinishTestItemRQ finishTestItemRQ = testCaptor.getValue(); + assertThat(finishTestItemRQ.getStatus(), equalTo(ItemStatus.SKIPPED.name())); + assertThat(finishTestItemRQ.getIssue(), notNullValue()); + Issue issue = finishTestItemRQ.getIssue(); + assertThat(issue.getIssueType(), equalTo("pb001")); + assertThat(issue.getComment(), equalTo(SimpleSkippedIssueTest.FAILURE_MESSAGE)); + } } diff --git a/src/test/java/com/epam/reportportal/junit5/features/issue/SimpleSkippedIssueTest.java b/src/test/java/com/epam/reportportal/junit5/features/issue/SimpleSkippedIssueTest.java new file mode 100644 index 0000000..c82655d --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/features/issue/SimpleSkippedIssueTest.java @@ -0,0 +1,36 @@ +/* + * 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.junit5.features.issue; + +import com.epam.reportportal.annotations.Issue; +import com.epam.reportportal.junit5.IssueReportingTest; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +@ExtendWith(IssueReportingTest.TestExtension.class) +public class SimpleSkippedIssueTest { + + public static final String FAILURE_MESSAGE = "This test is expected to fail"; + + @Test + @Issue(value = "pb001", comment = FAILURE_MESSAGE) + @Disabled + public void failureTest() { + throw new IllegalStateException(FAILURE_MESSAGE); + } +} From f9bf1cb34cc94802ab904afcc987ebafdd5bb6a2 Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Fri, 8 Nov 2024 17:31:20 +0300 Subject: [PATCH 15/16] Client version update --- CHANGELOG.md | 2 +- build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3784240..82b20a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ - Common Stack Trace frames skip in description and logs, by @HardNorth - `@Issue` and `@Issues` annotations support, by @HardNorth ### Changed -- Client version updated on [5.2.19](https://github.com/reportportal/client-java/releases/tag/5.2.19), by @HardNorth +- Client version updated on [5.2.20](https://github.com/reportportal/client-java/releases/tag/5.2.20), by @HardNorth ## [5.3.3] ### Added diff --git a/build.gradle b/build.gradle index 29574bb..eb9ff15 100644 --- a/build.gradle +++ b/build.gradle @@ -37,7 +37,7 @@ repositories { } dependencies { - api 'com.epam.reportportal:client-java:5.2.19' + api 'com.epam.reportportal:client-java:5.2.20' compileOnly "org.junit.jupiter:junit-jupiter-api:${junit_version}" implementation 'org.slf4j:slf4j-api:2.0.7' From 6b3ab3b4a21dc54c50683b8ee912ebf6b541b7bf Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Fri, 8 Nov 2024 17:37:00 +0300 Subject: [PATCH 16/16] Fix javadocs --- .../junit5/ReportPortalExtension.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java b/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java index 357343f..a308e1d 100644 --- a/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java +++ b/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java @@ -459,9 +459,11 @@ protected void startTestItem(ExtensionContext context, List arguments, I /** * Starts a test item of arbitrary type * - * @param context JUnit's test context - * @param arguments a list of test parameters - * @param itemType a type of the item + * @param context JUnit's test context + * @param arguments a list of test parameters + * @param itemType a type of the item + * @param description a description of the item + * @param startTime a start time of the item */ protected void startTestItem(@Nonnull final ExtensionContext context, @Nonnull final List arguments, @Nonnull final ItemType itemType, @Nullable final String description, @Nullable final Date startTime) { @@ -700,10 +702,11 @@ protected String createStepName(ExtensionContext context, ItemType itemType) { /** * Extension point to customize test step creation event/request * - * @param context JUnit's test context - * @param arguments a test arguments list - * @param itemType a test method item type - * @param startTime a start time of the test + * @param context JUnit's test context + * @param arguments a test arguments list + * @param itemType a test method item type + * @param description a description of the item + * @param startTime a start time of the test * @return Request to ReportPortal */ @Nonnull @@ -866,7 +869,8 @@ protected String createConfigurationName(@Nonnull Class testClass, @Nonnull M /** * Extension point to customize test step description * - * @param context JUnit's test context + * @param context JUnit's test context + * @param itemType a test method item type * @return Test/Step Description being sent to ReportPortal */ @Nonnull