I've got a TestNG framework currently set up with Extent Reports and I'm using ITestListener to handle the reporting. It works fine, until I try to add logging for individual test steps inside my @Test methods.
I declare my ExtentTest 'test' in baseTests.java, and then initialise it in my onTestStart() listener, but 'test' is coming back as 'null' in my @Test.
I've tried moving the ExtentTest declaration around, but it doesn't seem to make any difference. Is there a way of using the instance of test that's initialised in onTestStart()?
baseTests.java
package base;
import com.aventstack.extentreports.ExtentReports;
import com.aventstack.extentreports.ExtentTest;
import org.openqa.selenium.WebDriver;
import org.testng.annotations.BeforeMethod;
public class baseTests {
public ExtentReports extent = ExtentReporterNG.getReportObject();
public ExtentTest test;
@BeforeMethod
public void setUp() throws IOException {
// Test set-up code
}
}
ExtentReportNG.java
package base;
import com.aventstack.extentreports.ExtentReports;
import com.aventstack.extentreports.reporter.ExtentSparkReporter;
public class ExtentReporterNG {
static public ExtentReports extent;
public static ExtentReports getReportObject() {
String path = System.getProperty("user.dir")+"/reports/report.html";
ExtentSparkReporter reporter = new ExtentSparkReporter(path);
reporter.config().setReportName("Automation Tests");
extent = new ExtentReports();
extent.attachReporter(reporter);
return extent;
}
}
Listeners.java
package base;
import com.aventstack.extentreports.Status;
import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;
public class Listeners extends baseTests implements ITestListener {
@Override
public void onTestStart(ITestResult result) {
test = extent.createTest(result.getMethod().getMethodName());
}
@Override
public void onTestSuccess(ITestResult result) {
test.log(Status.PASS, "Test Passed");
}
@Override
public void onTestFailure(ITestResult result) {
test.fail(result.getThrowable());
}
@Override
public void onFinish(ITestContext context) {
extent.flush();
}
}
myTest.java
package test;
import base.baseTests;
import com.aventstack.extentreports.ExtentTest;
import com.aventstack.extentreports.Status;
import org.testng.Assert;
import org.testng.annotations.Test;
import pages.*;
public class myTest extends baseTests {
@Test
public void test1(){
// Some test code
test.log(Status.PASS, "Some test step");
// Assert statement
}
Stack trace
java.lang.NullPointerException: Cannot invoke "com.aventstack.extentreports.ExtentTest.log(com.aventstack.extentreports.Status, String)" because "this.test" is null
at test.myTest.test1(myTest.java:15)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:133)
at org.testng.internal.TestInvoker.invokeMethod(TestInvoker.java:598)
at org.testng.internal.TestInvoker.invokeTestMethod(TestInvoker.java:173)
at org.testng.internal.MethodRunner.runInSequence(MethodRunner.java:46)
at org.testng.internal.TestInvoker$MethodInvocationAgent.invoke(TestInvoker.java:824)
at org.testng.internal.TestInvoker.invokeTestMethods(TestInvoker.java:146)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:146)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:128)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.testng.TestRunner.privateRun(TestRunner.java:794)
at org.testng.TestRunner.run(TestRunner.java:596)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:377)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:371)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:332)
at org.testng.SuiteRunner.run(SuiteRunner.java:276)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:53)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:96)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1212)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1134)
at org.testng.TestNG.runSuites(TestNG.java:1063)
at org.testng.TestNG.run(TestNG.java:1031)
at com.intellij.rt.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:66)
at com.intellij.rt.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:109)
I just needed to make ExtentTest static. Now the tests steps get logged to the tests just as I wanted.
public static ExtentTest test;