Skip to content

Commit

Permalink
Merge pull request #209 from entrudo/Agents_Java_TestNG_LastErrorLog
Browse files Browse the repository at this point in the history
Add Agents_Java_TestNG Last Error Log
  • Loading branch information
HardNorth authored Apr 4, 2024
2 parents 064d474 + 7ced8b1 commit d697d63
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 0 deletions.
17 changes: 17 additions & 0 deletions src/main/java/com/epam/reportportal/testng/TestNGService.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import com.epam.ta.reportportal.ws.model.launch.StartLaunchRQ;
import com.epam.ta.reportportal.ws.model.log.SaveLogRQ;
import io.reactivex.Maybe;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.testng.*;
import org.testng.annotations.Factory;
Expand Down Expand Up @@ -94,6 +95,7 @@ public class TestNGService implements ITestNGService {
public static final String RP_RETRY = "rp_retry";
public static final String RP_METHOD_TYPE = "rp_method_type";
public static final String NULL_VALUE = "NULL";
public static final String DESCRIPTION_ERROR_FORMAT = "%s\nError: \n%s";
public static final TestItemTree ITEM_TREE = new TestItemTree();

private final Map<Object, Queue<Pair<Maybe<String>, FinishTestItemRQ>>> BEFORE_METHOD_TRACKER = new ConcurrentHashMap<>();
Expand Down Expand Up @@ -374,6 +376,9 @@ protected FinishTestItemRQ buildFinishTestMethodRq(@Nonnull ItemStatus status, @
FinishTestItemRQ rq = new FinishTestItemRQ();
rq.setEndTime(new Date(testResult.getEndMillis()));
rq.setStatus(status.name());
if (!testResult.isSuccess()) {
rq.setDescription(getLogMessage(testResult));
}
return rq;
}

Expand Down Expand Up @@ -797,4 +802,16 @@ Maybe<String> getConfigParent(ITestResult testResult, TestMethodType type) {
}
return parentId;
}

