TestNG Listeners

  • IExecutionListener
  • ITestListener
  • IReporter
  • IExecutionListener
  • ISuiteListener
  • IAnnotationTransformer
  • IMethodInterceptor
  • IInvokedMethodListener
  • IHookable


For Setting up the listeners, we either have to register with testng.xml file or @Listeners annotation in the testclass.

Listener confugured in testng.xml are only effective when you are running the the TestNG using testng.xml file as TestNG suite.

IExecutionListener Listener in TestNG :

IExecutionListener is a listener that monitors the beginning and end of a TestNG run. IExecutionListener interface has two methods:

  • onExecutionStart()
  • onExecutionFinish()
testng-iexecution-listener

onExecutionStart() :

TestNG calls this method before starting TestNG Suite, So onExecutionStart method is the one, which gets executed before anything in TestNG.

onExecutionFinish() :

onExecutionFinish gets executed after completing everything on te TestNg suites.


									<?xml version="1.0" encoding="UTF-8"?>
									<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
									<suite name="Suite">
										<listeners>
											<listener class-name="src.liste.SampleOfExecutionListener" />
										</listeners>
									  <test thread-count="5" name="Test">
										<classes>
										  <class name="listtest.TestExecutionListener"/>
										</classes>
									  </test> <!-- Test -->
									</suite> <!-- Suite -->			
									

As usual, when i try to run something new I will face errors, while running this below example, I got following error:
Listener src.liste.SampleOfExecutionListener was not found in project's classpath

I have corrected the error, by chaninging the listener location in the xml, the packages should start with the same level as test classes.

In above xml, the class location starts from listtest, so i removed the src from the listener location.


<listener class-name="liste.SampleOfExecutionListener" />			

Listener interface implementation.


import org.testng.IExecutionListener;
public class SampleOfExecutionListener implements IExecutionListener {
	@Override
	public void onExecutionStart() {
		System.out.println("First Listener of the TestNG Suite");		
	}

	@Override
	public void onExecutionFinish() {
		System.out.println("Completed execution of all Suites in TestNG");
	}
}			

Test class implementation


public class TestExecutionListener {
	@BeforeSuite
	public void beforeSuite() {
		System.out.println("BeforeSuite");
	}
	@Test
	public void test() {
		System.out.println("Test");
	}
	@AfterSuite
	public void afterSuite() {
		System.out.println("AfterSuite");
	}
}			

Output of the IExecutionListener implementations. output-iexecution-listener

Create QR Code

IAnnotationTransformer in TestNG

Annotations are so contant interms of changes by design, so any change in the annotation methods/ values require recompilation of source files, like our normal java code

Most of the things are done by annotations in TestNG, So TestNG relies more on annotations

IAnnotationTransformer allows you to override or change basic behaviour of the annotations on the run time, IAnnotationTransformer helps user only for @Test Annotation.

IAnnotationTransformer has only one method, which is transform(). Using transform() method, we can configure all the properties of @Test annotation.
transform method accepts four parameter which are types of ITestAnnotation interface, Class, Constrcutor, Method.

As you guessed user donot have to worry about the listener parameter as the TestNG takes care of it.

Disable / Enable a @Test in runtime :

In below example we are trying to disable a @Test during the run time and also to enable a disabled @Test, have you heard that few projects run the test based on an Excel sheet.

The Excel sheet may contain decisions, what are tests to run and what are the tests not to run, people do this excel for avoiding recompilation purpose.

Apache POI provides the facility to read and write the excel sheet with selenium

I am just hardcoding the value in the IAnnotationTransformer implementation itself.
IAnnotationTransformer Listener Implementation.


import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import org.testng.IAnnotationTransformer;
import org.testng.annotations.ITestAnnotation;
public class Sample_ITestAnnotationTransformer implements IAnnotationTransformer{
	@Override
	public void transform(ITestAnnotation annotation, Class testClass,
			Constructor testConstructor, Method testMethod) {	
		if (testMethod.getName().equals("test")) {
				System.out.println("About to disable the method called : " + testMethod.getName()); 
				annotation.setEnabled(false);
				System.out.println("I am the somebody, who is stopping the test");
			}
		if (testMethod.getName().equals("test_Disabled")) {
			System.out.println("About to enable the method called : " + testMethod.getName()); 
			annotation.setEnabled(true);
			System.out.println("@Test enabler");
		}
	}
}			

IAnnotationTransformer Listener Implementation.


