TestNG Annotations 101

The Blog To Learn Selenium and Test Automation

TestNG Annotations 101

This article explains basics of all TestNG annotations, provides examples for each annotation, explains each TestNG annotation in more detail along with its attributes, and provides tips and tricks for efficient usage.

A Brief Introduction to Annotations

Annotations are used to provide additional information (Metadata) about a program; To be specific it provides additional information about variables, methods or classes to compiler. It has following properties

  • It always start with ‘@’ character
  • They do not change the action of a compiled program
  • Generally used to associate certain metadata (data about data) to instance variables, methods, classes, etc
  • Annotations can change the way a program is treated by compiler; However it has no direct effect on the operation of the annotated code

Annotations have a many uses and few important among them are given below.

  • Information for the compiler — Annotations can be used by the compiler to detect errors or suppress warnings.
  • Compile-time and deployment-time processing — Software tools can process annotation information to generate code, XML files, and so forth.
  • Runtime processing — Some annotations are available to be examined at runtime.

Basics of TestNG Suite

Basic understanding of TestNG test suite is necessary to understand the behavior of TestNG annotations. It is nothing but a xml file to group classes under test group and test groups under suite.

  • There should be only one suite
  • Suite can have ‘n’ number of test groups
  • Each test group can have more than one class list
  • Each class list is a list of classes; and can be one or more

For Example, consider below TestNG test suite.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">

<suite name="allselenium_example_suite">
  <test name="allselenium_example_test_1">
    <classes>
      <class name="allselenium.testng.AnnotationsDiffGroupClass"/>
      <class name="allselenium.testng.AnnotationsSameGroupClass"/>
      <class name="allselenium.testng.AnnotationsExampleClass"/>
    </classes>
  </test>
  <test name="allselenium_example_test_2">
    <classes>
      <class name="allselenium.testng.AnnotationsDiffGroupClass"/>
    </classes>
  </test>
</suite>
  • There is only one suite – “allselenium_example_suite
  • There are two test groups – “allselenium_example_test_1” and “allselenium_example_test_2
  • Each class list have more than one class

We are going to use above suite to understand annotations more clearly. So it is ok to spend more time to understand this TestNG suite.

TestNG Annotations

TestNG use these annotations to help in making a robust test framework.

List of all TestNG Annotations

@BeforeSuite
@BeforeTest
@BeforeClass
@BeforeGroups
@BeforeMethod
@Test
@AfterMethod
@AfterGroups
@AfterClass
@AfterTest
@AfterSuite

@DataProvider
@Listener
@Parameters
@Factory

Test

Marks a class as a test – all methods inside the class without any other annotations marked are considered as test methods

@Test
public class TestNGAnnotations() {

    public void validateMessageTest1() {
        Assert.assertTrue(true);
    }

    public void validateMessageTest2() {
        Assert.assertTrue(true);
    }
}

Marks an individual method as a test

@Test
public void validateMessageTest1() {
    Assert.assertTrue(true);
}

BeforeSuite

Any method marked with this annotation will run only once before all tests in the test suite. If there are more than one BeforeSuite annotated methods, all will be executed.

@BeforeSuite
public void beforeSuiteMethod() {
    System.out.println("BeforeSuite method");
}

AfterSuite

Any method marked with this annotation will run once after execution of all tests in the test suite. If there are more than one AfterSuite annotated methods, all will be executed.

@AfterSuite
public void afterSuiteMethod() {
    System.out.println("AfterSuite method");
}

BeforeTest

Any method marked with this annotation will be executed before first @Test annotated method in the test group in test suite. Local to to the test group and runs only once for the test group in xml suite file.

@BeforeTest
public void beforeTestMethod() {
    System.out.println("BeforeTest method - "+this.getClass().getSimpleName());
}

AfterTest

Any method marked with this annotation will be executed after all @Test annotated methods complete the execution in the test group in test suite. Local to to the test group and runs only once for the test group in xml suite file.

@AfterTest
public void afterTestMethod() {
    System.out.println("AfterTest method - "+this.getClass().getSimpleName());
}

BeforeClass

Any method marked with this annotation will be executed before first @Test method execution in the class. Local to the class and runs only once for the class.

@BeforeClass
public void beforeClassMethod() {
    System.out.println("BeforeClass method");
}

AfterClass

Any method marked with this annotation will be executed after all the test methods in the current class have been executed. Local to the class and runs only once for the class.

@AfterClass
public void afterClassMethod() {
    System.out.println("AfterClass method");
}

BeforeGroups