/**
* Extension point to customize test step description with error message
* @param testResult TestNG's testResult context
* @return Test/Step Description being sent to ReportPortal
*/
private String getLogMessage(ITestResult testResult) {
return String.format(DESCRIPTION_ERROR_FORMAT,
createStepDescription(testResult),
ExceptionUtils.getStackTrace(testResult.getThrowable()))
.trim();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package com.epam.reportportal.testng;

import static com.epam.reportportal.testng.TestNGService.DESCRIPTION_ERROR_FORMAT;
import static com.epam.reportportal.testng.integration.feature.description.DescriptionFailedTest.ASSERT_ERROR;
import static com.epam.reportportal.testng.integration.feature.description.DescriptionFailedTest.NO_SUCH_ELEMENT_EXCEPTION;
import static com.epam.reportportal.testng.integration.feature.description.DescriptionFailedTest.TEST_DESCRIPTION;
import static com.epam.reportportal.testng.integration.util.TestUtils.mockLaunch;
import static com.epam.reportportal.testng.integration.util.TestUtils.mockLogging;
import static com.epam.reportportal.testng.integration.util.TestUtils.namedUuid;
import static com.epam.reportportal.testng.integration.util.TestUtils.runTests;
import static com.epam.reportportal.testng.integration.util.TestUtils.standardParameters;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.startsWith;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import com.epam.reportportal.listeners.ItemStatus;
import com.epam.reportportal.listeners.ListenerParameters;
import com.epam.reportportal.service.Launch;
import com.epam.reportportal.service.ReportPortal;
import com.epam.reportportal.service.ReportPortalClient;
import com.epam.reportportal.testng.integration.feature.description.DescriptionFailedTest;
import com.epam.reportportal.utils.MemoizingSupplier;
import com.epam.ta.reportportal.ws.model.FinishTestItemRQ;
import com.epam.ta.reportportal.ws.model.launch.StartLaunchRQ;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class TestDescriptionFailedTest {

public static class TestListener extends BaseTestNGListener {
public static final ThreadLocal<ReportPortal> REPORT_PORTAL_THREAD_LOCAL = new ThreadLocal<>();

public TestListener() {
super(new TestNGService(new MemoizingSupplier<>(() -> getLaunch(REPORT_PORTAL_THREAD_LOCAL.get().getParameters()))));
}

public static void initReportPortal(ReportPortal reportPortal) {
REPORT_PORTAL_THREAD_LOCAL.set(reportPortal);
}

private static Launch getLaunch(ListenerParameters parameters) {

ReportPortal reportPortal = REPORT_PORTAL_THREAD_LOCAL.get();
StartLaunchRQ rq = new StartLaunchRQ();
rq.setName(parameters.getLaunchName());
rq.setStartTime(Calendar.getInstance().getTime());
rq.setMode(parameters.getLaunchRunningMode());
rq.setStartTime(Calendar.getInstance().getTime());

return reportPortal.newLaunch(rq);

}
}

private final String suitedUuid = namedUuid("suite");
private final String testClassUuid = namedUuid("class");
private final String assertionError = "java.lang.AssertionError: " + ASSERT_ERROR;
private final String noSuchElementException = "java.util.NoSuchElementException: " + NO_SUCH_ELEMENT_EXCEPTION;
private final String empty = "";
private final String testDescriptionTestAssertErrorMessage = String.format(DESCRIPTION_ERROR_FORMAT, TEST_DESCRIPTION, assertionError);
private final String testDescriptionTestExceptionMessage = String.format(DESCRIPTION_ERROR_FORMAT, TEST_DESCRIPTION, noSuchElementException);
private final String testWithoutDescriptionTestAssertErrorMessage = String.format(DESCRIPTION_ERROR_FORMAT, empty, assertionError).trim();
private final String testWithoutDescriptionTestExceptionMessage = String.format(DESCRIPTION_ERROR_FORMAT, empty, noSuchElementException).trim();

@Mock
private ReportPortalClient client;

@BeforeEach
public void initMocks() {
mockLaunch(client, namedUuid("launchUuid"), suitedUuid, testClassUuid, "test");
mockLogging(client);
ReportPortal reportPortal = ReportPortal.create(client, standardParameters());
TestListener.initReportPortal(reportPortal);
}

@Test
public void verify_description_in_case_of_test_exceptions() {
runTests(Collections.singletonList(TestDescriptionFailedTest.TestListener.class), DescriptionFailedTest.class);

verify(client, times(1)).startLaunch(any()); // Start launch
verify(client, times(1)).startTestItem(any()); // Start parent suites
verify(client, times(1)).startTestItem(same(suitedUuid), any()); // Start test class

ArgumentCaptor<String> finishUuidCapture = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<FinishTestItemRQ> finishItemCapture = ArgumentCaptor.forClass(FinishTestItemRQ.class);
verify(client, times(7)).finishTestItem(finishUuidCapture.capture(), finishItemCapture.capture());

List<FinishTestItemRQ> finishItems = finishItemCapture.getAllValues();
FinishTestItemRQ testDescriptionTestAssertError = finishItems.get(0);
FinishTestItemRQ testDescriptionTestException = finishItems.get(1);
FinishTestItemRQ testWithDescriptionAnnotationTestException = finishItems.get(2);
FinishTestItemRQ testWithoutDescriptionTestAssertError = finishItems.get(3);
FinishTestItemRQ testWithoutDescriptionTestException = finishItems.get(4);

assertThat(testDescriptionTestAssertError.getStatus(), equalTo(ItemStatus.FAILED.name()));
assertThat(testDescriptionTestException.getStatus(), equalTo(ItemStatus.FAILED.name()));
assertThat(testWithoutDescriptionTestAssertError.getStatus(), equalTo(ItemStatus.FAILED.name()));
assertThat(testWithoutDescriptionTestException.getStatus(), equalTo(ItemStatus.FAILED.name()));
assertThat(testWithDescriptionAnnotationTestException.getStatus(), equalTo(ItemStatus.FAILED.name()));

assertThat(testDescriptionTestAssertError.getDescription(), startsWith(testDescriptionTestAssertErrorMessage));
assertThat(testDescriptionTestException.getDescription(), startsWith(testDescriptionTestExceptionMessage));
assertThat(testWithoutDescriptionTestAssertError.getDescription(), startsWith(testWithoutDescriptionTestAssertErrorMessage));
assertThat(testWithoutDescriptionTestException.getDescription(), startsWith(testWithoutDescriptionTestExceptionMessage));
assertThat(testWithDescriptionAnnotationTestException.getDescription(), startsWith(testDescriptionTestExceptionMessage));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.epam.reportportal.testng.integration.feature.description;

import com.epam.reportportal.annotations.Description;
import java.util.NoSuchElementException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
import org.testng.annotations.Test;

public class DescriptionFailedTest {
private static final Logger LOGGER = LoggerFactory.getLogger(DescriptionFailedTest.class);

public static final String TEST_DESCRIPTION = "My test description";
public static final String ASSERT_ERROR = "Assert Error";
public static final String NO_SUCH_ELEMENT_EXCEPTION = "No Such Element Exception";

@Test(description = TEST_DESCRIPTION)
public void testDescriptionTestAssertError() {
LOGGER.info("Inside 'testDescriptionTestAssertError' method");
Assert.fail(ASSERT_ERROR);
}

@Test
public void testWithoutDescriptionTestAssertError() {
LOGGER.info("Inside 'testWithoutDescriptionTestAssertError' method");
Assert.fail(ASSERT_ERROR);
}

@Test(description = TEST_DESCRIPTION)
public void testDescriptionTestException() {
LOGGER.info("Inside 'testDescriptionTestException' method");
throw new NoSuchElementException(NO_SUCH_ELEMENT_EXCEPTION);
}

@Test
public void testWithoutDescriptionTestException() {
LOGGER.info("Inside 'testWithoutDescriptionTestException' method");
throw new NoSuchElementException(NO_SUCH_ELEMENT_EXCEPTION);
}

@Test
@Description(TEST_DESCRIPTION)
public void testWithDescriptionAnnotationTestException() {
LOGGER.info("Inside 'testWithoutDescriptionTestException' method");
throw new NoSuchElementException(NO_SUCH_ELEMENT_EXCEPTION);
}
}

0 comments on commit d697d63

Please sign in to comment.