Skip to main content

Quality Assurance

Concurrency in Extent Reports for Parallel Testing: ThreadLocal to the Rescue!

Learning from collaboration

Modern automation frameworks greatly benefit from parallel test execution. However, it can introduce complexities when dealing with shared resources like extent reports. Running tests in parallel can lead to chaos in the results, as multiple tests might update the same report simultaneously. This blog tackles a common hurdle: how to ensure thread safety in Extent Reports during parallel Selenium testing using the ThreadLocal class.

The Problem: Clash of the Tests

Extent Reports provide beautiful and detailed test reports, but when running tests in parallel, several issues arise:

  • Overwritten Reports: One test might overwrite another’s report data, leading to inaccurate or incomplete results.
  • Mixed-Up Steps: With multiple threads, test steps from different tests could get jumbled within the report, creating confusion.

Using ThreadLocal to Solve Concurrency Problems

ThreadLocal is a Java class that provides thread-local variables. Each thread accessing the variable has its own independently initialized copy of the variable. This makes ThreadLocal an ideal solution for managing resources that are specific to a thread, such as Extent Test instances.

Here’s how ThreadLocal helps tame concurrency in Extent Reports:

  1. Thread-Specific Storage: Each thread running a test case gets its own copy of the ExtentTest object within the ThreadLocal variable.
  2. Isolated Updates: Tests update their own ExtentTest object without affecting others running concurrently.
  3. Clean Reports: After the test finishes, its specific ExtentTest object is used to generate a clear and organized report.

Implementing ThreadLocal with Extent Reports:

Let’s see how to implement ThreadLocal with Extent Reports and Selenium for parallel testing; below is the step-by-step code explanation of the process:

public class ListenersClass implements ITestListener {

    // Path for the report file
    String path = System.getProperty("user.dir") + "\\reports\\index.html";

    // Create an ExtentSparkReporter for the report file configuration
    ExtentSparkReporter reporter = new ExtentSparkReporter(path);
    reporter.config().setReportName("webAutomationRes");
    reporter.config().setDocumentTitle("Test Result");

    // Create an ExtentReports object and attach the reporter
    ExtentReports extent = new ExtentReports();
    extent.attachReporter(reporter);
    extent.setSystemInfo("Tester", "Mohim");

    //The extentTest object is created to manage the ExtentTest instances for each test method in your test suite. 
    //ExtentTest is a class provided by the ExtentReports library that represents a test in your test report.
    
    ExtentTest test;

    // ThreadLocal object to store the ExtentTest object for each thread
    ThreadLocal<ExtentTest> extentTest = new ThreadLocal<ExtentTest>();

    public void onTestStart(ITestResult result) {
        
        // Create a new test in the ExtentReports and assign it to the test variable
        test = extent.createTest(result.getMethod().getMethodName());
        
        // Store the test object in the ThreadLocal object, mapping it to the unique thread ID
        extentTest.set(test);
    }

    public void onTestSuccess(ITestResult result) {
        // Log a pass status for the test
        extentTest.get().log(Status.PASS, "test passed");
    }

    public void onTestFailure(ITestResult result) {
        // Log a fail status for the test
        test.log(Status.FAIL, "test failed");

        // Retrieve the driver object from the test result to take a screenshot
        try {
            driver = (WebDriver) result.getTestClass().getRealClass().getField("driver").get(result.getInstance());
        } catch (Exception e1) {
            e1.printStackTrace();
        }

        // TakeScreenshot code
    }

    public void onFinish(ITestResult result) {
        // Flush the ExtentReports to write the report to the file
        extent.flush();
    }

}

This code implements the ITestListener interface in TestNG, allowing you to listen to test events such as test start, success, failure, and test finish. The ExtentReports and ExtentTest classes are from the ExtentReports library, which generates HTML reports in Selenium testing.

Explanation:

  1. A ThreadLocal variable “test” is created to store the ExtentTest object.
  2. In onTestStart, a new ExtentTest object is created based on the test case name and stored in the test.
  3. Subsequent methods like onTestSuccess and onTestFailure access and update the ExtentTest object specific to the current thread.
  4. In onFinish, the report is flushed to generate the final report with each test’s information.

Three main classes from the ExtentReports library

  1. ExtentSparkReporter: This class creates an HTML report file for your test results. It allows you to customize the report’s appearance, such as setting the report name and document title. In your code, you create an instance of ExtentSparkReporter and attach it to your ExtentReports object to generate the HTML report file.
  2. ExtentReports: This class is the main reporting class in ExtentReports. It is used to create and manage the overall test report. You can attach one or more ExtentSparkReporter objects to an ExtentReports object to generate different types of reports (e.g., HTML, PDF). In your code, you are creating an instance of ExtentReports and attaching the ExtentSparkReporter to it.
  3. ExtentTest: This class represents a test in your test report. You create an instance of ExtentTest for each test method in your test suite. You can use the ExtentTest object to log test steps, pass or fail a test, add screenshots, and more. In your code, you are creating a ThreadLocal object to store a unique instance of ExtentTest for each test method running in parallel. This ensures that each test method has its own ExtentTest instance and prevents concurrency issues when updating the Extent report.

Additional Considerations

  • Proper Flushing: Ensure the extent report is flushed appropriately to capture all test data.
  • Thread-Safe ExtentReports Generator: If you’re using a custom ExtentReports generator class, make sure it’s thread-safe to handle concurrent report creation.
  • Parallel Execution Configuration: For this approach to be effective, configure your TestNG suite or framework to run tests in parallel.

Conclusion

In this blog, we learned about using the ThreadLocal class for concurrency and different classes of ExtentReport. By utilizing ThreadLocal, you may successfully handle the concurrency problems that occur while utilizing Extent Reports Library with concurrent test execution in Selenium. This technique guarantees accurate and well-organized reports, greatly enhancing your test analysis and debugging efforts. Remember that solid automation frameworks require an understanding of concurrency. So, harness the power of ThreadLocal to overcome your parallel testing issues!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Himanshu Pawar

Himanshu Pawar works in Quality assurance at Perficient, based out of India. He is currently working on Adobe technologies. Himanshu is a technology enthusiast passionate about automation and automation tools. He constantly seeks opportunities to learn and explore new technologies.

More from this Author

Categories
Follow Us