How to customize TestNG result xml
Posted on
TestNG generates a default test-results.xml file after running tests. This file contains details about passed, failed, and skipped tests. However, sometimes we need a customized TestNG result XML to fit specific reporting needs, such as:
- Adding additional information (e.g., execution time, custom messages)
- Changing the XML structure
- Filtering test results
In this blog, we'll learn how to customize the TestNG result XML using a custom IReporter implementation.
Default TestNG result xml
When you run a TestNG suite, it generates an XML report (e.g., test-output/testng-results.xml).
A sample default XML looks like this:
<testng-results> <suite name="MySuite"> <test name="MyTest"> <class name="SampleTest"> <test-method name="testMethod" status="PASS"/> </class> </test> </suite> </testng-results>
Now, let's customize this XML using TestNG's IReporter interface.
Steps to Customize TestNG Result XML
Step 1: Create a Sample Test Class
Create a test class with a simple test case.
import org.testng.annotations.Test; public class SampleTest { @Test public void testMethod1() { System.out.println("Test 1 executed"); } @Test public void testMethod2() { System.out.println("Test 2 executed"); } }
Step 2: Create a Custom IReporter Class
Now, let's implement IReporter to generate a custom XML report.
import org.testng.*; import org.testng.xml.XmlSuite; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.List; public class CustomTestNGReporter implements IReporter { @Override public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) { StringBuilder xmlReport = new StringBuilder(); xmlReport.append("<CustomTestResults>\n"); for (ISuite suite : suites) { xmlReport.append("\t<Suite name=\"").append(suite.getName()).append("\">\n"); for (ISuiteResult result : suite.getResults().values()) { ITestContext context = result.getTestContext(); xmlReport.append("\t\t<Test name=\"").append(context.getName()).append("\">\n"); appendTestResults("PassedTests", context.getPassedTests(), xmlReport); appendTestResults("FailedTests", context.getFailedTests(), xmlReport); appendTestResults("SkippedTests", context.getSkippedTests(), xmlReport); xmlReport.append("\t\t</Test>\n"); } xmlReport.append("\t</Suite>\n"); } xmlReport.append("</CustomTestResults>"); // Write custom XML to a file writeToFile(outputDirectory + "/custom-testng-results.xml", xmlReport.toString()); } private void appendTestResults(String tag, IResultMap results, StringBuilder xmlReport) { xmlReport.append("\t\t\t<").append(tag).append(">\n"); for (ITestResult result : results.getAllResults()) { xmlReport.append("\t\t\t\t<TestMethod name=\"").append(result.getMethod().getMethodName()).append("\" "); xmlReport.append("status=\"").append(result.getStatus()).append("\" "); xmlReport.append("timeTaken=\"").append(result.getEndMillis() - result.getStartMillis()).append("ms\" />\n"); } xmlReport.append("\t\t\t</").append(tag).append(">\n"); } private void writeToFile(String filePath, String content) { try (FileWriter writer = new FileWriter(new File(filePath))) { writer.write(content); } catch (IOException e) { e.printStackTrace(); } } }
Step 3: Add the Custom Reporter in testng.xml
Modify testng.xml to include our custom reporter.
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd"> <suite name="MySuite"> <listeners> <listener class-name="CustomTestNGReporter"/> </listeners> <test name="MyTest"> <classes> <class name="SampleTest"/> </classes> </test> </suite>
Step 4: Run testng.xml
Run your testng.xml or execute it programmatically:
import org.testng.TestNG; import java.util.Arrays; public class RunTestNG { public static void main(String[] args) { TestNG testng = new TestNG(); testng.setTestSuites(Arrays.asList("testng.xml")); testng.run(); } }
Expected Output
TestNG will generate a custom-testng-results.xml file inside the test-output directory.
A sample custom-testng-results.xml output:
<CustomTestResults> <Suite name="MySuite"> <Test name="MyTest"> <PassedTests> <TestMethod name="testMethod1" status="1" timeTaken="3ms"/> </PassedTests> <PassedTests> <TestMethod name="testMethod2" status="1" timeTaken="2ms"/> </PassedTests> </Test> </Suite> </CustomTestResults>