Any method marked with this annotation will be executed before execution of any test in the specified group in all the class list in the test group.

@BeforeGroups("default")
public void beforeGroupsMethod() {
    System.out.println("BeforeGroups method");
}

AfterGroups

Any method marked with this annotation will be executed after execution of all tests in the specified group in all the class list in the test group.

@AfterGroups("default")
public void afterGroupsMethod() {
     System.out.println("AfterGroups method");
}

BeforeMethod

Any method marked with this annotation will be executed before every @Test annotated method in that class. Scope of this BeforeMethod is ‘class‘.

@BeforeMethod
public void beforeMethodMethod() {
    System.out.println("BeforeMethod method");
}

AfterMethod

Any method marked with this annotation will be executed after every @Test annotated method in that class. Scope of this AfterMethod is ‘class‘.

@AfterMethod
public void afterMethodMethod() {
    System.out.println("AfterMethod method");
}

Parameters

This annotation is used to pass parameters to test methods.

DataProvider

If we use @DataProvider annotation for any method that means you are using that method as a data supplier. The configuration of @DataProvider annotated method must be like it always return Object[][] which we can use in @Test annotated method. The @Test method that wants to receive data from this DataProvider needs to use a dataProvider name equals to the name of this annotation.

Factory

Marks a method as a factory that returns objects that will be used by TestNG as Test classes. The method must return Object[ ].

Listeners

This annotation is used with test class. It helps in writing logs and results.

Benefits of using TestNG Annotations

  • It identifies the methods it is interested in by looking up annotations. Hence method names are not restricted to any pattern or format.
  • We can pass additional parameters to annotations.
  • Annotations are strongly typed, so the compiler will flag any mistakes right away.
  • Test classes no longer need to extend anything (such as Test Case, for JUnit 3).

TestNG Annotations order of Execution

Inside same class

Example Class – AnnotationsExample.java

 import org.testng.Assert;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.AfterGroups;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.AfterSuite;
 import org.testng.annotations.AfterTest;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeGroups;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.BeforeSuite;
 import org.testng.annotations.BeforeTest;
 import org.testng.annotations.Test;

 public class AnnotationsExample {

 @BeforeSuite
 public void beforeSuiteMethod() {
     System.out.println("BeforeSuite method - "+this.getClass().getSimpleName());
 }

 @BeforeTest
 public void beforeTestMethod() {
     System.out.println("BeforeTest method - "+this.getClass().getSimpleName());
 }

 @BeforeClass
 public void beforeClassMethod() {
     System.out.println("BeforeClass method - "+this.getClass().getSimpleName());
 }

 @BeforeGroups("default")
 public void beforeGroupsMethod() {
     System.out.println("BeforeGroups method - "+this.getClass().getSimpleName());
 }

 @BeforeMethod
 public void beforeMethodMethod() {
     System.out.println("BeforeMethod method - "+this.getClass().getSimpleName());
 }

 @Test(groups={"default"})
 public void validateMessageTest1() {
     System.out.println("Test 1 validation in progress - "+this.getClass().getSimpleName());
     Assert.assertTrue(true);
 }

 @Test(groups={"default"})
 public void validateMessageTest2() {
     System.out.println("Test 2 validation in progress - "+this.getClass().getSimpleName());
     Assert.assertTrue(true);
 }

 @AfterMethod
 public void afterMethodMethod() {
     System.out.println("AfterMethod method - "+this.getClass().getSimpleName());
 }

 @AfterGroups("default")
 public void afterGroupsMethod() {
     System.out.println("AfterGroups method - "+this.getClass().getSimpleName());
 }

 @AfterClass
 public void afterClassMethod() {
     System.out.println("AfterClass method - "+this.getClass().getSimpleName());
 }

 @AfterTest
 public void afterTestMethod() {
     System.out.println("AfterTest method - "+this.getClass().getSimpleName());
 }

 @AfterSuite
 public void afterSuiteMethod() {
     System.out.println("AfterSuite method - "+this.getClass().getSimpleName());
 }

 }

TestNG Suite

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">

<suite name="Suite">
  <test thread-count="5" name="Test">
    <classes>
      <class name="ar.learn.testng.AnnotationsExample"/>
    </classes>
  </test>
</suite>

