All IT Courses 50% Off
Selenium Tutorials

TestNG Listeners in Selenium

ITestListener & ITestResult Example

What is Listeners?

Listeners are the very important features of TestNG which allow you to customized logs or report of TestNG. As the name says it listens to certain events and behaves accordingly. We can fully customize the logs using listeners. There are several interfaces in java that allow you to modify TestNG behavior. These interfaces are known as TestNG Listeners in Selenium WebDriver. TestNG Listeners also allows us to customize the test logs or report according to project requirements. Selenium WebDriver TestNG Listeners are modules that listen to certain events and keep track of execution while performing some action at test execution stages.

In Selenium WebDriver TestNG Listeners can be implemented at two levels:

  1. Class Level: In this level, for every particular class we implement listeners, no matter how many test cases it includes.
  2. Suite Level: In this level, for a particular suite we implement listeners which include several classes of test cases.

Types of Listeners in Selenium WebDriver

There are several interfaces that allow you to modify TestNG’s behaviour. These interfaces are broadly called “TestNG Listeners”. Below are the few listeners:

  1. IAnnotation Transformer
  2. IConfigurationListener 
  3. IHookable
  4. IInvokedMethodListener
  5. IMethodInterceptor
  6. IReporter
  7. ISuiteListener
  8. ITestListener
  9. IConfigurable
  10. IExecutionListener

Frequently Used TestNG Listeners With Examples

Below are the most popular and widely used TestNG listeners with examples.

  1. ITestListener: ITestListener is the most popular TestNG listener in Selenium WebDriver. It provides an easy way to implement interface through a normal Java class, where the class overrides every method that are declared inside the ITestListener. By using TestNG listeners in Selenium WebDriver, you can change the default behavior of your test by adding different events to the methods and also defines a new way of logging or reporting.

ITestListener interface will implements Listeners. An ITestListener interface has following methods.

All IT Courses 50% Off
  1. onTestStart(): An onTestStart() method is invoked before any test method gets started.
  2. onTestSuccess(): An onTestSuccess() method is invoked when any test method succeeds. It is used to indicate that the particular test method has successfully finished its execution.
  3. onTestFailure(): An onTestFailure() method is executed when test method fails. It is used to indicate that the particular test method has failed.
  4.  onTestSkipped(): An onTestSkipped() method is executed when each test method is skipped. It is used to indicate that the particular test method has been skipped. 
  5. onTestFailedButWithinSuccessPercentage: This method is invoked each time the test method fails but within success percentage.
  6. onStart(): An onStart() method is invoked on the start of any test method.
  7. onFinish(): An onFinish() method is invoked when all test methods gets executed.

Test Example:

In this scenario, we’re going to automate the login process and incorporate the ‘ITestListener’ feature.

  1. We’ll begin by launching the Chrome browser and navigating to the website www.gmail.com.
  2. After that, we’ll execute the login procedure.

Steps for Setting Up a TestNG Listener

Step 1: Open up Eclipse.

Step 2: Create a class called “TestListener” that implements the ‘ITestListener’ interface. Fill in the missing methods by simply hovering over the highlighted lines.

listener.PNG

Click the “Add unimplemented methods” option. This action will insert several unimplemented methods (without content) into the code, as shown below.

package ListenerDemo;

import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;

public class ListenerTest implements ITestListener {

public void onTestStart(ITestResult result) {
// TODO Auto-generated method stub

}

public void onTestSuccess(ITestResult result) {
// TODO Auto-generated method stub

}

public void onTestFailure(ITestResult result) {
// TODO Auto-generated method stub

}

public void onTestSkipped(ITestResult result) {
// TODO Auto-generated method stub

}

public void onTestFailedButWithinSuccessPercentage(ITestResult result) {
// TODO Auto-generated method stub

}

public void onStart(ITestContext context) {
// TODO Auto-generated method stub

}

public void onFinish(ITestContext context) {
// TODO Auto-generated method stub

}

}

Let’s make some changes to the ‘ListenerTest’ class now. Specifically, we’ll be modifying the following methods:

methods.PNG

In the updated version, we’re simply printing the name of the test. This generates logs in the console that make it straightforward for the user to identify whether a test has passed, failed, or been marked as skipped.

