Integrating Extent Reports in Your Automation Suite using TestNG Listener

Prasad Patharkar
5 min readJan 18, 2024

--

In the world of test automation, reporting plays a pivotal role in providing insights into the test execution results. Detailed and visually appealing reports not only aid in understanding the test outcomes but also facilitate effective communication among team members. One popular choice for generating interactive and comprehensive reports is Extent Reports, a powerful reporting library for Java and .NET applications. In this article, we’ll delve into the process of integrating Extent Reports into your automation suite for enhanced reporting capabilities.

Step 1: Add a dependency

We need to add dependencies for extent reports, testNG and jackson-databind(to generate json for test summary). For Java projects using Maven, you need to add the Extent Reports dependency to your project’s pom.xml file. If you are using gradle then add the similar dependency in your build.gradle file. In the code snippet below, I have shown the dependency for gradle project.

dependencies {
//Your other project dependecies
implementation('com.aventstack:extentreports:4.0.9')
implementation("org.testng:testng:7.5")
implementation("com.fasterxml.jackson.core:jackson-databind:2.13.3")
}

Step 2: Create ExtentManager.java and ExtentReportListener.java classes

Create package ‘reports’ under src/main/java. Create 2 classes ExtentManager.java and ExtentReportListener.java under this package.

In the ExtentManager.java class in which we will specify

  1. Path where html report should be generated
  2. Load extent-config.xml file configuration to generate the report

In the code snippet below, my HTML report will be generated with name TestExecutionReport.html inside the folder structure /test-output/ExtentReport/

package com.packagename.reports;

import com.aventstack.extentreports.ExtentReports;
import com.aventstack.extentreports.ExtentTest;
import com.aventstack.extentreports.reporter.ExtentHtmlReporter;

public class ExtentManager {

public static ExtentHtmlReporter htmlReporter;
public static ExtentReports extent;
public static ExtentTest test;

public static void setExtent() {
htmlReporter = new ExtentHtmlReporter(
System.getProperty("user.dir") + "/test-output/ExtentReport/"
+ "TestExecutionReport"
+ ".html");
htmlReporter.loadXMLConfig(System.getProperty("user.dir")
+ "/extent-config.xml");

extent = new ExtentReports();
extent.attachReporter(htmlReporter);
}

public static void endReport() {
extent.flush();
}
}

Now create extent-config.xml under src/main/resources and copy the below code to generate report based on styling specified. Note that you can change the report styling by making changes to this file.

<?xml version="1.0" encoding="UTF-8"?>
<extentreports>
<configuration>
<!-- report theme -->
<!-- standard, dark -->
<documentTitle>TestExecutionReport</documentTitle>

<!-- document encoding -->
<!-- defaults to UTF-8 -->
<encoding>UTF-8</encoding>

<!-- protocol for script and stylesheets -->
<!-- defaults to https -->
<protocol>http</protocol>

<!-- title of the document -->
<reportName>Test Execution Report
<![CDATA[
<img src='D:/Workspace_Eclipse/ExtentDemo/Logo/ATI.png'/>
]]>
</reportName>

<!-- report name - displayed at top-nav -->
<scripts>
<![CDATA[
$(document).ready(function() {

});
]]>
</scripts>


<!-- location of charts in the test view -->
<!-- top, bottom -->
<styles>
<![CDATA[
.report-name { padding-left: 18px; } .report-name > img { float:
left;height: 90%;margin-left: 30px;margin-top: 3px;width: auto; }
]]>
</styles>

<!-- custom javascript -->
<testViewChartLocation>bottom</testViewChartLocation>

<!-- custom styles -->
<theme>dark</theme>
</configuration>
</extentreports>

Now create child class of ExtentManager class(created above) and ITestListener interface. Add below code (which is self explanatory) in that class(ExtentReportListener.java in my case). One thing to note is that we are also creating TestExecutionReport.json file inside the folder structure ‘test-output/ExtentReport/’. This file will be helpful for us to get the pass, failed, total test case count etc. and we can use this information while sending msg on MS Teams using Github Actions in future.

