How to Set Up Extent Reports with ExtentReportManager for HTML Test Reports in anhtester/automationframeworkselenium

The anhtester/automationframeworkselenium repository provides a ready-to-use ExtentReportManager that integrates ExtentReports with TestNG via a custom listener to generate thread-safe HTML test reports with screenshots and metadata.

The anhtester/automationframeworkselenium framework ships with a built-in reporting architecture that simplifies setting up Extent Reports with ExtentReportManager for HTML test reports. This implementation abstracts the ExtentReports API into manageable components that handle initialization, thread-safe test logging, and automatic HTML generation without requiring boilerplate code in your test classes.

Core Architecture Components

The framework implements a three-layer architecture to manage ExtentReports lifecycle and thread safety.

ExtentReportManager

The ExtentReportManager class in src/main/java/com/anhtester/reports/ExtentReportManager.java serves as the central utility that creates the singleton ExtentReports instance. It configures the Spark HTML reporter, sets document titles, captures screenshots as Base64, assigns authors and categories, and handles the final flush operation that writes the HTML file to disk.

ExtentTestManager

The ExtentTestManager class in src/main/java/com/anhtester/reports/ExtentTestManager.java maintains a ThreadLocal<ExtentTest> variable. This design ensures that each test method running in parallel execution receives its own isolated ExtentTest object, preventing race conditions when multiple threads log simultaneously.

TestListener

The TestListener class in src/test/java/com/anhtester/listeners/TestListener.java implements TestNG's ITestListener interface. This listener wires the manager into the test lifecycle by triggering initialization on suite start, creating test entries when methods begin, logging results after execution, and flushing reports when the suite finishes.

Maven Dependency Configuration

The project declares the ExtentReports dependency in pom.xml using version 5.1.2. No additional configuration is required unless upgrading the library.

<dependency>
    <groupId>com.aventstack</groupId>
    <artifactId>extentreports</artifactId>
    <version>${extentreports.version}</version>
</dependency>

The property extentreports.version is defined in the properties section of pom.xml. Update this value to upgrade to newer ExtentReports releases.

Configuring Report Paths and Behavior

All report configuration resides in FrameworkConstants (src/main/java/com/anhtester/constants/FrameworkConstants.java), which reads values from config.properties at startup. Modify these settings in src/main/resources/config.properties:

  • EXTENT_REPORT_FOLDER – Directory where HTML reports are written (e.g., reports/ExtentReports/)
  • EXTENT_REPORT_NAME – Base filename without extension (e.g., ExtentReport)
  • OVERRIDE_REPORTS – Set to "yes" to overwrite the same file on each run, or "no" to generate timestamped files
  • OPEN_REPORTS_AFTER_EXECUTION – Set to "yes" to automatically open the HTML report in the default browser after test completion
  • SCREENSHOT_PASSED_TCS, SCREENSHOT_FAILED_TCS, SCREENSHOT_SKIPPED_TCS – Enable screenshots for specific test statuses by setting to "yes"

Initializing the Extent Report

The framework initializes the report automatically when the TestListener triggers. The onStart() method invokes:

ExtentReportManager.initReports();

This method creates the ExtentReports instance, instantiates an ExtentSparkReporter with the configured theme and document title, attaches system information (framework name, author, environment), and stores the output file path in a private static variable for later flushing.

Creating Thread-Safe Test Entries

When each test method begins execution, the listener's onTestStart() method creates a dedicated test entry:

ExtentReportManager.createTest(iTestResult.getName());

You can enrich test metadata immediately after creation:

ExtentReportManager.addAuthors(getAuthorType(iTestResult));
ExtentReportManager.addCategories(getCategoryType(iTestResult));
ExtentReportManager.addDevices();
ExtentReportManager.info(BrowserInfoUtils.getOSInfo());

These calls delegate to ExtentTestManager.setExtentTest(), which stores the ExtentTest object in a thread-local variable, ensuring isolated logging for parallel test execution.

Logging Steps and Capturing Screenshots

Use the static helper methods from ExtentReportManager anywhere in your test code to append log entries and visual evidence:

