TestNG Listeners
TestNG listeners are callback interfaces that let you “listen” to TestNG’s internal events (test start, success, failure, suite start/end, method invocation, etc.) and plug in custom behavior—logging, reporting, retry logic, data transformation, and more. You register listeners either via the @Listeners annotation on your test classes or in your testng.xml.
Below is an overview of the most common listener types, what they do, and a minimal implementation pattern for each.
1. ITestListener #
Fires events around individual test methods (@Test).
- Key callbacks:
- onTestStart(ITestResult result)
- onTestSuccess(ITestResult result)
- onTestFailure(ITestResult result)
- onTestSkipped(ITestResult result)
- onStart(ITestContext context) / onFinish(ITestContext context)
Example #
public class MyTestListener implements ITestListener {
@Override
public void onTestStart(ITestResult result) {
System.out.println(“>> TEST START: ” + result.getMethod().getMethodName());
}
@Override
public void onTestSuccess(ITestResult result) {
System.out.println(“>> TEST PASS: ” + result.getMethod().getMethodName());
}
@Override
public void onTestFailure(ITestResult result) {
System.out.println(“>> TEST FAIL: ” + result.getMethod().getMethodName());
}
// implement other methods as needed…
}
Register via annotation:
@Listeners(MyTestListener.class)
public class MyTests { … }
2. IReporter #
Runs after all suites have executed to generate a custom summary report.
- Key callback:
void generateReport(List<XmlSuite> xmlSuites,
List<ISuite> suites,
String outputDirectory);
Example #
public class MyReporter implements IReporter {
@Override
public void generateReport(List<XmlSuite> xmlSuites,
List<ISuite> suites,
String outputDir) {
// iterate suites → results, output custom HTML / CSV / JSON
}
}
3. ISuiteListener #
Hooks at suite level (across all <test> tags).
- onStart(ISuite suite)
- onFinish(ISuite suite)
Example #
public class MySuiteListener implements ISuiteListener {
@Override
public void onStart(ISuite suite) {
System.out.println(“>> SUITE START: ” + suite.getName());
}
@Override
public void onFinish(ISuite suite) {
System.out.println(“>> SUITE END: ” + suite.getName());
}
}
4. IInvokedMethodListener #
Intercepts every TestNG-invoked method—@Before*, @Test, @After*.
- beforeInvocation(IInvokedMethod method, ITestResult testResult)
- afterInvocation(IInvokedMethod method, ITestResult testResult)
Example #
public class MyInvokeListener implements IInvokedMethodListener {
@Override
public void beforeInvocation(IInvokedMethod im, ITestResult tr) {
System.out.println(“BEFORE: ” +
im.getTestMethod().getMethodName());
}
@Override
public void afterInvocation(IInvokedMethod im, ITestResult tr) {
System.out.println(“AFTER: ” +
im.getTestMethod().getMethodName());
}
}
5. IHookable #
Allows you to wrap the invocation of @Test methods, controlling whether—and how—they actually execute.
- void run(IHookCallBack callBack, ITestResult testResult)
Example #
public class MyHookable implements IHookable {
@Override
public void run(IHookCallBack cb, ITestResult tr) {
// before
System.out.println(“HOOK before ” + tr.getMethod().getMethodName());
cb.runTestMethod(tr); // actually invoke the test
// after
System.out.println(“HOOK after ” + tr.getMethod().getMethodName());
}
}
6. IConfigurationListener #
Fires for configuration methods (@BeforeClass, @AfterMethod, etc.).
- onConfigurationSuccess(ITestResult)
- onConfigurationFailure(ITestResult)
- onConfigurationSkip(ITestResult)
Example #
public class MyConfigListener implements IConfigurationListener {
@Override
public void onConfigurationSuccess(ITestResult tr) {
System.out.println(“CONFIG PASS: ” + tr.getMethod());
}
@Override
public void onConfigurationFailure(ITestResult tr) {
System.out.println(“CONFIG FAIL: ” + tr.getMethod());
}
// …
}
7. IAnnotationTransformer #
Dynamically modify annotations at runtime—e.g. set timeouts, priorities, retry analyzers—without changing test code.
- transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod)
Example #
public class MyTransformer implements IAnnotationTransformer {
@Override
public void transform(ITestAnnotation ann,
Class testClass,
Constructor testConstructor,
Method testMethod) {
if (ann.getRetryAnalyzer() == null) {
ann.setRetryAnalyzer(MyRetryAnalyzer.class);
}
}
}
8. IExecutionListener #
Hooks at the very start and end of the entire TestNG run.
- onExecutionStart()
- onExecutionFinish()
Example #
public class MyExecutionListener implements IExecutionListener {
@Override
public void onExecutionStart() {
System.out.println(“>> TESTNG START”);
}
@Override
public void onExecutionFinish() {
System.out.println(“>> TESTNG FINISH”);
}
}
9. IMethodInterceptor #
Intercepts the list of test methods to be executed, letting you re‐order, filter, or augment them.
- List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context)
Example #
public class MyInterceptor implements IMethodInterceptor {
@Override
public List<IMethodInstance> intercept(List<IMethodInstance> methods,
ITestContext ctx) {
// filter out all tests named “skipMe”
return methods.stream()
.filter(m -> !m.getMethod().getMethodName().equals(“skipMe”))
.collect(Collectors.toList());
}
}
10. IConfigurable #
(rarely used) Allows you to dynamically configure the parameters for configuration methods.
- boolean runConfigurationMethod(IMethodInstance mi, ITestResult testResult)
You can decide at runtime whether a @BeforeMethod, @AfterClass, etc., should actually run.
Registering Listeners #
Via testng.xml:
<suite name=”MySuite”>
<listeners>
<listener class-name=”com.example.listeners.MyTestListener”/>
<listener class-name=”com.example.listeners.MyReporter”/>
<!– etc. –>
</listeners>
</suite>
Via @Listeners annotation:
@Listeners({MyTestListener.class, MyReportListener.class})
public class MyTestClass { … }
By implementing the interfaces relevant to your needs—and registering them—you can hook custom logic into virtually every stage of TestNG’s execution lifecycle, from the moment your suite starts to the final report generation.