package com.packagename.reports;

import com.aventstack.extentreports.Status;
import com.aventstack.extentreports.markuputils.ExtentColor;
import com.aventstack.extentreports.markuputils.MarkupHelper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;

public class ExtentReportListener extends ExtentManager implements ITestListener {

public void onTestStart(ITestResult result) {
test = extent.createTest(result.getName());
}

public void onTestSuccess(ITestResult result) {
if (result.getStatus() == ITestResult.SUCCESS) {
test.log(Status.PASS, "Pass Test case is: " + result.getName());
}
}

public void onTestFailure(ITestResult result) {
if (result.getStatus() == ITestResult.FAILURE) {
test.log(Status.FAIL,
MarkupHelper.createLabel(result.getName() + " - Test Case Failed", ExtentColor.RED));
test.log(Status.FAIL,
MarkupHelper.createLabel(result.getThrowable() + " - Test Case Failed", ExtentColor.RED));
}
}

public void onTestSkipped(ITestResult result) {
if (result.getStatus() == ITestResult.SKIP) {
test.log(Status.SKIP, "Skipped Test case is: " + result.getName());
}
}

public void onTestFailedButWithinSuccessPercentage(ITestResult result) {
test.log(Status.INFO, "Test case failed but within success percentage: " + result.getName());
}

public void onStart(ITestContext context) {
//test.log(Status.INFO, "Test Execution Started");
}

public void onFinish(ITestContext context) {
try {
Map<String, Object> testResult = new HashMap<>();
testResult.put("TotalTestCaseCount", context.getAllTestMethods().length);
testResult.put("PassedTestCaseCount", context.getPassedTests().size());
testResult.put("FailedTestCaseCount", context.getFailedTests().size());
testResult.put("SkippedTestCaseCount", context.getSkippedTests().size());

ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
String filePath = "test-output/ExtentReport/TestExecutionReport.json";
mapper.writeValue(new File(filePath), testResult);
} catch (IOException e) {
throw new RuntimeException("Error occurred while writing to TestExecutionReport.json file: ",
e);
}
}
}

Step 3: Initializing ExtentManager.java

Using the TestNG’s @BeforeSuite annotation call the setExtent() method from ExtentManager class. This will initialize the necessary configuration needed to generate the Extent Report.

Using the TestNG’s @AfterSuite annotation call the endReport() method which will flush the test execution output to HTML file.

Below is the code snippet for your reference:

package com.testpackagename.automationsuite;

import com.packagename.reports.ExtentManager;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;

/**
* This class consists of operations that are supposed to be done before the test case suite begins
*/
public class TestBaseClass {

@BeforeSuite
public void beforeSuite() {
ExtentManager.setExtent();
}

@AfterSuite
public void afterSuite() {
service.shutdown();
ExtentManager.endReport();
}
}

Step 4: Add listener to testNG.xml file

Once we are done with all the above steps most important step is to add the listener in testNG.xml. This will make sure that whatever test file names we have mentioned in testNG.xml file, the ExtentReport will be generated for all the test cases written in those test files. Sample code snippet for that is given below:

<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >
<suite name="Automation-Suite">
<listeners>
<listener
class-name="com.packagename.reports.ExtentReportListener"/>
</listeners>
<test name="Test">
<classes>
<class name="com.testpackagename.automationsuite.TestFunctionalityOne"/>
<class name="com.testpackagename.automationsuite.TestFunctionalityTwo"/>
</classes>
</test>
</suite>

That’s all. We are all set to generate the extent report for our test cases. Once your suite execution completes you can see the report ‘TestExecutionReport.html’ generated under test-output/ExtentReport/ folder. Below is snapshot of report generated for me.

Feel free to comment below if you have any questions or facing any issues. If you would like to see more such articles, feel free to follow me here or on linkedIn. :)

--

--

Prasad Patharkar

Hey, thanks for finding me. I write articles about test automation with an intent to help the QA community. If this interests you, feel free to follow me.