Output

 [RemoteTestNG] detected TestNG version 6.14.2
 BeforeSuite method - AnnotationsExample
 BeforeTest method - AnnotationsExample
 BeforeClass method - AnnotationsExample
 BeforeGroups method - AnnotationsExample
 BeforeMethod method - AnnotationsExample
 Test 1 validation in progress - AnnotationsExample
 AfterMethod method - AnnotationsExample
 BeforeMethod method - AnnotationsExample
 Test 2 validation in progress - AnnotationsExample
 AfterMethod method - AnnotationsExample
 AfterGroups method - AnnotationsExample
 AfterClass method - AnnotationsExample
 AfterTest method - AnnotationsExample
 AfterSuite method - AnnotationsExample

Multiple classes

AnnotationsExample.java

 import org.testng.Assert;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.AfterGroups;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.AfterSuite;
 import org.testng.annotations.AfterTest;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeGroups;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.BeforeSuite;
 import org.testng.annotations.BeforeTest;
 import org.testng.annotations.Test;

 public class AnnotationsExample {

 @BeforeSuite
 public void beforeSuiteMethod() {
     System.out.println("BeforeSuite method - "+this.getClass().getSimpleName());
 }

 @BeforeTest
 public void beforeTestMethod() {
     System.out.println("BeforeTest method - "+this.getClass().getSimpleName());
 }

 @BeforeClass
 public void beforeClassMethod() {
     System.out.println("BeforeClass method - "+this.getClass().getSimpleName());
 }

 @BeforeGroups("default")
 public void beforeGroupsMethod() {
     System.out.println("BeforeGroups method - "+this.getClass().getSimpleName());
 }

 @BeforeMethod
 public void beforeMethodMethod() {
     System.out.println("BeforeMethod method - "+this.getClass().getSimpleName());
 }

 @Test(groups={"default"})
 public void validateMessageTest1() {
     System.out.println("Test 1 validation in progress - "+this.getClass().getSimpleName());
     Assert.assertTrue(true);
 }

 @Test(groups={"default"})
 public void validateMessageTest2() {
     System.out.println("Test 2 validation in progress - "+this.getClass().getSimpleName());
     Assert.assertTrue(true);
 }

 @AfterMethod
 public void afterMethodMethod() {
     System.out.println("AfterMethod method - "+this.getClass().getSimpleName());
 }

 @AfterGroups("default")
 public void afterGroupsMethod() {
     System.out.println("AfterGroups method - "+this.getClass().getSimpleName());
 }

 @AfterClass
 public void afterClassMethod() {
     System.out.println("AfterClass method - "+this.getClass().getSimpleName());
 }

 @AfterTest
 public void afterTestMethod() {
     System.out.println("AfterTest method - "+this.getClass().getSimpleName());
 }

 @AfterSuite
 public void afterSuiteMethod() {
     System.out.println("AfterSuite method - "+this.getClass().getSimpleName());
 }

 }

AnnotationsSameGroup.java

 import org.testng.Assert;
 import org.testng.annotations.Test;

 public class AnnotationsSameGroup {
     @Test(groups={"default"})
     public void validatePrint() {
         System.out.println("Validation in progress "+this.getClass().getSimpleName());
         Assert.assertTrue(true);
     }
 }

AnnotationsDifferentGroup.java

 import org.testng.Assert;
 import org.testng.annotations.Test;

 public class AnnotationsDifferentGroup {
     @Test(groups={"special"})
     public void validatePrint() {
         System.out.println("Validation in progress "+this.getClass().getSimpleName());
         Assert.assertTrue(true);
     }
 }

TestNG Suite

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">

<suite name="Suite">
  <test thread-count="5" name="Test">
    <classes>
      <class name="ar.learn.testng.AnnotationsDifferentGroup"/>
      <class name="ar.learn.testng.AnnotationsSameGroup"/>
      <class name="ar.learn.testng.AnnotationsExample"/>
    </classes>
  </test>
</suite>

Output

 [RemoteTestNG] detected TestNG version 6.14.2
 BeforeSuite method - AnnotationsExample
 BeforeTest method - AnnotationsExample
 Validation in progress AnnotationsDifferentGroup
 BeforeGroups method - AnnotationsExample
 Validation in progress AnnotationsSameGroup
 BeforeClass method - AnnotationsExample
 BeforeMethod method - AnnotationsExample
 Test 1 validation in progress - AnnotationsExample
 AfterMethod method - AnnotationsExample
 BeforeMethod method - AnnotationsExample
 Test 2 validation in progress - AnnotationsExample
 AfterMethod method - AnnotationsExample
 AfterGroups method - AnnotationsExample
 AfterClass method - AnnotationsExample
 AfterTest method - AnnotationsExample
 AfterSuite method - AnnotationsExample

 

Leave a Reply

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