TestNG - Basic Annotations - Transformers


In some scenarios you might want to execute TestNG tests based on some condition or criteria that is evaluated dynamically while test execution is in progress.Such as :

  • Enable or disable a test

  • Add data provider at run time

In order to achieve this, you need to use an Annotation Transformer. An Annotation Transformer is a class that implements the following interface:

  public interface IAnnotationTransformer {

   * This method will be invoked by TestNG to give you a chance
   * to modify a TestNG annotation read from your test classes.
   * You can change the values you need by calling any of the
   * setters on the ITest interface.
   * Note that only one of the three parameters testClass,
   * testConstructor and testMethod will be non-null.
   * @param annotation The annotation that was read from your
   * test class.
   * @param testClass If the annotation was found on a class, this
   * parameter represents this class (null otherwise).
   * @param testConstructor If the annotation was found on a constructor,
   * this parameter represents this constructor (null otherwise).
   * @param testMethod If the annotation was found on a method,
   * this parameter represents this method (null otherwise).
  public void transform(ITest annotation, Class testClass,
      Constructor testConstructor, Method testMethod);

You can specify this class either on the command line or with ant as shown below:

  java org.testng.TestNG -listener TestTransformer testng.xml

or programmatically as shown below:

  TestNG test = new TestNG();
  test.setAnnotationTransformer(new TestTransformer());
  // ...

This interface IAnnotationTransformer modifies the default TestNG tests behavior at run time. Using this listener, we can modify values of all attributes defined in @Test annotation by calling their setters.

Create a Class

Let's see the usage of annotation transformer in below example. Let us skip tests that are tagged to a specified group without changing TestNG suite every time. Create a java class to be tested, say, ListenerTest.java in /work/testng/src.

  import org.testng.annotations.Test;

  public class ListenerTest {
  	public void test1() {
  		System.out.println("I am test1");

  	public void test2() {
  		System.out.println("I am test2");

Create Tansformer class Case Class

  • Create a java test class, say, TestTransformer.java(that implements IAnnotationTransformer) in /work/testng/src.

  • Override method transform().

  • Add an Annotation @Test to methods test1() and test2() and group them.

  • Add logic to skip tests with group name betaTest.

Following are the TestTransformer.java contents.

  import java.lang.reflect.Constructor;
  import java.lang.reflect.Method;
  import java.util.Arrays;
  import java.util.List;

  import org.testng.IAnnotationTransformer;
  import org.testng.annotations.ITestAnnotation;

  public class TestTransformer implements IAnnotationTransformer{
  	public void transform(ITestAnnotation annotation, Class testClass,
  			Constructor testConstructor, Method testMethod) {

  		List groupNames = Arrays.asList(annotation.getGroups());
  		//Value 'betaTest' can be read from many places like properties file, run time parameter etc...
  		//For Simplicity, group is hardcoded in this program

  		String groupNameToSkip = "betaTest";

  			System.out.println("found group name");

Create testng.xml

Next, let's create testng.xml file in /work/testng/src, to execute test case(s).

  <suite name="Suite" parallel="classes" thread-count="2">
    <listener class-name="TestTransformer"></listener>
  <test name="Test">
      <class name="ListenerTest"/>

Compile the test case using javac.

/work/testng/src$ javac TestTransformer.java ListenerTest.java

Now, run the testng.xml, which will run the test case defined in <test> tag. As you can see the tests grouped under name betaTest are skipped.

/work/testng/src$ java org.testng.TestNG testng.xml

Verify the output.

  [betaTest, aplhaTest]
  found group name
  I am test2

  Total tests run: 1, Passes: 1, Failures: 0, Skips: 0