For Setting up the listeners, we either have to register with testng.xml file or @Listeners annotation in the testclass.
IExecutionListener is a listener that monitors the beginning and end of a TestNG run. IExecutionListener interface has two methods:
TestNG calls this method before starting TestNG Suite, So onExecutionStart method is the one, which gets executed before anything in TestNG.
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:
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.
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.
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
===============================================
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
===============================================
IAnnotationTransformer2 Listener is used to modify the properties of the dataProvider annotation and factoryAnnotaton on the run time.
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".
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
}
Article is written by Pavan (a) KarthiQ. Well, I am serving notice period in an MNC, Bangalore. I thought to enrich every person knowledge a little, I always have a feeling, when we teach something, we will learn more than what you know.
Knowledge is the only thing that doubles when you spend it.
I have also created the reporter for Protractor Jasmine. Use for your projects without any hesitation