TestNG Listeners – Selenium WebDriver: This post, we are going to discuss the listeners in TestNG as we have discussed many important feature implementation of TestNG. Other, this feature is also the most crucial feature of TestNG. Before start discussing Listeners, let us start What is a listener & different types of Listeners.
What is the Listener?
The listener is defined as an interface that modifies the default behaviour. As the name suggests, listeners “Listen” to the event and keep track of the test execution while performing some action at every stage of test execution by the Selenium WebDriver and Behave accordingly. We can use this by implementing the Listener Interface.
We can also customize the test logs and report according to your project requirements, which helps in setting the proper message in the execution report so that anyone can easily understand by going through that.
There are different types of events present, with the help of those we can generate own events when a test case got failed/pass/ or skipped.
What Is an Event?
An event refers to any action that we perform using Selenium WebDriver like click, type, navigate, etc. this all are termed as Events.
Different Types Of Listeners
Mainly there are two main listeners are available:
- WebDriver Listeners
- TestNg Listeners
We have discussed WebDriver listener briefly in a separate post, and You can read that by following this link.
Now we are going to discuss the TestNg Listeners briefly in Details:
We can use use the TestNg Listeners in Selenium WebDriver at Two Level:
- Class Level: If you want to apply for all the @Test method of a class, then you can define it at the class level.
- Suite Level: If you want to apply the listeners to all class of a specific suite, then you can use at the suite level.
Types Of TestNG Listeners
In TestNG, We Can find many TestNG Listeners. Still, we are going to discuss those listeners who are frequently used by most of the automation testers while writing the automation script using Selenium WebDriver.
So we are going to cover below testNG Listeners in our Post, Those are:
- ITestListener
- IAnnotationTransformer
- IInvokedMethodListener
- ISuiteListener
- IReporter
- IConfigurable
- IExecutionListener
- IHookable
- IMethodInterceptor
- IConfigurationListener
Now let us start with one by one and understand what the use of the above listeners is and how we can implement in our script with some examples.
ITestListener
This is one of the most used TestNG Listeners in selenium WebDriver. To use this listener, you need to implement in your Java class and also need to override all methods which are present inside this interface.
With the help of this listener in Selenium WebDriver, we can change the default behaviour of the test by adding the different methods to the existed methods of that listener interface.
Following are the methods which are present inside the Interface:
- onStart: This method is executed each time before executing any test method.
- onFinish: This method is executed after the execution of all the test methods.
- onTestStart:
- onTestSkipped:
- onTestSuccess:
- onTestFailure:
- onTestFailedButWithinSuccessPercentage:
When you are using ITestListener, and you want to get the details about the result, then you need to pass the following things as the parameter to those methods “ITestResult” interface along with the instance “Result.”
Example:
public void onTestStart(ITestResult result) { System.out.println(“New Test Started” +result.getName()); }
Note: If you want to trace all the exceptions by using ItestResult, then don’t use the try/catch handling in the script.
For getting all the information about the test run, then you need to pass the “ITestContext” interface as a parameter with its instance “context.”
public void onStart(ITestContext context) { System.out.println("This is onStart method" +context.getOutputDirectory()); }
Now let us take a simple example and implement the Listener in Class level. So that the logs will be generated at a console and which will help us to understand which test passed, failed, and skipped.
Steps to Follow:
- Create a Class and implements all the methods of the ITestListener interface.
- Create another class that has your test cases and add the listener, which we created on that.
Listener Implemented Class:
package TestNgListeners; import org.testng.ITestContext; import org.testng.ITestListener; import org.testng.ITestResult; public class ListenersBlog implements ITestListener { public void onTestStart(ITestResult result) { System.out.println("New Test Started" +result.getName()); } public void onTestSuccess(ITestResult result) { System.out.println("Test Successfully Finished" +result.getName()); } public void onTestFailure(ITestResult result) { System.out.println("Test Failed" +result.getName()); } public void onTestSkipped(ITestResult result) { System.out.println("Test Skipped" +result.getName()); } public void onTestFailedButWithinSuccessPercentage(ITestResult result) { System.out.println("Test Failed but within success percentage" +result.getName()); } public void onStart(ITestContext context) { System.out.println("This is onStart method" +context.getOutputDirectory()); } public void onFinish(ITestContext context) { System.out.println("This is onFinish method" +context.getPassedTests()); System.out.println("This is onFinish method" +context.getFailedTests()); } }
We need to create another class, where we can write our test cases which have written inside the Test Methods and add the previously created listener above the class name so that it will be implemented at the class level.
Syntax:
@Listeners(PackageName.ClassName.class)
Test Class:
package TestNgListeners; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.testng.SkipException; import org.testng.annotations.Listeners; import org.testng.annotations.Test; import junit.framework.Assert; @Listeners(TestNgListeners.ListenersBlog.class) public class TestNGListenersTest { @Test //Passing Test public void sampleTest1() throws InterruptedException { System.setProperty("webdriver.chrome.driver", "C:\\Users\\Lenovo-I7\\Desktop\\Selenium\\chromedriver.exe"); WebDriver driver = new ChromeDriver(); driver.get("https://www.apple.com/"); driver.manage().window().maximize(); driver.findElement(By.xpath("//*[@id=\'ac-globalnav\']/div/ul[2]/li[3]")).click(); Thread.sleep(2000); driver.findElement(By.cssSelector("#chapternav > div > ul > li.chapternav-item.chapternav-item-ipad-air > a")).click(); Thread.sleep(2000); driver.findElement(By.linkText("Why iPad")).click(); Thread.sleep(2000); driver.quit(); } @Test //Failing Test public void sampleTest2() throws InterruptedException { System.out.println("Forcely Failed Test Method"); Assert.assertTrue(false); } private int i = 0; @Test(successPercentage = 60, invocationCount = 5) //Test Failing But Within Success Percentage public void sampleTest3() { i++; System.out.println("Test Failed But Within Success Percentage Test Method, invocation count: " + i); if (i == 1 || i == 2) { System.out.println("sampleTest3 Failed"); Assert.assertEquals(i, 6); } } @Test //Skipping Test public void sampleTest4() { throw new SkipException("Forcely skipping the sampleTest4"); } }
Suppose there are multiple classes in your project and you need to add TestNg Listener in all classes then that’s a difficult job, In that case, you can define in Suite Level Like Below:
Testng.xml Sample Code
<suite name="TestNG Listeners Suite" parallel="false"> <listeners> <listener class-name="TestNgListeners.ListenersBlog"></listener> </listeners> <test name="Test"> <classes> <class name="TestNgListeners.TestNGListenersTest"></class> </classes> </test> </suite>
IAnnotationTransformer
IAnnotationTransformer interface has a method “transform,” which is used to modify the TestNG behaviour of @Test method of the test class.
This transform method takes four parameters are those are:
- Annotation: This annotation is used to read from the test class.
- Test class: If this annotation found in a class, then it represents the same class.
- testConstructor: If this annotation found a constructor, then it returns the same constructor.
- testMethod: If this annotation found on a method, then this parameter represents the same method.
Note: At least one of the parameters will be non-null.
Listener Class:
package TestNgListeners; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import org.testng.IAnnotationTransformer; import org.testng.annotations.ITestAnnotation; public class AnnotationTransformers implements IAnnotationTransformer { public boolean isTestRunning(ITestAnnotation ins) { if(ins.getAlwaysRun()) { return true; } return false; } public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) { if(isTestRunning(annotation)) { annotation.setEnabled(false); } } }
Test Class:
package TestNgListeners; import org.testng.annotations.Listeners; import org.testng.annotations.Test; public class AnnotationTransformerTests { @Test(alwaysRun=true) public void test1() { System.out.println("This is my first test whose behaviour would get changed while executing"); } @Test public void test2() { System.out.println("This is my second test executing"); } }
TestNG.XML
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> <suite name="Suite"> <test name="Test"> <classes> <class name="com.softwaretestingo.learnSelenium.Test1"/> </classes> </test> <!-- Test --> <listeners> <listener class-name="com.softwaretestingo.learnSelenium.AnnotationTransformers"></listener> </listeners> </suite> <!-- Suite -->
[https://www.youtube.com/watch?v=AHQcq4YazUE]
Explanation:
If you saw the test class, then we have mentioned the attribute alwaysRun=”true,” which means the test method would always run even if the parameters on which the method depends fails. But by implementing IAnnotationTransformer and Transformer method in Listener class, we change the default behaviour of the TestNG class. Because of that, only the test2 method got executed.
IInvokedMethodListener:
This interface allows us to perform some action before and after a method executed.
This listener executed for both configuration and test methods.
This interface has two methods, and that is:
- beforeInvocation(): This method is invoked before every method.
- afterInvocation(): This method is invoked post every method.
Listener Class:
InvokedMethodListeners.java(includes listeners implemented methods)
package TestNgListeners; import org.testng.IInvokedMethod; import org.testng.IInvokedMethodListener; import org.testng.ITestResult; public class InvokedMethodListeners implements IInvokedMethodListener { public void beforeInvocation(IInvokedMethod method, ITestResult testResult) { System.out.println("Before Invocation of: " + method.getTestMethod().getMethodName() + "of Class:" + testResult.getTestClass()); } public void afterInvocation(IInvokedMethod method, ITestResult testResult) { System.out.println("After Invocation of: " + method.getTestMethod().getMethodName() + "of Class:" + testResult.getTestClass()); } }
Test Class:
package TestNgListeners; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Listeners; import org.testng.annotations.Test; @Listeners(value=InvokedMethodListeners.class) public class InvokedMethodListenersTest { @Test public void test1() { System.out.println("My first test"); } @Test public void test2() { System.out.println("My second test"); } @BeforeClass public void setUp() { System.out.println("Before Class method"); } @AfterClass public void cleanUp() { System.out.println("After Class method"); } }
ISuiteListener
This TestNG is implemented at the Suite level. Has two methods:
- onStart: This method is executed before the test suite execution.
- onFinish: This method is executed after the test execution.
This listener listens to the events to have occurred before and after the execution of the suite. If the parent suite further contains child suites, then child suites are executed before running the parent suite.
Listener Class:
package TestNgListeners; import org.testng.ISuite; import org.testng.ISuiteListener; public class SuiteListeners implements ISuiteListener { public void onStart(ISuite suite) { System.out.println("Suite executed onStart" + suite.getName()); } public void onFinish(ISuite suite) { System.out.println("Suite executed onFinish" + suite.getName()); } }
Test1:
package TestNgListeners; import org.testng.annotations.AfterSuite; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; public class SuiteListenersTests1 { @BeforeSuite public void test1() { System.out.println("BeforeSuite method in Suite1"); } @Test public void test2() { System.out.println("Main Test method 1"); } @AfterSuite public void test3() { System.out.println("AfterSuite method in Suite1"); } }
Test2:
package TestNgListeners; import org.testng.annotations.AfterSuite; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; public class SuiteListenersTests2 { @BeforeSuite public void test1() { System.out.println("BeforeSuite method in Suite2"); } @Test public void test2() { System.out.println("Main Test method 2"); } @AfterSuite public void test3() { System.out.println("AfterSuite method in Suite2"); } }
IReporter
This interface of TestNG helps us to customize the test report generated by the TestNG. This interface has one method called generateReport, which will execute after execute of all the suites. We need to pass three parameters to the generateReport method.
- xmlSuite: If you provide the list of suites of the testng.xml file, which are required to be executed.
- Suites: This object represents various information like classes, packages, test execution result, along with all the test methods. We can say that it will give us detailed information about the suite after the final execution.
- outputDirectory: It has the output folder where the reports get generated.
Listener Class:
package TestNgListener; import java.util.List; import java.util.Map; import org.testng.IReporter; import org.testng.ISuite; import org.testng.ISuiteResult; import org.testng.ITestContext; import org.testng.xml.XmlSuite; public class ReporterListener implements IReporter { public void generateReport(List xmlSuites, List suites, String outputDirectory) { for(ISuite isuite : suites) { Map<string, isuiteresult=""> suiteResults = isuite.getResults(); String sn = isuite.getName(); for(ISuiteResult obj : suiteResults.values()) { ITestContext tc = obj.getTestContext(); System.out.println("Passed Tests of" + sn + "=" + tc.getPassedTests().getAllResults().size()); System.out.println("Failed Tests of" + sn + "=" + tc.getFailedTests().getAllResults().size()); System.out.println("Skipped Tests of" + sn + "=" + tc.getSkippedTests().getAllResults().size()); } } } }
Test Class:
package TestNgListener; import org.testng.SkipException; import org.testng.annotations.Listeners; import org.testng.annotations.Test; import junit.framework.Assert; public class ReporterTest { @Test public void FirstTest() { System.out.println("The First Test Method"); Assert.assertTrue(true); } @Test public void SecondTest() { System.out.println("The Second Test Method"); Assert.fail("Failing this test case"); } @Test public void ThirdTest() { System.out.println("The Third Test Method"); throw new SkipException("Test Skipped"); } }
Not Frequently Used In TestNG Listener:
Now we have discussed a few more listeners that are not frequently used in the automation script.
IConfigurationListener
This interface is used when you want to perform some operation when the configuration metho is passed, failed, or skipped. IConfigurationListener has three methods, and that is:
- onConfigurationSuccess: This method will be executed when a configuration method passed.
- onConfigurationFailure: This method will be executed when a configuration method got failed.
- onConfigurationSkip: When a configuration method got skipped at that time, this method will be executed.
IExecutionListener
This listener interface is used to find out when the suite or test is start or finish. It has two methods, and those are:
- onExecutionStart: This method is executed before the test or suite starts running.
- onExecutionFinish: This method is executed after the test or suite starts execution is completed.
Note: It is not possible for this listener to prevent the execution but only to create events in some way. Also, you can provide more than one “IExecution” listener as you configure TestNG.
IHookable
When you don’t want to run the @Test method at that time, you can use this interface. This interface provides a run method that will be invoked when it found an @Test method.
Source: Link
This is the best tutorial I found. Thanks a lot.