After these modifications, the code will appear as follows:

package Listener_Demo;

import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;

public class ListenerTest implements ITestListener {

    // This method is called when Test case get Started.
public void onTestStart(ITestResult result) {
    System.out.println(result.getName()+" test case started");

}
    // This method is called when Test case get passed.
public void onTestSuccess(ITestResult result) {
    System.out.println("The name of the testcase passed is :"+result.getName());

}
    // This method is called when Test case get failed,.
    public void onTestFailure(ITestResult result) {
    System.out.println("The name of the testcase failed is :"+result.getName());

}
    // This method is called when Test case get Skipped,.
    public void onTestSkipped(ITestResult result) {
        System.out.println("The name of the testcase Skipped is :"+result.getName());
}

public void onTestFailedButWithinSuccessPercentage(ITestResult result) {
// TODO Auto-generated method stub

}

public void onStart(ITestContext context) {
// TODO Auto-generated method stub

}

public void onFinish(ITestContext context) {
// TODO Auto-generated method stub

}

}

Step 3: Develop another class called “TestCases” to handle the login process. Selenium will utilize this ‘TestCases’ class to execute the login procedure automatically.

package Listener_Demo;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.Assert;
import org.testng.annotations.Test;

public class TestCases {

WebDriver driver= new ChromeDriver();

// Test to pass as to verify listeners .
@Test
public void Login()
{
    driver.get("https://login.yahoo.com/config/login?");
    
    driver.findElement(By.id("login-username")).sendKeys("vinodreddy10.thumma@gmail.com");
    driver.findElement(By.id("login-signin")).click();
    driver.findElement(By.id("login-passwd")).sendKeys("Oracle11i");
    driver.findElement(By.id("login-signin")).click();
}

// Forcefully failed this test as to verify listener.
@Test
public void TestToFail()
{
    System.out.println("This method to test fail");
    Assert.assertTrue(false);
}


}

Step 4: We’ll incorporate this listener into our project class named “TestCases.” There are two distinct methods to link the class and interface.

The initial approach involves using the Listeners annotation (@Listeners), demonstrated as follows:

listenerclass.PNG

We apply this in the “TestCases” class, as illustrated below.

Thus, the appearance of the “TestCases” class following the implementation of the Listener annotation will be:

package Listener_Demo;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.Assert;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;

@Listeners(ListenerDemo.ListenerTest.class)


public class TestCases {
WebDriver driver= new ChromeDriver();

// Test to pass as to verify listeners .
@Test
public void Login()
{
    driver.get("https://login.yahoo.com/config/login?");
    
    driver.findElement(By.id("login-username")).sendKeys("vinodreddy10.thumma@gmail.com");
    driver.findElement(By.id("login-signin")).click();
    driver.findElement(By.id("login-passwd")).sendKeys("Oracle11i");
    driver.findElement(By.id("login-signin")).click();
}

// Forcefully failed this test as to verify listener.
@Test
public void TestToFail()
{
    System.out.println("This method to test fail");
    Assert.assertTrue(false);
}


}

When you run the above class the project structure is shown below:

out.PNG

Step 5: Now, let’s run the “TestCases” class. The methods from the “ListenerTest” class will be called automatically depending on how the methods annotated with @Test behave.

Step 6: Take a look at the console output. The logs displayed after running the ‘TestCases’ will look something like this:

output1.PNG

Using Listeners for Multiple Classes:

In cases where a project involves multiple classes, if we need to add listeners, we can handle this by creating a testng.xml file. Within the XML, we can include a listeners tag to achieve the desired functionality.

<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">  
<suite name="test_suite">  
<test name="Including test cases">  
<groups>  
<run>  
<include name="Include.*"/>  
</run>  
</groups>  
<classes>  
<class name="com.testing.GroupRegularExpression"/>  
</classes>  
</test> <!-- Test -->  
</suite> <!-- Suite --> 

This listener is applied consistently across all classes within the entire test suite. Once you execute the XML file mentioned above, the listeners will operate on all the classes specified. You’re free to declare any number of listener classes as needed.

2. IAnnotationTransformer

