TestNG Listeners are used to inspect and modify the testing behavior. TestNG listeners always extend org.testng.ITestNGListener
marker interface. TestNG listeners can be defined for a test class using org.testng.annotations.Listeners
annotation.
TestNG Listeners
There are many listeners interfaces provided by TestNG. They all extend org.testng.ITestNGListener
interface.
Let’s look at some of the important TestNG listeners.
ISuiteListener
: We can use this test suite listener to perform some operations when test suite starts and when all the tests are executed. This interface contains two methods –onStart(ISuite suite)
andonFinish(ISuite suite)
and provides access to test suite object.ITestListener
: We can use this listener to analyze test methods, perform logging. We can also use them to send notifications if any test fails by implementingonTestFailure(ITestResult result)
method.IAnnotationTransformer
: We can implement this interface to modify the annotations for any@Test
method. Note that we can use this annotation only with TestNG XML configuration.IAnnotationTransformer2
: We can implement this interface to modify the annotations for any method other than@Test
method.This annotation can be used with TestNG XML configuration only.IConfigurable
: If a test class implements this interface, its run() method will be invoked instead of each configuration method found.IConfigurationListener
: Listener interface for events related to configuration methods.IExecutionListener
: This listener is used to monitor when a TestNG run starts and ends.IHookable
: If a test class implements this interface, its run() method will be invoked instead of each @Test method found.IInvokedMethodListener
: A listener that gets invoked before and after a method is invoked by TestNG.IMethodInterceptor
: This class is used to alter the list of test methods that TestNG is about to run.IReporter
: This interface can be implemented by clients to generate a report.
TestNG Listener Example
Let’s create a simple TestNG test class, then we will implement few listeners and add it to the class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
package com.journaldev.listeners; import org.testng.annotations.DataProvider; import org.testng.annotations.Listeners; import org.testng.annotations.Test; public class Test3 { @Test public void test() { System.out.println("Test3 test method"); } @Test(dataProvider = "dp") public void testString(String s) { System.out.println("Test3 testString method, input = "+s); } @DataProvider public Object[] dp() { return new Object[] {"A", "B"}; } } |
When we run above as TestNG test, we get the following output in the console.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
[RemoteTestNG] detected TestNG version 6.14.3 Test3 test method Test3 testString method, input = A Test3 testString method, input = B PASSED: test PASSED: testString("A") PASSED: testString("B") =============================================== Default test Tests run: 3, Failures: 0, Skips: 0 =============================================== =============================================== Default suite Total tests run: 3, Failures: 0, Skips: 0 =============================================== |
ISuiteListener Example
Here is a simple implementation of ISuiteListener interface.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package com.journaldev.listeners; import org.testng.ISuite; import org.testng.ISuiteListener; public class Test3SuiteListener implements ISuiteListener { @Override public void onStart(ISuite suite) { System.out.println("TestNG suite default output directory = "+suite.getOutputDirectory()); } @Override public void onFinish(ISuite suite) { System.out.println("TestNG invoked methods = " +suite.getAllInvokedMethods()); } } |
ITestListener Example
Here is a simple implementation of ITestListener interface.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
package com.journaldev.listeners; import org.testng.ITestContext; import org.testng.ITestListener; import org.testng.ITestResult; public class Test3TestListener implements ITestListener{ public Test3TestListener() { System.out.println("Test3Listener constructor"); } @Override public void onTestStart(ITestResult result) { System.out.println("Test Started. "+result.getStartMillis()); } @Override public void onTestSuccess(ITestResult result) { System.out.println("Test Success. "+result.getEndMillis()); } @Override public void onTestFailure(ITestResult result) { System.out.println("Test Failed. "+result.getTestName()); } @Override public void onTestSkipped(ITestResult result) { System.out.println("Test Skipped. "+result.getTestName()); } @Override public void onTestFailedButWithinSuccessPercentage(ITestResult result) { } @Override public void onStart(ITestContext context) { System.out.println("Context Name = "+context.getName()); } @Override public void onFinish(ITestContext context) { System.out.println(context.getPassedTests()); } } |
Now modify the Test3
class by adding Listeners to its class definition.
1 2 3 4 5 |
@Listeners({Test3TestListener.class, Test3SuiteListener.class}) public class Test3 { } |
When we run the class again as TestNG test, we get following output.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
[RemoteTestNG] detected TestNG version 6.14.3 Test3Listener constructor TestNG suite default output directory = /Users/pankaj/Documents/eclipse-github/TestNG-Examples/test-output/Default suite Context Name = Default test Test Started. 1527662805150 Test3 test method Test Success. 1527662805159 Test Started. 1527662805163 Test3 testString method, input = A Test Success. 1527662805164 Test Started. 1527662805165 Test3 testString method, input = B Test Success. 1527662805166 [ResultMap map={[TestResult name=test status=SUCCESS method=Test3.test()[pri:0, instance:com.journaldev.listeners.Test3@291caca8] output={null}]=Test3.test()[pri:0, instance:com.journaldev.listeners.Test3@291caca8], [TestResult name=testString status=SUCCESS method=Test3.testString(java.lang.String)[pri:0, instance:com.journaldev.listeners.Test3@291caca8] output={null}]=Test3.testString(java.lang.String)[pri:0, instance:com.journaldev.listeners.Test3@291caca8], [TestResult name=testString status=SUCCESS method=Test3.testString(java.lang.String)[pri:0, instance:com.journaldev.listeners.Test3@291caca8] output={null}]=Test3.testString(java.lang.String)[pri:0, instance:com.journaldev.listeners.Test3@291caca8]}] PASSED: test PASSED: testString("A") PASSED: testString("B") =============================================== Default test Tests run: 3, Failures: 0, Skips: 0 =============================================== TestNG invoked methods = [Test3.test()[pri:0, instance:com.journaldev.listeners.Test3@291caca8] 689745064, Test3.testString(java.lang.String)[pri:0, instance:com.journaldev.listeners.Test3@291caca8]A 689745064, Test3.testString(java.lang.String)[pri:0, instance:com.journaldev.listeners.Test3@291caca8]B 689745064] =============================================== Default suite Total tests run: 3, Failures: 0, Skips: 0 =============================================== |
Summary
TestNG listeners are very powerful in monitoring the test suite and test cases. Some of them can be used to alter the testing behavior at runtime.