public class Test_ITestAnnotationTransformer{
	@Test
	public void test() {
		System.out.println("hello, somebody is not letting me run");
	}
	@Test(enabled = false)
	public void test_Disabled() {
		System.out.println("Please Someone Run me");
	}
}		

testng.xml integration for IAnnotationTransformer Listener.


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Suite">
	<listeners>
		<listener class-name="liste.Sample_ITestAnnotationTransformer" />
	</listeners>
  <test thread-count="5" name="Test">
    <classes>
      <class name="listtest.Test_ITestAnnotationTransformer"/>
    </classes>
  </test> <!-- Test -->
</suite> <!-- Suite -->			

Output of Enable/Disable @Test on runtime


[RemoteTestNG] detected TestNG version 6.14.2
About to enable the method called : test_Disabled
@Test enabler
About to disable the method called : test
I am the somebody, who is stopping the test
Please Someone Run me

===============================================
Suite
Total tests run: 1, Failures: 0, Skips: 0
===============================================

Modify Invocation count & Invocation Timeout on RunTime :

We can set the invocation count and invocation Timeout of a @Test ethod on the run time, change the trasfom method like below.


@Override
public void transform(ITestAnnotation annotation, Class testClass,
		Constructor testConstructor, Method testMethod) {	
	if (testMethod.getName().equals("test")) {
		System.out.println("Setting invocationCount and Timeout for : " + testMethod.getName()); 
		annotation.setInvocationCount(3);
		annotation.setInvocationTimeOut(10);
	}
}			

output


[RemoteTestNG] detected TestNG version 6.14.2
Setting invocationCount and Timeout for : test
hello, somebody is not letting me run
hello, somebody is not letting me run
hello, somebody is not letting me run

===============================================
Suite
Total tests run: 1, Failures: 0, Skips: 0
===============================================			

I hope you understood how to modify the parameters present in the @Test test method, not only above we can set all the parameters.

Create Headless Chrome Browser in Selenium webdriver

IAnnotationTransformer2 listener in TestNG

IAnnotationTransformer2 Listener is used to modify the properties of the dataProvider annotation and factoryAnnotaton on the run time.

Modify the dataProvider on fly :

transform(IDataProviderAnnotation annotation, Method method) method present in the IAnnotationTransformer2, will help us to modify the behavior of the dataProvider annotation.

In below example, I am deciding to run the testcases in parallel if I face a dataProvider name called "HugeData".

This case will be useful when you are testing the same test case with different data sets, also it would execute faster if we can decide to run in parallel when we have lorge data

Create a class ( Dummy_DataProvider ) to supply data, i have created few data provider with different names in TestNG.


import org.testng.annotations.DataProvider;

public class Dummy_DataProvider {
	@DataProvider
	public static Object[][] getDp1() {
		return new Object[][]{{"one"}, {"two"}, {"three"}};
	}
	@DataProvider
	public static Object[][] getDp2() {
		return new Object[][]{{"1"}, {"2"}, {"3"}};
	}
	@DataProvider(name="HugeData")
	public static Object[][] getLargeDataSet() {
		return new Object[][]{{"Large"}, {"Data"}, {"Set"}};
	}
	@DataProvider(name="constructorParams")
	public static Object[][] getConstructorParams() {
		return new Object[][]{{"a"}, {"b"}, {"c"}};
	}
}			

Create a test class ( ) with a @Test method to check on which thread we are running


public class TestDataProvider_IAnnotationTransformer2 {
	@Test(dataProvider="HugeData", dataProviderClass=Dummy_DataProvider.class)
	public void testParallel(String param) {
		System.out.println("testParallel is runnning with parameter " + param + " threadId: "
				+ Thread.currentThread().getId());
	}
}			

Create the listener for the IAnnotationTransformer2 interface


public class Sample_IAnnotationTransformer2 implements IAnnotationTransformer2{
	@Override
	public void transform(IDataProviderAnnotation annotation, Method method) {
		if (annotation.getName().equals("HugeData")) {
			System.out.println("Huge data set, run parallel");
			annotation.setParallel(true);
			System.out.println("Are you parallel : "+annotation.isParallel());
		}
	}
	// there are three more methods to override 
	// but due to space issue i am not writing in this code
}
			

Xpath in Selenium

About Author

Myself KarthiQ, I am the author of this blog, I know ways to write a good article but some how I donot have the skills to make it to reach people, would you like help me to reach more people By sharing this Article in the social media.

Share this Article Facebook
Comment / Suggestion Section
Point our Mistakes and Post Your Suggestions
Copyright © CherCher Tech