IAnnotationTransformer is an interface that gets invoked by TestNG to modify the behavior of the test annotation method in our test class that provides a “transform” method. The transform method provides parameters:

  1. annotation: The annotation is read from the test class.
  2. testClass: This parameter would represent the same class if the annotation found on a class.
  3. testConstructor: If the annotation found a constructor, this parameter would represent that same constructor.
  4. testMethod: If the annotation found a method, this parameter would represent that same method.

Note: At least one of the parameters will be non-null.

Below is the code that would be executed at the suite level. In this code, we used a (“alwaysRun = true”) parameter in our Test annotation that indicates that the test method would always run even if the parameters on which the method depends fails. However, we would transform this behavior of our test method through IAnnotationTransformer Listener which won’t allow the particular test method to get executed.

Listeners Class File:

package Listener_Demo;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

import org.testng.annotations.ITestAnnotation;

public class AnnotationTransformers {
    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 File:

package Listener_Demo;

import org.testng.annotations.Test;

public class AnnotationTransformerTests {
@Test(alwaysRun = true) public void test1() {
        System.out.println("This is my first test whose behaviour  get changed while executing");
    }
    @Test public void test2() {
        System.out.println("This is my executed second test");
    }
}

Console Output Screen:

output2.PNG
  1. ISuiteListener: This ISuiteListener listener in Selenium WebDriver is implemented at a suite level called ISuiteListener. It mainly has two methods:
  • onStart: This method is executed prior the test suite.
  • onFinish: This method is executed post the test suite.

This ISuiteListener basically listens to the events that have occurred before and after the execution of the suite. If the parent suite contains child suites then these child suites are executed before running the parent suite.

Step 1: Implementing ISuiteListener with java class and adding the unimplemented methods.

Class: ListenersSuite

package Listener_Demo;

import org.testng.ISuite;
import org.testng.ISuiteListener;

public class ListenersSuite 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());
    }
}

Step 2: Creating two test classes and add in two different child suites.

Class 1: Tests1SuiteListeners

package Listener_Demo;

import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;

public class Tests1SuiteListeners {
    @BeforeSuite public void test1() {
        System.out.println("BeforeSuite method in Suite1");
    }
    @Test public void test2() {
        System.out.println("Main method 1 Test");
    }
    @AfterSuite public void test3() {
        System.out.println("AfterSuite method in Suite1");
    }

}

Class 2: Tests2SuiteListeners

package Listener_Demo;

import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;

public class Tests2SuiteListeners {
    @BeforeSuite public void test1() {
        System.out.println("BeforeSuite method in Suite2");
    }
    @Test public void test2() {
        System.out.println("Main method 2 Test");
    }
    @AfterSuite public void test3() {
        System.out.println("AfterSuite method in Suite2");
    }

}

Step 3: Adding the test classes to the child suites.

Suite 1: Test Suite One.xml

<?xml version="1.0" encoding="UTF-8"?>
<suite name="Test Suite One">
    <test name="Test Method1">
        <classes>
            <class name="Listener_Demo.Tests1SuiteListeners" />
        </classes>
    </test>
</suite>

Suite 2: Test Suite Two.xml

<?xml version="1.0" encoding="UTF-8"?>
<suite name="Test Suite Two">
    <test name="Test Method2">
        <classes>
            <class name="Listener_Demo.Tests2SuiteListeners" />
        </classes>
    </test>
</suite>

Step 4: Create a parent suite xml file and combine above 2 defined suites along with the listeners class.

<?xml version="1.0" encoding="UTF-8"?>
<suite name="suiteListener">
    <listeners>
        <listener class-name="Listener_Demo.ListenersSuite"></listener>
    </listeners>
    <suite-files>
        <suite-file path="./One.xml"></suite-file>
        <suite-file path="./Two.xml"></suite-file>
    </suite-files>
</suite>

Console Output Screen:

listoutput.PNG

Conculsion:

Listeners are used to generate logs or customize the TestNG reports in Selenium Webdriver.

  • There are different types of listeners and can be used as per requirements.
  • Listeners are interfaces used in selenium web driver script
Facebook Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Related Articles

Back to top button