Method Usage
logMessage(String msg) General informational logging
logMessage(Status status, String msg) Log with explicit status (PASS, FAIL, WARNING)
pass(String msg) / fail(String msg) / skip(String msg) Shorthand for status-specific logging
addScreenShot(Status status, String name) Captures Base64 screenshot from the Selenium WebDriver and attaches it to the current step
addScreenShot(String name) Captures screenshot with INFO status
info(Markup markup) Adds rich HTML content like tables or code blocks

Screenshot capture respects the configuration flags set in config.properties. When enabled, the framework automatically captures the browser state and embeds it directly into the HTML report using Base64 encoding to ensure portability.

Flushing and Opening the Final Report

When the test suite completes, the listener's onFinish() method finalizes the report:

ExtentReportManager.flushReports();
ReportUtils.openReports(link);

The flushReports() method writes all accumulated data to the HTML file, closes the ExtentReports instance, and calls ExtentTestManager.unload() to clear thread-local storage. If OPEN_REPORTS_AFTER_EXECUTION is enabled, the generated HTML file opens automatically in the system default browser.

Complete Working Example

The following minimal test class demonstrates the integration. Because TestListener handles the lifecycle automatically, you only write logging statements:

import com.anhtester.reports.ExtentReportManager;
import com.aventstack.extentreports.Status;
import org.testng.annotations.Test;

public class LoginTest {

    @Test
    public void verifyValidLogin() {
        // Log navigation step
        ExtentReportManager.logMessage("Navigating to login URL");
        
        // Perform login actions here...
        
        // Attach screenshot after login
        ExtentReportManager.addScreenShot(Status.PASS, "Post-login dashboard");
        
        // Log verification
        ExtentReportManager.pass("Login successful with valid credentials");
    }
}

Ensure your testng.xml registers the listener:

<suite name="Automation Suite">
    <listeners>
        <listener class-name="com.anhtester.listeners.TestListener"/>
    </listeners>
    <test name="Regression Tests">
        <classes>
            <class name="LoginTest"/>
        </classes>
    </test>
</suite>

Summary

  • ExtentReportManager in src/main/java/com/anhtester/reports/ExtentReportManager.java handles singleton instance creation, Spark reporter configuration, and HTML generation.
  • ExtentTestManager maintains thread-local storage via ThreadLocal<ExtentTest> to support parallel test execution safely.
  • TestListener automates the entire lifecycle from initialization through flushing without requiring manual setup in test classes.
  • Configuration is centralized in FrameworkConstants and driven by config.properties values for report paths, naming conventions, and screenshot behavior.
  • Screenshots are captured as Base64 and embedded directly into the HTML report to ensure single-file portability.
  • The framework supports automatic report opening post-execution via the OPEN_REPORTS_AFTER_EXECUTION property.

Frequently Asked Questions

How do I enable screenshots only for failed test cases?

Set the property SCREENSHOT_FAILED_TCS=yes in src/main/resources/config.properties, and ensure SCREENSHOT_PASSED_TCS and SCREENSHOT_SKIPPED_TCS are set to no. The ExtentReportManager checks these flags before invoking the screenshot capture logic in addScreenShot().

Can I run tests in parallel without mixing log entries?

Yes. The ExtentTestManager class uses a ThreadLocal<ExtentTest> variable to isolate each thread's ExtentTest instance. When createTest() is called, the manager stores the test object in thread-local storage, ensuring that parallel test methods write to their respective report nodes without interference.

Where is the final HTML report file located?

The report writes to the directory specified by EXTENT_REPORT_FOLDER in config.properties, typically under reports/ExtentReports/. If OVERRIDE_REPORTS is set to no, the filename includes a timestamp prefix (e.g., 20240115_143022_ExtentReport.html). The exact path is constructed in ExtentReportManager.initReports() using FrameworkConstants.EXTENT_REPORT_FOLDER_PATH.

How do I add custom system information to the report header?

Modify the initReports() method in ExtentReportManager.java or extend the manager to call extentReports.setSystemInfo(key, value) before the suite starts. Common additions include build numbers, test environments, or browser versions captured via BrowserInfoUtils.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →