Understanding TestNG annotations

Image

Let’s see how the TestNG annotations work. Below table gives the details on when/how the annotated methods get executed. I’ve also pasted the Classes, xml file and the output, so as to illustrate whatever I’ve explained.

 

Annotation when & How
@BeforeSuite Once, before ANY test in ANY class in the suite is run. No matter in which class this annotated method is present.

If every class in the suite has this method then, it will be executed in the same order as the order in which classes are listed in the suite in xml file

@BeforeTest Once, before ANY test in all classes in the suite is run.

Lets say 3 classes are listed in the suite and this method is there in class#3. Even then, this class is executed at the very beginning, even before the Test method of Class#1 is executed

@BeforeClass Once, before ANY test in THAT PARTICULAR class in the suite is run (in case if the class contains @BeforeTest as well then, @BeforeTest gets run first and then @BeforeClass)

Lets say 3 classes are listed in the suite and this method is there in class#3. Then, this class is executed before the Test method of Class#3 is executed

@BeforeMethod Once, before EACH test in THAT PARTICULAR class in the suite is run (i.e this method is tightly bound to the Test method of particular class and has no relation with other class in the suite)

package GoogleSearchScreenTesting;

****Test Class 1******************

import java.io.File;
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.WebDriver;

import pomGoogleSearchScreen.GoogleSearchScreen;

import org.openqa.selenium.ie.InternetExplorerDriver;
import org.testng.annotations.BeforeMethod;

import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
public class NewTest {

int counter, counter1,counter2 = 0;

@BeforeTest
public void setup(){
//commenting the code below because life of variable gets killed soon after the method execution is over
//int counter = 0;
counter = counter + 1;
System.out.println(“I’m @BeforeTest method. Your visit Number is “+ counter);

}

@BeforeMethod
public void bm(){
//if i dont comment this line of code below, Java will pick local variable during execution of method
//int counter1 = 0;
counter1 = counter1 + 1;
System.out.println(“I’m @BeforeMethod method. I got run before your Test case# “+ counter1 + ” was run”);
}

@Test
public void testCase1() {
System.out.println(“THis is first test”);

}

@Test
public void testCase2(){
System.out.println(“This is test case2. Lets check if @Before Test gets executed before me also”);
}

}

****Test Class 2******************

package GoogleSearchScreenTesting;

import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;

public class NewTest2 {

int counter2 = 0;

@BeforeSuite
public void bs(){
counter2+= 1;
System.out.println(“I’m @BeforeSuite. This is your entry# “+counter2+” inside me”);
}

@BeforeClass
public void bc(){

System.out.println(“I’m @BeforeClass method.But now inside the 2nd class”);
}

@Test
public void testCase1() {
System.out.println(“This is 1st test case of 2nd class. Not doing anything much”);
}
}

XML FIle

<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE suite SYSTEM “http://testng.org/testng-1.0.dtd”&gt;
<suite guice-stage=”DEVELOPMENT” name=”Default suite”>
<test verbose=”2″ name=”Default test”>
<classes>
<class name=”GoogleSearchScreenTesting.NewTest”/>
<class name=”GoogleSearchScreenTesting.NewTest2″/>
</classes>
</test> <!– Default test –>
</suite> <!– Default suite –>

Output

I’m @BeforeSuite. This is your entry# 1 inside me
I’m @BeforeTest method. Your visit Number is 1
I’m @BeforeMethod method. I got run before your Test case# 1 was run
THis is first test
I’m @BeforeMethod method. I got run before your Test case# 2 was run
This is test case2. Lets check if @Before Test gets executed before me also
I’m @BeforeClass method.But now inside the 2nd class
This is 1st test case of 2nd class. Not doing anything much

 

Second: Lets Understand @After Type of annotations

@AfterSuite Executed at the end – after all other annotated methods are exectued (including @AfterTest method)
@AfterTest Executed after all the Test methods of all classes in the suite are executed
@AfterClass Executed after all the Test methods of THAT PARTICULAR class in the suite are executed
@AfterMethod Executed each time after a Test method inside a Particular class is executed

——————-TestClass1——————-

package GoogleSearchScreenTesting;

import java.io.File;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.WebDriver;
import pomGoogleSearchScreen.GoogleSearchScreen;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;

public class NewTest {

int counter, counter1,counter2 = 0;

@BeforeSuite
public void bs(){
System.out.println(“I’m @BeforeSuite inside class1”);
}

@Test
public void testCase1() {

System.out.println(“THis is first test”);

}

@Test
public void testCase2(){
System.out.println(“This is test case2. Lets check if @Before Test gets executed before me also”);
}

@AfterSuite
public void as(){
System.out.println(“Hello World. I’m @AfterSuite Method. I’m inside First class”);
}

@AfterTest
public void at(){
System.out.println(“Hiii…. I’m @AfterTest Method. I’m competing with whom? Who next?”);
}

@AfterMethod
public void am(){
System.out.println(“I’m @AfterMethod method, i’m the only one getting run after each test in this class”);
}

}

——————-TestClass2——————-

import org.junit.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

public class NewTest2 {

int counter2 = 0;

@BeforeSuite
public void bs(){
System.out.println(“I’m @BeforeSuite inside class2”);
}

@BeforeClass
public void bc(){
System.out.println(“I’m @BeforeClass inside class2”);
}

@BeforeTest
public void bt(){
System.out.println(“I’m @BeforeTest. I’m inside 2nd class”);
}

@Test
public void testCase1() {
System.out.println(“This is 1st test case of 2nd class. Not doing anything much”);
}

@AfterClass
public void ac(){
System.out.println(“Ladies and gentlement, I’m your @AfterClass method”);
}
}

Output:

I’m @BeforeSuite inside class1
I’m @BeforeSuite inside class2
I’m @BeforeTest. I’m inside 2nd class
I’m @AfterMethod method, i’m the only one getting run after each test in this class
This is test case2. Lets check if @Before Test gets executed before me also
I’m @AfterMethod method, i’m the only one getting run after each test in this class
I’m @BeforeClass inside class2
This is 1st test case of 2nd class. Not doing anything much
Hiii…. I’m @AfterTest Method. I’m competing with whom? Who next?
[Utils] Attempting to create C:\Selenium\workspace\SelenimTests\test-output\Default suite\Default test.xml
[Utils] Directory C:\Selenium\workspace\SelenimTests\test-output\Default suite exists: true
PASSED: testCase1
PASSED: testCase2
PASSED: testCase1

===============================================
Default test
Tests run: 3, Failures: 0, Skips: 0
===============================================

Hello World. I’m @AfterSuite Method. I’m inside First class

===============================================
Default suite
Total tests run: 3, Failures: 0, Skips: 0
===============================================

 

 

a object oriented approach in designing the selenium script

Image

Having learnt java as part of my zeal to learn selenium, I did what any java-selenium beginner will do – write everything in main() function. The code was looking so messy with a class defined in way as to break all the rules of abstraction, encapsulation and data hiding. There was a joy – for having built the first selenium code overcoming all the problems that I discussed in my earlier posts. But there was something missing in the joy. And it didnt take much time for me to know what was it.

When i started looking out for options to make my selenium script data driven, I bumped with TestNG framework. This is a wonderful framework which makes the life easier when one has to implement the data driven framework.

The framework provides many annotations – @BeforeClass, @ BeforeTest, @BeforeMethod, @Test and all these with @After keywords.

So there was no need to have main() and drive the tests from there. More importantly, there was no need to write complex line of codes for reading data from excel. TestNG provides @DataProvider annotation which will iterate our corresponding @Test as many number of times as the number of rows of test data is present in the excel file. Please visit TestNG site for a detailed understanding of the features of it.

Now, my script (written to automate the account opening functionality in a core banking application called Flexcube) looked somewhat like this –

Class SomeClassName

{

@BeforeTest

Function to setup the environment, open url;

@Test

line of code to open account;

}

The following were the drawbacks that I observed:

  1. I was not following the rules of OOP again. Everything was declared as and when required. Test data was hard coded, as my plan was to implement @DataProvider at a later point of time once the script was ready.
  2. No code reusage
  3. Everything was driven from @Test.
  4. Any change in the script was painful task, as the program was almost looking like that written in procedural Language such as C.
  5. Finally, the @DataProvider – There was no way i could implement it here given that the lines of code which required data was scattered all through the program aimlessly.

So I spent hours together to design a program which would include the best practices of both – the OOP features and the TestNG features. And finally I have achieved it to a certain extent with the help of inheritance, abstraction and encapsulation. The program now looks somewhat like this ;

(due to some security issues, removed the code)

Looking at the above, its not difficult to makeout that if i use the @DataProvider, all that needs to be done is to enclose the single liner code in a function, such that it gets data from the data provider function. This data can then be used to call the function for which the parameters passed will be the data recieved form the data provider. The data provider function will have the line of codes to handle the array which will read and store the value from excel.