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 vid 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.