Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Generating Test Reports with TestNG in Java Automation Testing

Tech 3

Using TestNG's Built-in Repotrers

To generate TestNG's default reports, configure the execution settings in your IDE. In the Run/Debug configurations, select the test file and enable the "Use default reporters" option in the Listeners section. When executing a testng.xml file, TestNG automatically creates a folder named test-output in the project structure. This folder contains the generated test reports and associated data files from the test run.

ZTestReport for Custom Reporting

ZTestReport is a custom reporting tool similar to BeautifulReport in Python. There are two methods to integrate it into your TestNG setup.

Method 1: Menual Integration

Add the required dependency to your project's pom.xml file:

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.0</version>
</dependency>

Place the ZTestReport Java files and template files in your project, typically within a utility package. Adjust the paths in the ZTestReport files to point to the correct locations for the template and report generation. Add the ZTestReport listener to your test class and remove any existing report listeners from the testng.xml file. Execute the testng.xml file to produce the custom report.

Method 2: XML Configuration

Alternatively, add the ZTestReport listener directly in the testng.xml file by specifying the class and method names. After adding the listener, run the testng.xml file to generate the report. Both methods yield identical ZTestReport outputs.

ZTestReport templates are available for download from its GitHub repository.

ExtentReports for Advanced Reporting

ExtentReports provides a more feature-rich reporting solution. Follow these steps to set it up.

Step 1: Add Dependencies

Include the necessary dependencies in your Maven project's pom.xml:

<dependencies>
    <dependency>
        <groupId>com.relevantcodes</groupId>
        <artifactId>extentreports</artifactId>
        <version>2.41.1</version>
    </dependency>
    <dependency>
        <groupId>com.vimalselvam</groupId>
        <artifactId>testng-extentsreport</artifactId>
        <version>1.3.1</version>
    </dependency>
    <dependency>
        <groupId>com.aventstack</groupId>
        <artifactId>extentreports</artifactId>
        <version>3.0.6</version>
    </dependency>
</dependencies>

Step 2: Implement a Custom Listneer

Create a listener class that implements the IReporter interface to monitor test outcomes and generate reports. Here is a restructured example:

package util;

import com.aventstack.extentreports.ExtentReports;
import com.aventstack.extentreports.ExtentTest;
import com.aventstack.extentreports.ResourceCDN;
import com.aventstack.extentreports.Status;
import com.aventstack.extentreports.model.TestAttribute;
import com.aventstack.extentreports.reporter.ExtentHtmlReporter;
import com.aventstack.extentreports.reporter.configuration.ChartLocation;
import com.aventstack.extentreports.reporter.configuration.Theme;
import org.testng.*;
import org.testng.xml.XmlSuite;

import java.io.File;
import java.util.*;

public class CustomExtentReporter implements IReporter {
    private static final String REPORT_DIR = "test-output/";
    private static final String REPORT_FILE = "extent-report.html";
    private ExtentReports report;

