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.

  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 Scenario:

In this scenario, we will automate the Login process and implement ‘ItestListener’

  1. Launch the Chrome browser and open the site www.gmail.com
  2. Login to Gmail

Steps to create a TestNG Listener

Step 1: Launch the Eclipse

Step2: Create a class “TestListener” that implements ‘ITestListener’. Add the Unimplemented methods by moving the mouse over redline text.

listener.PNG

Click on “Add unimplemented methods”. Multiple unimplemented methods (without a body) are added to the code as 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

}

}

Now, Lets modify the ‘ListenerTest’ class. In particular, we will modify following methods-

methods.PNG

In modification we just print the name of the Test.

Logs are created in the console, to easily understand for the user which test is a pass, fail, and skip status.

After modification, the code looks like as-

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: Create another class “TestCases” for the login process. Selenium will execute this ‘TestCases’ to login 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: Next, we will implement this listener in our project class i.e. “TestCases”. There are two different ways to connect to the class and interface.

The first way is to use Listeners annotation (@Listeners) as shown below:

listenerclass.PNG

We use this in the “TestCases” class as shown below.

So the “TestCases” class looks like after using Listener annotation:

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 looks like:

out.PNG

Step 5: Execute the “TestCases” class. The Methods in “ListenerTest” class are automatically called according to the behaviour of methods annotated as @Test.

Step 6: Verify the Output that logs displays at the console. Output of the ‘TestCases’ will look like this:

output1.PNG

Listener use for multiple classes.

If project has multiple classes adding Listeners in such cases, we can create a testng.xml and add listeners tag in XML.

<?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 implemented irrespective of the number of classes you have throughout the test suite. When you run above XML file, listeners will work on all classes which are mentioned. You can declare any number of listeners class.

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
Tags

Related Articles

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.

Back to top button
Close
Close