extentreports-java
extentreports-java copied to clipboard
CreateTest when called with same TestName does not create another test with same name.
I have implemented extent report 3.1.5 via ITestListener interface and using retryAnalyzer in my testsuite.
- So , in onStart() method , I have called extent.createTest(String testname) method with testname as argument.
- I am printing logs via a common generic file having common methods like click, sendkeys etc. used across @beforemethod @test and @AfterMethod annotations.
- Now whenever test case is failed , it goes to retry analyzer and its started again based on retry count.
- Again code flow comes to onStart() method of ITestListener Interface which is having extent.create(String testname) method.
- Now while retrying the test case since test case name is same , new test case is not created , which is causing logs of the retried test case to be merged with the previous test run logs.
I hope ,I am able to explain the situation , please help me to get over it , Am I missing something here or doing it the wrong way ?
Thanks, Yogit Thakral
Can you share the iTestListener code?
Yes Sure ..
public class CustomListener extends BaseTestClass implements ITestListener {
public static ExtentReports extent = ExtentManager.getExtent();
public static ThreadLocal<ExtentTest> parentTest = new ThreadLocal<ExtentTest>();
public static ThreadLocal<ExtentTest> test = new ThreadLocal<ExtentTest>();
@Override
public synchronized void onStart(ITestContext context) {
ExtentTest parent;
int arrLength=context.getName().split("\\.").length;
String testName=context.getName().split("\\.")[arrLength-1];
/just to ignore a specific test from adding to the report/
if(!testName.equalsIgnoreCase("SetBrowserConfig")){
if(arrLength>0){
parent = extent.createTest(testName);
parent.assignCategory(context.getName().split("\\.")[arrLength-2]);
test.set(parent);
}else{
parent = extent.createTest(context.getName());
test.set(parent);
}
}
}
@Override
public synchronized void onFinish(ITestContext context) {
extent.flush();
}
@Override
public synchronized void onTestStart(ITestResult result) {
}
@Override
public synchronized void onTestSuccess(ITestResult result) {
if(!result.getMethod().getMethodName().equals("SetBrowserConfig")){
test.get().pass(result.getMethod().getMethodName()+" passed");
}
}
@Override
public synchronized void onTestSkipped(ITestResult result) {
if(!result.getMethod().getMethodName().equals("SetBrowserConfig")){
test.get().skip(result.getMethod().getMethodName()+" skipped");
}
}
@Override
public synchronized void onTestFailure(ITestResult result) {
if(!result.getMethod().getMethodName().equals("SetBrowserConfig")){
test.get().fail(result.getMethod().getMethodName()+" failed");
}
}
@Override public synchronized void onTestFailedButWithinSuccessPercentage(ITestResult result) {
}
@yogitthakral can you please format your code so it's readable?
Please try with this:
public class ExtentITestListener
implements ITestListener {
private static final ExtentReports EXTENT = Extent.getInstance();
private static ThreadLocal<ExtentTest> methodTest = new ThreadLocal<ExtentTest>();
private static ThreadLocal<ExtentTest> dataProviderTest = new ThreadLocal<>();
@Override
public synchronized void onStart(ITestContext context) { }
@Override
public synchronized void onFinish(ITestContext context) {
EXTENT.flush();
}
@Override
public synchronized void onTestStart(ITestResult result) {
String methodName = result.getMethod().getMethodName();
if (result.getParameters().length>0) {
if (methodTest.get() != null && methodTest.get().getModel().getName().equals(methodName)) { }
else {
createTest(result);
}
String paramName = Arrays.asList(result.getParameters()).toString();
ExtentTest paramTest = methodTest.get().createNode(paramName);
dataProviderTest.set(paramTest);
} else {
createTest(result);
}
}
private void createTest(ITestResult result) {
String methodName = result.getMethod().getMethodName();
ExtentTest test = EXTENT.createTest(methodName);
methodTest.set(test);
String[] groups = result.getMethod().getGroups();
if (groups.length > 0) {
Arrays.asList(groups)
.forEach(x -> methodTest.get().assignCategory(x));
}
}
@Override
public synchronized void onTestSuccess(ITestResult result) {
getTest(result).pass("Test passed");
}
private ExtentTest getTest(ITestResult result) {
ExtentTest t = result.getParameters() != null && result.getParameters().length>0
? dataProviderTest.get()
: methodTest.get();
return t;
}
@Override
public synchronized void onTestFailure(ITestResult result) {
getTest(result).fail(result.getThrowable());
}
@Override
public synchronized void onTestSkipped(ITestResult result) {
getTest(result).skip(result.getThrowable());
}
@Override
public synchronized void onTestFailedButWithinSuccessPercentage(ITestResult result) { }
}
Thank you so much for helping me out here
Pardon me for code formatting ...
I already tried a similar approach by placing a suffix to retried test case as "retry{counterOfRetry} and it solved the problem with test cases under retry now being entered separately.Well, the problem with this approach is , when you create an extent test on OnTestStart() method and flush it in OnFinish() --- When retry happens , it will start the process again , @beforemethod will be called and the logs created by @beforemethod will be appended to the previous run of the test case since Thread is having the extent test instance of the previous test case.
What I mean to say , is After Flushing and before creating another test case , if thread is having any logs , its writing to the previous test case .