</>

Technology

TestNG

Difficulty

Advanced

Interview Question

What is IReporter in TestNG and how do you create a custom report?

Answer

IReporter in TestNG

IReporter is called once after the entire suite finishes. It receives the complete test results and lets you generate any output format — CSV, JSON, email, custom HTML.

Implement IReporter

Java
import org.testng.IReporter;
import org.testng.ISuite;
import org.testng.ISuiteResult;
import org.testng.ITestContext;
import org.testng.ITestNGMethod;
import org.testng.xml.XmlSuite;

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

public class CustomCSVReporter implements IReporter {

    @Override
    public void generateReport(List<XmlSuite> xmlSuites,
                               List<ISuite> suites,
                               String outputDirectory) {

        StringBuilder sb = new StringBuilder();
        sb.append("TestName,Status,Duration(ms),ClassName\n");

        for (ISuite suite : suites) {
            Map<String, ISuiteResult> results = suite.getResults();

            for (ISuiteResult suiteResult : results.values()) {
                ITestContext context = suiteResult.getTestContext();

                // Passed tests
                context.getPassedTests().getAllResults().forEach(result -> {
                    sb.append(result.getName()).append(",PASS,")
                      .append(result.getEndMillis() - result.getStartMillis()).append(",")
                      .append(result.getTestClass().getName()).append("\n");
                });

                // Failed tests
                context.getFailedTests().getAllResults().forEach(result -> {
                    sb.append(result.getName()).append(",FAIL,")
                      .append(result.getEndMillis() - result.getStartMillis()).append(",")
                      .append(result.getTestClass().getName()).append("\n");
                });

                // Skipped tests
                context.getSkippedTests().getAllResults().forEach(result -> {
                    sb.append(result.getName()).append(",SKIP,0,")
                      .append(result.getTestClass().getName()).append("\n");
                });
            }
        }

        // Write to file
        try {
            String filePath = outputDirectory + "/custom-report.csv";
            new File(outputDirectory).mkdirs();
            try (FileWriter fw = new FileWriter(filePath)) {
                fw.write(sb.toString());
            }
            System.out.println("Custom CSV report generated: " + filePath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Register in testng.xml

XML
<suite name="Suite">
    <listeners>
        <listener class-name="reporters.CustomCSVReporter"/>
    </listeners>
    <test name="Tests">
        <classes><class name="tests.LoginTest"/></classes>
    </test>
</suite>

Generate Summary Statistics

Java
@Override
public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outDir) {
    int passed = 0, failed = 0, skipped = 0;

    for (ISuite suite : suites) {
        for (ISuiteResult result : suite.getResults().values()) {
            ITestContext ctx = result.getTestContext();
            passed  += ctx.getPassedTests().size();
            failed  += ctx.getFailedTests().size();
            skipped += ctx.getSkippedTests().size();
        }
    }

    int total = passed + failed + skipped;
    double passRate = total > 0 ? (double) passed / total * 100 : 0;

    System.out.println("========= Test Summary =========");
    System.out.printf("Total:   %d%n", total);
    System.out.printf("Passed:  %d (%.1f%%)%n", passed, passRate);
    System.out.printf("Failed:  %d%n", failed);
    System.out.printf("Skipped: %d%n", skipped);
    System.out.println("================================");
}

IReporter vs ITestListener

InterfaceWhen CalledScopeUse For
ITestListenerDuring execution (per test)Real-timeLive logging, ExtentReports
IReporterAfter entire suitePost-executionFinal CSV/JSON/email reports

Follow AutomateQA

Related Topics