    @Override
    public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDir) {
        initializeReport();
        boolean multiSuite = suites.size() > 1;
        for (ISuite suite : suites) {
            Map<String, ISuiteResult> results = suite.getResults();
            if (results.isEmpty()) continue;
            int totalPass = 0, totalFail = 0, totalSkip = 0;
            ExtentTest suiteNode = null;
            if (multiSuite) {
                suiteNode = report.createTest(suite.getName()).assignCategory(suite.getName());
            }
            boolean multiResult = results.size() > 1;
            for (ISuiteResult suiteResult : results.values()) {
                ITestContext context = suiteResult.getTestContext();
                ExtentTest resultNode;
                if (multiResult) {
                    resultNode = (suiteNode == null) ? report.createTest(context.getName()) : suiteNode.createNode(context.getName());
                } else {
                    resultNode = suiteNode;
                }
                if (resultNode != null) {
                    resultNode.getModel().setName(suite.getName() + " : " + context.getName());
                    resultNode.assignCategory(context.getName());
                    resultNode.getModel().setStartTime(context.getStartDate());
                    resultNode.getModel().setEndTime(context.getEndDate());
                    int passCount = context.getPassedTests().size();
                    int failCount = context.getFailedTests().size();
                    int skipCount = context.getSkippedTests().size();
                    totalPass += passCount;
                    totalFail += failCount;
                    totalSkip += skipCount;
                    if (failCount > 0) {
                        resultNode.getModel().setStatus(Status.FAIL);
                    }
                    resultNode.getModel().setDescription(String.format("Passed: %d; Failed: %d; Skipped: %d", passCount, failCount, skipCount));
                }
                addTestResults(resultNode, context.getFailedTests(), Status.FAIL);
                addTestResults(resultNode, context.getSkippedTests(), Status.SKIP);
                addTestResults(resultNode, context.getPassedTests(), Status.PASS);
            }
            if (suiteNode != null) {
                suiteNode.getModel().setDescription(String.format("Total Passed: %d; Total Failed: %d; Total Skipped: %d", totalPass, totalFail, totalSkip));
                if (totalFail > 0) {
                    suiteNode.getModel().setStatus(Status.FAIL);
                }
            }
        }
        report.flush();
    }

    private void initializeReport() {
        File dir = new File(REPORT_DIR);
        if (!dir.exists() && !dir.isDirectory()) {
            dir.mkdir();
        }
        ExtentHtmlReporter htmlReporter = new ExtentHtmlReporter(REPORT_DIR + REPORT_FILE);
        htmlReporter.config().setResourceCDN(ResourceCDN.EXTENTREPORTS);
        htmlReporter.config().setDocumentTitle("API Test Report");
        htmlReporter.config().setReportName("API Automation Results");
        htmlReporter.config().setChartVisibilityOnOpen(true);
        htmlReporter.config().setTestViewChartLocation(ChartLocation.TOP);
        htmlReporter.config().setTheme(Theme.STANDARD);
        htmlReporter.config().setCSS(".node.level-1 ul{ display:none;} .node.level-1.active ul{display:block;}");
        report = new ExtentReports();
        report.attachReporter(htmlReporter);
        report.setReportUsesManualConfiguration(true);
    }

    private void addTestResults(ExtentTest parentNode, IResultMap testMap, Status resultStatus) {
        String[] categories = new String[0];
        if (parentNode != null) {
            List<TestAttribute> attrList = parentNode.getModel().getCategoryContext().getAll();
            categories = new String[attrList.size()];
            for (int i = 0; i < attrList.size(); i++) {
                categories[i] = attrList.get(i).getName();
            }
        }
        if (testMap.size() > 0) {
            Set<ITestResult> sortedResults = new TreeSet<>(Comparator.comparingLong(ITestResult::getStartMillis));
            sortedResults.addAll(testMap.getAllResults());
            for (ITestResult result : sortedResults) {
                StringBuilder paramName = new StringBuilder();
                for (Object param : result.getParameters()) {
                    paramName.append(param.toString());
                }
                String testName = paramName.length() > 0 ? (paramName.length() > 50 ? paramName.substring(0, 49) + "..." : paramName.toString()) : result.getMethod().getMethodName();
                ExtentTest testNode = (parentNode == null) ? report.createTest(testName) : parentNode.createNode(testName).assignCategory(categories);
                for (String group : result.getMethod().getGroups()) {
                    testNode.assignCategory(group);
                }
                for (String log : Reporter.getOutput(result)) {
                    testNode.debug(log);
                }
                if (result.getThrowable() != null) {
                    testNode.log(resultStatus, result.getThrowable());
                } else {
                    testNode.log(resultStatus, "Test " + resultStatus.toString().toLowerCase() + "ed");
                }
                testNode.getModel().setStartTime(new Date(result.getStartMillis()));
                testNode.getModel().setEndTime(new Date(result.getEndMillis()));
            }
        }
    }
}

Step 3: Configure TestNG XML

Add the listener class path to your testng.xml file. Execute the testng.xml file, and a test-output folder will be generated containing an HTML report named extent-report.html, wich can be viewed in a browser.

Tags: JavaTestNG

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.