diff --git a/CHANGELOG.md b/CHANGELOG.md index ee85cba..d9ea7ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Changelog ## [Unreleased] +### Added +- `@DisplayName` annotation support, by @nick130589 +- Last error log reporting into Test Item Description, by @aykhangaffarov ## [5.3.2] ### Changed diff --git a/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java b/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java index b4c04f8..4b5a0da 100644 --- a/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java +++ b/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java @@ -36,6 +36,7 @@ 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; @@ -91,7 +92,8 @@ 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"; + private final Map testThrowable = new ConcurrentHashMap<>(); @Nonnull protected Optional> getItemId(@Nonnull ExtensionContext context) { return ofNullable(idMapping.get(context)); @@ -286,14 +288,16 @@ public T interceptTestFactoryMethod(Invocation invocation, /** * Returns a status of a test based on execution exception * + * @param context JUnit's test context * @param throwable test exception * @return an {@link ItemStatus} */ @Nonnull - protected ItemStatus getExecutionStatus(@Nullable final Throwable throwable) { + 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; } @@ -320,7 +324,7 @@ public void interceptDynamicTest(Invocation invocation, DynamicTestInvocat invocation.proceed(); finishTest(extensionContext, PASSED); } catch (Throwable throwable) { - finishTest(extensionContext, getExecutionStatus(throwable)); + finishTest(extensionContext, getExecutionStatus(extensionContext, throwable)); throw throwable; } } @@ -340,7 +344,7 @@ public void interceptTestTemplateMethod(Invocation invocation, */ @Nonnull protected ItemStatus getExecutionStatus(@Nonnull final ExtensionContext context) { - return context.getExecutionException().map(this::getExecutionStatus).orElse(PASSED); + return context.getExecutionException().map(t -> getExecutionStatus(context, t)).orElse(PASSED); } @Override @@ -368,6 +372,7 @@ public void testFailed(ExtensionContext context, Throwable cause) { if(failedClassInits.contains(parent)) { startTestItem(context, STEP); sendStackTraceToRP(cause); + testThrowable.put(context, cause); finishTest(context, FAILED); } }); @@ -420,7 +425,7 @@ private void finishBeforeAfter(Invocation invocation, ExtensionContext con try { invocation.proceed(); } catch (Throwable throwable) { - finishBeforeAfter(context, id, getExecutionStatus(throwable)); + finishBeforeAfter(context, id, getExecutionStatus(context, throwable)); throw throwable; } finishBeforeAfter(context, id, PASSED); @@ -676,7 +681,7 @@ protected StartTestItemRQ buildStartStepRq(@Nonnull final ExtensionContext conte @Nullable final Date startTime) { StartTestItemRQ rq = new StartTestItemRQ(); rq.setStartTime(ofNullable(startTime).orElseGet(Calendar.getInstance()::getTime)); - rq.setName(createStepName(context)); + rq.setName(createStepName(context, itemType)); rq.setDescription(ofNullable(description).orElseGet(() -> createStepDescription(context, itemType))); rq.setType(itemType == TEMPLATE ? SUITE.name() : itemType.name()); String codeRef = getCodeRef(context); @@ -757,8 +762,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; + String description = String.format(DESCRIPTION_TEST_ERROR_FORMAT, + createStepDescription(context, itemType), + ExceptionUtils.getStackTrace(testThrowable.get(context))); + rq.setDescription(description); + } ofNullable(status).ifPresent(s -> rq.setStatus(s.name())); rq.setEndTime(Calendar.getInstance().getTime()); + testThrowable.remove(context); return rq; } @@ -782,11 +795,38 @@ protected FinishTestItemRQ buildFinishTestItemRq(@Nonnull ExtensionContext conte * 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) { + protected String createStepName(ExtensionContext context, ItemType itemType) { String name = context.getDisplayName(); - return name.length() > 1024 ? name.substring(0, 1021) + "..." : name; + 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; } /** diff --git a/src/test/java/com/epam/reportportal/junit5/DisplayNameTest.java b/src/test/java/com/epam/reportportal/junit5/DisplayNameTest.java new file mode 100644 index 0000000..6b581c0 --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/DisplayNameTest.java @@ -0,0 +1,281 @@ +package com.epam.reportportal.junit5; + +import com.epam.reportportal.junit5.features.displayname.*; +import com.epam.reportportal.junit5.util.TestUtils; +import com.epam.reportportal.service.Launch; +import com.epam.reportportal.util.test.CommonUtils; +import com.epam.ta.reportportal.ws.model.StartTestItemRQ; +import io.reactivex.Maybe; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.mockito.ArgumentCaptor; +import org.mockito.stubbing.Answer; + +import java.util.List; +import java.util.stream.Collectors; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasItem; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +/** + * @author Mykola Zakapko + */ +public class DisplayNameTest { + public static class TestExtension extends ReportPortalExtension { + static Launch LAUNCH; + + @Override + protected Launch getLaunch(ExtensionContext context) { + return LAUNCH; + } + } + + @BeforeEach + public void setupMock() { + TestExtension.LAUNCH = mock(Launch.class); + when(TestExtension.LAUNCH.startTestItem(any())).thenAnswer((Answer>) invocation -> CommonUtils.createMaybeUuid()); + when(TestExtension.LAUNCH.startTestItem(any(), + any() + )).thenAnswer((Answer>) invocation -> CommonUtils.createMaybeUuid()); + } + + @Test + void displayNameFromMethodAnnotationTest() { + TestUtils.runClasses(DisplayNameAnnotatedClassTest.class); + + Launch launch = TestExtension.LAUNCH; + + verify(launch, times(1)).startTestItem(any()); // Start parent Suite + + ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(launch, times(1)).startTestItem(notNull(), captor.capture()); // Start a test + + StartTestItemRQ request = captor.getValue(); + assertThat(request.getName(), equalTo(DisplayNameAnnotatedClassTest.TEST_DISPLAY_NAME_CLASS)); + } + + @Test + void displayNameFromClassAnnotationTest() { + TestUtils.runClasses(DisplayNameAnnotatedClassTest.class); + + Launch launch = TestExtension.LAUNCH; + + verify(launch, times(1)).startTestItem(any()); // Start parent Suite + + ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(launch, times(1)).startTestItem(notNull(), captor.capture()); // Start a test + + StartTestItemRQ request = captor.getValue(); + assertThat(request.getName(), equalTo(DisplayNameAnnotatedClassTest.TEST_DISPLAY_NAME_CLASS)); + } + + @Test + void displayNameFromBothMethodAndClassAnnotationTest() { + TestUtils.runClasses(DisplayNameAnnotatedMethodAndClassTest.class); + + Launch launch = TestExtension.LAUNCH; + + verify(launch, times(1)).startTestItem(any()); // Start parent Suite + + ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(launch, times(1)).startTestItem(notNull(), captor.capture()); // Start a test + + StartTestItemRQ request = captor.getValue(); + //from both annotations the expected one should be taken from the method + assertThat(request.getName(), equalTo(DisplayNameAnnotatedMethodTest.TEST_DISPLAY_NAME_METHOD)); + } + + @Test + void displayNameFromMethodAnnotationDynamicTest() { + TestUtils.runClasses(DisplayNameAnnotatedMethodDynamicTest.class); + + Launch launch = TestExtension.LAUNCH; + verify(launch, times(1)).startTestItem(any()); // Start parent Suite + + ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(launch, times(2)).startTestItem(notNull(), captor.capture()); // Start a test + + List testStepsDisplayName = captor.getAllValues() + .stream() + .filter(e -> e.getType().equals(ItemType.STEP.name())) + .map(StartTestItemRQ::getName) + .collect(Collectors.toList()); + + assertThat(testStepsDisplayName, hasItem(DisplayNameAnnotatedMethodDynamicTest.TEST_DISPLAY_NAME_DYNAMIC_METHOD)); + } + + @Test + void displayNameFromClassAnnotationDynamicTest() { + TestUtils.runClasses(DisplayNameAnnotatedClassDynamicTest.class); + + Launch launch = TestExtension.LAUNCH; + verify(launch, times(1)).startTestItem(any()); // Start parent Suite + + ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(launch, times(2)).startTestItem(notNull(), captor.capture()); // Start a test + + List testStepsDisplayName = captor.getAllValues() + .stream() + .filter(e -> e.getType().equals(ItemType.STEP.name())) + .map(StartTestItemRQ::getName) + .collect(Collectors.toList()); + + assertThat(testStepsDisplayName, hasItem(DisplayNameAnnotatedClassDynamicTest.TEST_DISPLAY_NAME_DYNAMIC_CLASS)); + } + + @Test + void displayNameFromBothMethodAndClassAnnotationDynamicTest() { + TestUtils.runClasses(DisplayNameAnnotatedMethodAndClassDynamicTest.class); + + Launch launch = TestExtension.LAUNCH; + verify(launch, times(1)).startTestItem(any()); // Start parent Suite + + ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(launch, times(2)).startTestItem(notNull(), captor.capture()); // Start a test + + List testStepsDisplayName = captor.getAllValues() + .stream() + .filter(e -> e.getType().equals(ItemType.STEP.name())) + .map(StartTestItemRQ::getName) + .collect(Collectors.toList()); + //from both annotations the expected one should be taken from the method + assertThat(testStepsDisplayName, hasItem(DisplayNameAnnotatedMethodDynamicTest.TEST_DISPLAY_NAME_DYNAMIC_METHOD)); + } + + @Test + void displayNameJunitAndRPFromMethodAnnotationTest() { + TestUtils.runClasses(DisplayNameBothJunitAndRPAnnotatedMethodTest.class); + + Launch launch = TestExtension.LAUNCH; + + verify(launch, times(1)).startTestItem(any()); // Start parent Suite + + ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(launch, times(1)).startTestItem(notNull(), captor.capture()); // Start a test + + StartTestItemRQ request = captor.getValue(); + assertThat(request.getName(), equalTo(DisplayNameBothJunitAndRPAnnotatedMethodTest.TEST_DISPLAY_NAME_METHOD)); + } + + @Test + void displayNameJunitAndRPFromClassAnnotationAnnotationTest() { + TestUtils.runClasses(DisplayNameBothJunitAndRPAnnotatedClassTest.class); + + Launch launch = TestExtension.LAUNCH; + + verify(launch, times(1)).startTestItem(any()); // Start parent Suite + + ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(launch, times(1)).startTestItem(notNull(), captor.capture()); // Start a test + + StartTestItemRQ request = captor.getValue(); + assertThat(request.getName(), equalTo(DisplayNameBothJunitAndRPAnnotatedClassTest.TEST_DISPLAY_NAME_CLASS)); + } + + @Test + void displayNameJunitAndRPFromMethodAnnotationDynamicTest() { + TestUtils.runClasses(DisplayNameBothJunitAndRPAnnotatedMethodDynamicTest.class); + + Launch launch = TestExtension.LAUNCH; + verify(launch, times(1)).startTestItem(any()); // Start parent Suite + + ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(launch, times(2)).startTestItem(notNull(), captor.capture()); // Start a test + + List testStepsDisplayName = captor.getAllValues() + .stream() + .filter(e -> e.getType().equals(ItemType.STEP.name())) + .map(StartTestItemRQ::getName) + .collect(Collectors.toList()); + + assertThat(testStepsDisplayName, hasItem(DisplayNameBothJunitAndRPAnnotatedMethodDynamicTest.TEST_DISPLAY_NAME_DYNAMIC_METHOD)); + } + + @Test + void displayNameJunitAndRPFromClassAnnotationDynamicTest() { + TestUtils.runClasses(DisplayNameBothJunitAndRPAnnotatedClassDynamicTest.class); + + Launch launch = TestExtension.LAUNCH; + verify(launch, times(1)).startTestItem(any()); // Start parent Suite + + ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(launch, times(2)).startTestItem(notNull(), captor.capture()); // Start a test + + List testStepsDisplayName = captor.getAllValues() + .stream() + .filter(e -> e.getType().equals(ItemType.STEP.name())) + .map(StartTestItemRQ::getName) + .collect(Collectors.toList()); + + assertThat(testStepsDisplayName, hasItem(DisplayNameBothJunitAndRPAnnotatedClassDynamicTest.TEST_DISPLAY_NAME_DYNAMIC_CLASS)); + } + + @Test + void displayNameJunitAndRPFromBothMethodAndClassAnnotationTest() { + TestUtils.runClasses(DisplayNameBothJunitAndRPAnnotatedMethodAndClassTest.class); + + Launch launch = TestExtension.LAUNCH; + + verify(launch, times(1)).startTestItem(any()); // Start parent Suite + + ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(launch, times(1)).startTestItem(notNull(), captor.capture()); // Start a test + + StartTestItemRQ request = captor.getValue(); + //from both annotations the expected one should be taken from the method + assertThat(request.getName(), equalTo(DisplayNameAnnotatedMethodTest.TEST_DISPLAY_NAME_METHOD)); + } + + @Test + void displayNameJunitAndRPFromBothMethodAndClassAnnotationDynamicTest() { + TestUtils.runClasses(DisplayNameBothJunitAndRPAnnotatedMethodAndClassDynamicTest.class); + + Launch launch = TestExtension.LAUNCH; + verify(launch, times(1)).startTestItem(any()); // Start parent Suite + + ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(launch, times(2)).startTestItem(notNull(), captor.capture()); // Start a test + + List testStepsDisplayName = captor.getAllValues() + .stream() + .filter(e -> e.getType().equals(ItemType.STEP.name())) + .map(StartTestItemRQ::getName) + .collect(Collectors.toList()); + //from both annotations the expected one should be taken from the method + assertThat(testStepsDisplayName, hasItem(DisplayNameAnnotatedMethodDynamicTest.TEST_DISPLAY_NAME_DYNAMIC_METHOD)); + } + + @Test + void displayNameFromClassAnnotationWithEmptyValueTest() { + TestUtils.runClasses(DisplayNameAnnotatedClassWithEmptyValueTest.class); + + Launch launch = TestExtension.LAUNCH; + + verify(launch, times(1)).startTestItem(any()); // Start parent Suite + + ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(launch, times(1)).startTestItem(notNull(), captor.capture()); // Start a test + + StartTestItemRQ request = captor.getValue(); + assertThat(request.getName(), equalTo(DisplayNameAnnotatedClassWithEmptyValueTest.TEST_DISPLAY_NAME_CLASS)); + } + + @Test + void displayNameFromMethodAnnotationWithEmptyValueTest() { + TestUtils.runClasses(DisplayNameAnnotatedMethodWithEmptyValueTest.class); + + Launch launch = TestExtension.LAUNCH; + + verify(launch, times(1)).startTestItem(any()); // Start parent Suite + + ArgumentCaptor captor = ArgumentCaptor.forClass(StartTestItemRQ.class); + verify(launch, times(1)).startTestItem(notNull(), captor.capture()); // Start a test + + StartTestItemRQ request = captor.getValue(); + assertThat(request.getName(), equalTo(DisplayNameAnnotatedMethodWithEmptyValueTest.TEST_DISPLAY_NAME_METHOD)); + } +} diff --git a/src/test/java/com/epam/reportportal/junit5/ErrorLastLogTest.java b/src/test/java/com/epam/reportportal/junit5/ErrorLastLogTest.java new file mode 100644 index 0000000..734eb42 --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/ErrorLastLogTest.java @@ -0,0 +1,151 @@ +package com.epam.reportportal.junit5; + +import com.epam.reportportal.junit5.features.lasterrorlog.ErrorLastLogFeatureWithAssertionErrorTest; +import com.epam.reportportal.junit5.features.lasterrorlog.ErrorLastLogFeatureWithAssertionPassedTest; +import com.epam.reportportal.junit5.features.lasterrorlog.ErrorLastLogFeatureWithExceptionTest; +import com.epam.reportportal.junit5.features.lasterrorlog.ErrorLastLogFeatureWithStepTest; +import com.epam.reportportal.junit5.util.TestUtils; +import com.epam.reportportal.service.Launch; +import com.epam.reportportal.service.ReportPortal; +import com.epam.reportportal.service.ReportPortalClient; +import com.epam.ta.reportportal.ws.model.FinishTestItemRQ; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.platform.engine.TestExecutionResult; +import org.junit.platform.launcher.TestExecutionListener; +import org.junit.platform.launcher.TestIdentifier; +import org.mockito.ArgumentCaptor; + +import java.util.Deque; +import java.util.List; +import java.util.concurrent.ConcurrentLinkedDeque; + +import static com.epam.reportportal.util.test.CommonUtils.namedId; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.startsWith; +import static org.mockito.Mockito.*; + +@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 { + + 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()))); + + } + + @Override + protected Launch getLaunch(ExtensionContext context) { + return launch.get(); + } + + } + + public static class Listener implements TestExecutionListener { + public Deque results = new ConcurrentLinkedDeque<>(); + + @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); + + ReportPortalClient client = ErrorDescriptionTestExtension.client.get(); + + ArgumentCaptor finishTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); + verify(client, timeout(1000).atLeastOnce()).finishTestItem(same(testMethodUuid), finishTestCaptor.capture()); + + + List finishTests = finishTestCaptor.getAllValues(); + + FinishTestItemRQ testCaseWithException = finishTests.get(0); + + assertThat(testCaseWithException.getDescription(), startsWith(String.format(testErrorMessagePattern, "", testExceptionMessage))); + assertThat(testCaseWithException.getStatus(), equalTo(failedStatus)); + + } + + @Test + public void verify_last_error_log_step() { + ErrorDescriptionTestExtension.init(); + Listener listener = new Listener(); + TestUtils.runClasses(listener, ErrorLastLogFeatureWithStepTest.class); + + ReportPortalClient client = ErrorDescriptionTestExtension.client.get(); + + ArgumentCaptor finishTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); + verify(client, timeout(1000).atLeastOnce()).finishTestItem(same(testMethodUuid), finishTestCaptor.capture()); + + List finishTests = finishTestCaptor.getAllValues(); + + FinishTestItemRQ testCaseWithDescriptionAndStepError = finishTests.get(0); + + assertThat(testCaseWithDescriptionAndStepError.getDescription(), startsWith(String.format(testErrorMessagePattern, stepDescriptionMessage, exceptionStepErrorMessage))); + assertThat(testCaseWithDescriptionAndStepError.getStatus(), equalTo(failedStatus)); + } + + @Test + public void verify_last_error_log_assertion_error() { + ErrorDescriptionTestExtension.init(); + Listener listener = new Listener(); + TestUtils.runClasses(listener, ErrorLastLogFeatureWithAssertionErrorTest.class); + + ReportPortalClient client = ErrorDescriptionTestExtension.client.get(); + + ArgumentCaptor finishTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); + verify(client, timeout(1000).atLeastOnce()).finishTestItem(same(testMethodUuid), finishTestCaptor.capture()); + + List finishTests = finishTestCaptor.getAllValues(); + + FinishTestItemRQ testCaseAssertException = finishTests.get(0); + + assertThat(testCaseAssertException.getDescription(), startsWith(String.format(testErrorMessagePattern, assertDescriptionMessage, assertErrorMessage))); + assertThat(testCaseAssertException.getStatus(), equalTo(failedStatus)); + } + + @Test + public void verify_last_error_log_assertion_passed() { + ErrorDescriptionTestExtension.init(); + Listener listener = new Listener(); + TestUtils.runClasses(listener, ErrorLastLogFeatureWithAssertionPassedTest.class); + + ReportPortalClient client = ErrorDescriptionTestExtension.client.get(); + + ArgumentCaptor finishTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class); + verify(client, timeout(1000).atLeastOnce()).finishTestItem(same(testMethodUuid), finishTestCaptor.capture()); + + List finishTests = finishTestCaptor.getAllValues(); + + FinishTestItemRQ testCaseWithDescriptionAndPassed = finishTests.get(0); + + assertThat(testCaseWithDescriptionAndPassed.getStatus(), equalTo(passedStatus)); + + } +} diff --git a/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameAnnotatedClassDynamicTest.java b/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameAnnotatedClassDynamicTest.java new file mode 100644 index 0000000..053d488 --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameAnnotatedClassDynamicTest.java @@ -0,0 +1,21 @@ +package com.epam.reportportal.junit5.features.displayname; + +import com.epam.reportportal.annotations.DisplayName; +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) +@DisplayName(DisplayNameAnnotatedClassDynamicTest.TEST_DISPLAY_NAME_DYNAMIC_CLASS) +public class DisplayNameAnnotatedClassDynamicTest { + public static final String TEST_DISPLAY_NAME_DYNAMIC_CLASS = "My test displayName on the dynamic class"; + @TestFactory + Stream testForTestFactory() { + return Stream.of(dynamicTest("My dynamic test", () -> System.out.println("Inside dynamic test"))); + } +} diff --git a/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameAnnotatedClassTest.java b/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameAnnotatedClassTest.java new file mode 100644 index 0000000..c82d1ee --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameAnnotatedClassTest.java @@ -0,0 +1,14 @@ +package com.epam.reportportal.junit5.features.displayname; + +import com.epam.reportportal.junit5.DisplayNameTest; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +@com.epam.reportportal.annotations.DisplayName(DisplayNameAnnotatedClassTest.TEST_DISPLAY_NAME_CLASS) +@ExtendWith(DisplayNameTest.TestExtension.class) +public class DisplayNameAnnotatedClassTest { + public static final String TEST_DISPLAY_NAME_CLASS = "My display name"; + @Test + public void testDisplayNameTest() { + } +} diff --git a/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameAnnotatedClassWithEmptyValueTest.java b/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameAnnotatedClassWithEmptyValueTest.java new file mode 100644 index 0000000..90fe3c5 --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameAnnotatedClassWithEmptyValueTest.java @@ -0,0 +1,14 @@ +package com.epam.reportportal.junit5.features.displayname; + +import com.epam.reportportal.junit5.DisplayNameTest; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +@com.epam.reportportal.annotations.DisplayName(DisplayNameAnnotatedClassWithEmptyValueTest.TEST_DISPLAY_NAME_CLASS) +@ExtendWith(DisplayNameTest.TestExtension.class) +public class DisplayNameAnnotatedClassWithEmptyValueTest { + public static final String TEST_DISPLAY_NAME_CLASS = ""; + @Test + public void testDisplayNameTest() { + } +} diff --git a/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameAnnotatedMethodAndClassDynamicTest.java b/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameAnnotatedMethodAndClassDynamicTest.java new file mode 100644 index 0000000..c513265 --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameAnnotatedMethodAndClassDynamicTest.java @@ -0,0 +1,21 @@ +package com.epam.reportportal.junit5.features.displayname; + +import com.epam.reportportal.annotations.DisplayName; +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) +@DisplayName(DisplayNameAnnotatedClassDynamicTest.TEST_DISPLAY_NAME_DYNAMIC_CLASS) +public class DisplayNameAnnotatedMethodAndClassDynamicTest { + @TestFactory + @DisplayName(DisplayNameAnnotatedMethodDynamicTest.TEST_DISPLAY_NAME_DYNAMIC_METHOD) + Stream testForTestFactory() { + return Stream.of(dynamicTest("My dynamic test", () -> System.out.println("Inside dynamic test"))); + } +} diff --git a/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameAnnotatedMethodAndClassTest.java b/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameAnnotatedMethodAndClassTest.java new file mode 100644 index 0000000..f7a3739 --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameAnnotatedMethodAndClassTest.java @@ -0,0 +1,15 @@ +package com.epam.reportportal.junit5.features.displayname; + +import com.epam.reportportal.annotations.DisplayName; +import com.epam.reportportal.junit5.DisplayNameTest; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +@ExtendWith(DisplayNameTest.TestExtension.class) +@DisplayName(DisplayNameAnnotatedClassTest.TEST_DISPLAY_NAME_CLASS) +public class DisplayNameAnnotatedMethodAndClassTest { + @Test + @DisplayName(DisplayNameAnnotatedMethodTest.TEST_DISPLAY_NAME_METHOD) + public void testDisplayNameTest() { + } +} diff --git a/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameAnnotatedMethodDynamicTest.java b/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameAnnotatedMethodDynamicTest.java new file mode 100644 index 0000000..7712a60 --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameAnnotatedMethodDynamicTest.java @@ -0,0 +1,21 @@ +package com.epam.reportportal.junit5.features.displayname; + +import com.epam.reportportal.annotations.DisplayName; +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 DisplayNameAnnotatedMethodDynamicTest { + public static final String TEST_DISPLAY_NAME_DYNAMIC_METHOD = "My test displayName on the dynamic method"; + @TestFactory + @DisplayName(TEST_DISPLAY_NAME_DYNAMIC_METHOD) + Stream testForTestFactory() { + return Stream.of(dynamicTest("My dynamic test", () -> System.out.println("Inside dynamic test"))); + } +} diff --git a/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameAnnotatedMethodTest.java b/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameAnnotatedMethodTest.java new file mode 100644 index 0000000..e166c1c --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameAnnotatedMethodTest.java @@ -0,0 +1,15 @@ +package com.epam.reportportal.junit5.features.displayname; + +import com.epam.reportportal.annotations.DisplayName; +import com.epam.reportportal.junit5.DisplayNameTest; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +@ExtendWith(DisplayNameTest.TestExtension.class) +public class DisplayNameAnnotatedMethodTest { + public static final String TEST_DISPLAY_NAME_METHOD = "My test displayName on the method"; + @Test + @DisplayName(TEST_DISPLAY_NAME_METHOD) + public void testDisplayNameTest() { + } +} diff --git a/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameAnnotatedMethodWithEmptyValueTest.java b/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameAnnotatedMethodWithEmptyValueTest.java new file mode 100644 index 0000000..0c778e3 --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameAnnotatedMethodWithEmptyValueTest.java @@ -0,0 +1,15 @@ +package com.epam.reportportal.junit5.features.displayname; + +import com.epam.reportportal.annotations.DisplayName; +import com.epam.reportportal.junit5.DisplayNameTest; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +@ExtendWith(DisplayNameTest.TestExtension.class) +public class DisplayNameAnnotatedMethodWithEmptyValueTest { + public static final String TEST_DISPLAY_NAME_METHOD = ""; + @Test + @DisplayName(TEST_DISPLAY_NAME_METHOD) + public void testDisplayNameTest() { + } +} diff --git a/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameBothJunitAndRPAnnotatedClassDynamicTest.java b/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameBothJunitAndRPAnnotatedClassDynamicTest.java new file mode 100644 index 0000000..33d5e44 --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameBothJunitAndRPAnnotatedClassDynamicTest.java @@ -0,0 +1,22 @@ +package com.epam.reportportal.junit5.features.displayname; + +import com.epam.reportportal.annotations.DisplayName; +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) +@DisplayName(DisplayNameBothJunitAndRPAnnotatedClassDynamicTest.TEST_DISPLAY_NAME_DYNAMIC_CLASS) +@org.junit.jupiter.api.DisplayName("Junit") +public class DisplayNameBothJunitAndRPAnnotatedClassDynamicTest { + public static final String TEST_DISPLAY_NAME_DYNAMIC_CLASS = "My test displayName on the dynamic class"; + @TestFactory + Stream testForTestFactory() { + return Stream.of(dynamicTest("My dynamic test", () -> System.out.println("Inside dynamic test"))); + } +} diff --git a/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameBothJunitAndRPAnnotatedClassTest.java b/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameBothJunitAndRPAnnotatedClassTest.java new file mode 100644 index 0000000..49e383a --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameBothJunitAndRPAnnotatedClassTest.java @@ -0,0 +1,16 @@ +package com.epam.reportportal.junit5.features.displayname; + +import com.epam.reportportal.junit5.DisplayNameTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +@com.epam.reportportal.annotations.DisplayName(DisplayNameBothJunitAndRPAnnotatedClassTest.TEST_DISPLAY_NAME_CLASS) +@ExtendWith(DisplayNameTest.TestExtension.class) +@DisplayName("Junit") +public class DisplayNameBothJunitAndRPAnnotatedClassTest { + public static final String TEST_DISPLAY_NAME_CLASS = "My display name"; + @Test + public void testDisplayNameTest() { + } +} diff --git a/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameBothJunitAndRPAnnotatedMethodAndClassDynamicTest.java b/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameBothJunitAndRPAnnotatedMethodAndClassDynamicTest.java new file mode 100644 index 0000000..e555c2e --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameBothJunitAndRPAnnotatedMethodAndClassDynamicTest.java @@ -0,0 +1,23 @@ +package com.epam.reportportal.junit5.features.displayname; + +import com.epam.reportportal.annotations.DisplayName; +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) +@DisplayName(DisplayNameAnnotatedClassDynamicTest.TEST_DISPLAY_NAME_DYNAMIC_CLASS) +@org.junit.jupiter.api.DisplayName("Junit class") +public class DisplayNameBothJunitAndRPAnnotatedMethodAndClassDynamicTest { + @TestFactory + @DisplayName(DisplayNameAnnotatedMethodDynamicTest.TEST_DISPLAY_NAME_DYNAMIC_METHOD) + @org.junit.jupiter.api.DisplayName("Junit method") + Stream testForTestFactory() { + return Stream.of(dynamicTest("My dynamic test", () -> System.out.println("Inside dynamic test"))); + } +} diff --git a/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameBothJunitAndRPAnnotatedMethodAndClassTest.java b/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameBothJunitAndRPAnnotatedMethodAndClassTest.java new file mode 100644 index 0000000..d287ac2 --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameBothJunitAndRPAnnotatedMethodAndClassTest.java @@ -0,0 +1,17 @@ +package com.epam.reportportal.junit5.features.displayname; + +import com.epam.reportportal.annotations.DisplayName; +import com.epam.reportportal.junit5.DisplayNameTest; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +@ExtendWith(DisplayNameTest.TestExtension.class) +@DisplayName(DisplayNameAnnotatedClassTest.TEST_DISPLAY_NAME_CLASS) +@org.junit.jupiter.api.DisplayName("Junit class") +public class DisplayNameBothJunitAndRPAnnotatedMethodAndClassTest { + @Test + @DisplayName(DisplayNameAnnotatedMethodTest.TEST_DISPLAY_NAME_METHOD) + @org.junit.jupiter.api.DisplayName("Junit method") + public void testDisplayNameTest() { + } +} diff --git a/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameBothJunitAndRPAnnotatedMethodDynamicTest.java b/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameBothJunitAndRPAnnotatedMethodDynamicTest.java new file mode 100644 index 0000000..86c20dc --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameBothJunitAndRPAnnotatedMethodDynamicTest.java @@ -0,0 +1,22 @@ +package com.epam.reportportal.junit5.features.displayname; + +import com.epam.reportportal.annotations.DisplayName; +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 DisplayNameBothJunitAndRPAnnotatedMethodDynamicTest { + public static final String TEST_DISPLAY_NAME_DYNAMIC_METHOD = "My test displayName on the dynamic method"; + @TestFactory + @DisplayName(TEST_DISPLAY_NAME_DYNAMIC_METHOD) + @org.junit.jupiter.api.DisplayName("Junit") + Stream testForTestFactory() { + return Stream.of(dynamicTest("My dynamic test", () -> System.out.println("Inside dynamic test"))); + } +} diff --git a/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameBothJunitAndRPAnnotatedMethodTest.java b/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameBothJunitAndRPAnnotatedMethodTest.java new file mode 100644 index 0000000..559a9ca --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/features/displayname/DisplayNameBothJunitAndRPAnnotatedMethodTest.java @@ -0,0 +1,16 @@ +package com.epam.reportportal.junit5.features.displayname; + +import com.epam.reportportal.annotations.DisplayName; +import com.epam.reportportal.junit5.DisplayNameTest; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +@ExtendWith(DisplayNameTest.TestExtension.class) +public class DisplayNameBothJunitAndRPAnnotatedMethodTest { + public static final String TEST_DISPLAY_NAME_METHOD = "My test displayName on the method"; + @Test + @DisplayName(TEST_DISPLAY_NAME_METHOD) + @org.junit.jupiter.api.DisplayName("Junit") + public void testDisplayNameTest() { + } +} diff --git a/src/test/java/com/epam/reportportal/junit5/features/lasterrorlog/ErrorLastLogFeatureWithAssertionErrorTest.java b/src/test/java/com/epam/reportportal/junit5/features/lasterrorlog/ErrorLastLogFeatureWithAssertionErrorTest.java new file mode 100644 index 0000000..df28623 --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/features/lasterrorlog/ErrorLastLogFeatureWithAssertionErrorTest.java @@ -0,0 +1,18 @@ +package com.epam.reportportal.junit5.features.lasterrorlog; + +import com.epam.reportportal.annotations.Description; +import com.epam.reportportal.junit5.ErrorLastLogTest; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + + +@ExtendWith(ErrorLastLogTest.ErrorDescriptionTestExtension.class) +public class ErrorLastLogFeatureWithAssertionErrorTest { + + @Test + @Description("0 and 1 is not equal") + public void testWithAssertException() { + Assertions.assertEquals(0, 1); + } +} diff --git a/src/test/java/com/epam/reportportal/junit5/features/lasterrorlog/ErrorLastLogFeatureWithAssertionPassedTest.java b/src/test/java/com/epam/reportportal/junit5/features/lasterrorlog/ErrorLastLogFeatureWithAssertionPassedTest.java new file mode 100644 index 0000000..ce55f62 --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/features/lasterrorlog/ErrorLastLogFeatureWithAssertionPassedTest.java @@ -0,0 +1,24 @@ +package com.epam.reportportal.junit5.features.lasterrorlog; + +import com.epam.reportportal.annotations.Description; +import com.epam.reportportal.annotations.Step; +import com.epam.reportportal.junit5.ErrorLastLogTest; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +@ExtendWith(ErrorLastLogTest.ErrorDescriptionTestExtension.class) +public class ErrorLastLogFeatureWithAssertionPassedTest { + + @Test + @Description("successful test") + public void testWithDescriptionAndPassed() { + login(); + Assertions.assertTrue(true); + } + + @Step + public void login() { + System.out.println("Login successful"); + } +} diff --git a/src/test/java/com/epam/reportportal/junit5/features/lasterrorlog/ErrorLastLogFeatureWithExceptionTest.java b/src/test/java/com/epam/reportportal/junit5/features/lasterrorlog/ErrorLastLogFeatureWithExceptionTest.java new file mode 100644 index 0000000..f19e32c --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/features/lasterrorlog/ErrorLastLogFeatureWithExceptionTest.java @@ -0,0 +1,17 @@ +package com.epam.reportportal.junit5.features.lasterrorlog; + +import com.epam.reportportal.junit5.ErrorLastLogTest; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +@ExtendWith(ErrorLastLogTest.ErrorDescriptionTestExtension.class) +public class ErrorLastLogFeatureWithExceptionTest { + + + @Test + public void testWithException() { + throw new RuntimeException("Critical error"); + } + + +} diff --git a/src/test/java/com/epam/reportportal/junit5/features/lasterrorlog/ErrorLastLogFeatureWithStepTest.java b/src/test/java/com/epam/reportportal/junit5/features/lasterrorlog/ErrorLastLogFeatureWithStepTest.java new file mode 100644 index 0000000..8df2a98 --- /dev/null +++ b/src/test/java/com/epam/reportportal/junit5/features/lasterrorlog/ErrorLastLogFeatureWithStepTest.java @@ -0,0 +1,33 @@ +package com.epam.reportportal.junit5.features.lasterrorlog; + +import com.epam.reportportal.annotations.Description; +import com.epam.reportportal.annotations.Step; +import com.epam.reportportal.junit5.ErrorLastLogTest; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import java.util.NoSuchElementException; + +@ExtendWith(ErrorLastLogTest.ErrorDescriptionTestExtension.class) +public class ErrorLastLogFeatureWithStepTest { + + @Test + @Description("Login issue") + public void testWithStepError() { + enterCredentials(); + System.out.println("Username is not correct"); + loginWithException(); + Assertions.assertTrue(Boolean.TRUE); + } + + @Step + @Description("Credentials entered") + public void enterCredentials() { + Assertions.assertTrue(Boolean.TRUE); + } + @Step + public void loginWithException() { + throw new NoSuchElementException("Error message"); + } +}