Sunday, October 9, 2016

Data Driven Testing with TestNG framework using Apache POI (Excel)

Data Driven Testing using Excel in TestNG

Quite simply put, data-driven testing is when you store test data (input, expected output, etc) in some external storage (database, spreadsheet, xml-files, etc) and then use that data iteratively in your tests when running them.

 We will use Apache Poi(Excel) to drive data from Excel spreadsheet.
Apache POI (Excel) and TestNG Data Providers to accomplish this in TestNG Framework. Let's get started.

Step 1: Create a test case of Login Application with TestNG Data Provider.
Step 2:  Create a Test Data sheet.
Step 3: Create functions to Open & Read data from Excel
Step 4: Create a TestNg test case for accepting data from Excel using Data Provider.
Step 5: Run the test against the Test Case name in the Test Data file.

I am going to use same class from previous post, 'DataProvider' class code and the code from previous post is below --

package automationFramework;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.safari.SafariDriver;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class DataProviderTest {
    public static WebDriver sDriver = new SafariDriver();
   
  @DataProvider(name= "LoginValidation")
  public static Object[][] credentials() {
 return new Object[][] { { "user1", "pass1" }, { "user2", "pass2" }};

}
  @Test(dataProvider="LoginValidation")
  public void testOne(String sUsername,String sPassword ) throws InterruptedException {
      sDriver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
      //Open website
      sDriver.get("http://amazon.com");
      //Verify Page title
      WebElement myAccountLink = sDriver.findElement(By.id("nav-link-yourAccount"));
     
      //Adding assertion check here. Test will only continue if below statement is True.
      Assert.assertTrue(myAccountLink.isDisplayed());
      //My Account Link will be clicked only if the above condition is true
      myAccountLink.click();
     
      Thread.sleep(1000);
      sDriver.findElement(By.xpath(".//*[@id='ap_email']")).sendKeys(sUsername);
      sDriver.findElement(By.xpath(".//*[@id='ap_password']")).sendKeys(sPassword);
      sDriver.findElement(By.xpath(".//*[@id='signInSubmit']")).click();
  }
}









Next, Create excel spreadsheet with test data.. I created below spreadsheet -

Next, Setup Apache POI library, which allows you to read, create and edit MS Office documents using Java. Follow below steps to install, setup and implement POI Libraries.

1. Download POI libraries here - https://poi.apache.org/download.html




 

Add all the Jar files to Eclipse Project. 


2. Next , Create a New Package file in the Project and name it as ‘testData’, by right click on the Project and select New > Package
Place all of your test data in this folder (package) whether it is a sql file, excel file or anything meaning, save your testData file into this Package location





3. Create new Package called 'utility' and inside the package create a new Constant Class 'Constant' and store the value of testData package path & Excel file name


Create a new Class in Utility package and ‘ExcelUtils‘ that include basic read/write methods. Copy and paste below read/write basic excel reader code.

 The folder so far should look like this - 

Now that XLS reader is ready. Let's modify the DataProviderTest class  to accept the test data from excel file.

4. Create a TestNg test case and under Annotations, check ‘@BeforeMethod‘, ‘@AfterMethod‘ & ‘DataProvider‘ and click Finish. By default it will looks like this.. We need to modify it now.

Add a method Login_data() to your Test class. This method takes two strings as input parameters.
Next, Divide the test cases into 3 parts -
@BeforeMethod : Launch Firefox and direct it to the Base URL
@Test : Enter Username & Password to Login, Print console message and Log out
@AfterMethod : Close Firefox browser
Test Case will look like this:

package utility;
import java.io.FileInputStream;
        import java.io.FileNotFoundException;
        import java.io.FileOutputStream;
        import java.io.IOException;
        import org.apache.poi.xssf.usermodel.XSSFCell;
        import org.apache.poi.xssf.usermodel.XSSFRow;
        import org.apache.poi.xssf.usermodel.XSSFSheet;
        import org.apache.poi.xssf.usermodel.XSSFWorkbook;
    public class ExcelUtils {
            private static XSSFSheet ExcelWSheet;
            private static XSSFWorkbook ExcelWBook;
            private static XSSFCell Cell;
            private static XSSFRow Row;
        //This method is to set the File path and to open the Excel file, Pass Excel Path and Sheetname as Arguments to this method
        public static void setExcelFile(String Path,String SheetName) throws Exception {
               try {
                    // Open the Excel file
                    FileInputStream ExcelFile = new FileInputStream(Path);
                    // Access the required test data sheet
                    ExcelWBook = new XSSFWorkbook(ExcelFile);
                    ExcelWSheet = ExcelWBook.getSheet(SheetName);
                    } catch (Exception e){
                        throw (e);
                    }
            }
        public static Object[][] getTableArray(String FilePath, String SheetName, int iTestCaseRow)    throws Exception
        { 
           String[][] tabArray = null;
           try{
               FileInputStream ExcelFile = new FileInputStream(FilePath);
               // Access the required test data sheet
               ExcelWBook = new XSSFWorkbook(ExcelFile);
               ExcelWSheet = ExcelWBook.getSheet(SheetName);
               int startCol = 1;
               int ci=0,cj=0;
               int totalRows = 1;
               int totalCols = 2;
               tabArray=new String[totalRows][totalCols];
                   for (int j=startCol;j<=totalCols;j++, cj++)
                   {
                       tabArray[ci][cj]=getCellData(iTestCaseRow,j);
                       System.out.println(tabArray[ci][cj]);
                   }
            }
            catch (FileNotFoundException e)
            {
                System.out.println("Could not read the Excel sheet");
                e.printStackTrace();
            }
            catch (IOException e)
            {
                System.out.println("Could not read the Excel sheet");
                e.printStackTrace();
            }
            return(tabArray);
        }
        //This method is to read the test data from the Excel cell, in this we are passing parameters as Row num and Col num
        public static String getCellData(int RowNum, int ColNum) throws Exception{
           try{
              Cell = ExcelWSheet.getRow(RowNum).getCell(ColNum);
              String CellData = Cell.getStringCellValue();
              return CellData;
              }catch (Exception e){
                return"";
                }
            }
        public static String getTestCaseName(String sTestCase)throws Exception{
            String value = sTestCase;
            try{
                int posi = value.indexOf("@");
                value = value.substring(0, posi);
                posi = value.lastIndexOf(".");  
                value = value.substring(posi + 1);
                return value;
                    }catch (Exception e){
                throw (e);
                        }
            }
        public static int getRowContains(String sTestCaseName, int colNum) throws Exception{
            int i;
            try {
                int rowCount = ExcelUtils.getRowUsed();
                for ( i=0 ; i<rowCount; i++){
                    if  (ExcelUtils.getCellData(i,colNum).equalsIgnoreCase(sTestCaseName)){
                        break;
                    }
                }
                return i;
                    }catch (Exception e){
                throw(e);
                }
            }
        public static int getRowUsed() throws Exception {
                try{
                    int RowCount = ExcelWSheet.getLastRowNum();
                    return RowCount;
                }catch (Exception e){
                    System.out.println(e.getMessage());
                    throw (e);
                }
            }
}


Now Update DataProviderWithExcel class

package automationFramework;
import org.testng.annotations.Test;
import utility.ExcelUtils;
import org.testng.annotations.BeforeMethod;
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.safari.SafariDriver;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.DataProvider;

public class DataProviderWithExcel {
WebDriver sDriver;
private String sTestCaseName;
private int iTestCaseRow;
@BeforeMethod
public void beforeMethod() {
 sDriver = new SafariDriver();
 sDriver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
 //Open website
 sDriver.get("http://amazon.com");
 }
 
  @Test(dataProvider = "LoginValidation")
  public void credentials(String sUsername, String sPassword) throws  Exception{
 
 //Verify Page title
 WebElement myAccountLink = sDriver.findElement(By.id("nav-link-yourAccount"));
 
 //Adding assertion check here. Test will only continue if below statement is True.
 Assert.assertTrue(myAccountLink.isDisplayed());
 //My Account Link will be clicked only if the above condition is true
 myAccountLink.click();
 System.out.println("My Account is clicked");
 Thread.sleep(1000);
 sDriver.findElement(By.xpath(".//*[@id='ap_email']")).sendKeys(sUsername);
 System.out.println("UserName is: " + sUsername);
 sDriver.findElement(By.xpath(".//*[@id='ap_password']")).sendKeys(sPassword);
 System.out.println("Password is: " +sPassword);
 sDriver.findElement(By.xpath(".//*[@id='signInSubmit']")).click();  
  }
  @AfterMethod
  public void afterMethod() {
 sDriver.close();
  }
  @DataProvider
  public Object[][] LoginValidation() throws Exception{
 
   // Setting up the Test Data Excel file
ExcelUtils.setExcelFile("//Users//User//Documents//workspace//Java//localFramework//src//testData//TestData.xlsx","Sheet1");
sTestCaseName = this.toString();
  // From above method we get long test case name including package and class name etc.
  // The below method will refine your test case name, exactly the name use have used
  sTestCaseName = ExcelUtils.getTestCaseName(this.toString());
   // Fetching the Test Case row number from the Test Data Sheet
   // Getting the Test Case name to get the TestCase row from the Test Data Excel sheet
iTestCaseRow = ExcelUtils.getRowContains(sTestCaseName,0);

   Object[][] testObjArray = ExcelUtils.getTableArray("//Users//User//Documents//workspace//Java//localFramework//src//testData//TestData.xlsx","Sheet1",iTestCaseRow);
    return (testObjArray);

}
}

Wednesday, October 5, 2016

Parameterization in TestNG and TestNG DataProviders

TestNG Parameters

There are times when we would like to run our tests against different data sets. Instead of hard coding the data set within tests itself, it will be more appropriate if we could pass our data as parameters to the test method. Thus the test logic remains same but the data on which the test is run changes and this is called data-driven testing.
One of the most important features of TestNG is its data-driven testing. It allows the user to pass parameter values to the test method as arguments, so the test ends up running for each data-set passed in.
TestNG supports two different ways of injecting parameter values.
  1. Parameterization through testng.xml
  2. DataProvider

In most cases, you'll come across a scenario where the business logic requires a hugely varying number of tests. Parameterized tests allow developers to run the same test over and over again using different values.

Passing Parameters with testng.xml 
With this technique, you define the simple parameters in the testng.xml file and then reference those parameters in the source files. Let us have an example to demonstrate how to use this technique to pass parameters.

I am going to create new TestNG class 'ParametrizationTest', Open Amazon site and try logging in by passing username and password as parameters.

Add the annotation @Parameters("myName") to this method. The parameter would be passed a value from testng.xml

package automationFramework;
import org.testng.annotations.Parameters;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.safari.SafariDriver;
import org.testng.Assert;
import org.testng.annotations.Test;

public class ParametrizationTest {
    public static WebDriver sDriver = new SafariDriver();
  @Test
  @Parameters({"sUsername","sPassword"})
  public void testOne(String sUsername, String sPassword) throws InterruptedException {
      sDriver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
      //Open website
      sDriver.get("http://amazon.com");
      //Verify Page title
      WebElement myAccountLink = sDriver.findElement(By.id("nav-link-yourAccount"));
     
      //Adding assertion check here. Test will only continue if below statement is True.
      Assert.assertTrue(myAccountLink.isDisplayed());
      //My Account Link will be clicked only if the above condition is true
      myAccountLink.click();
     
      Thread.sleep(1000);
      sDriver.findElement(By.xpath(".//*[@id='ap_email']")).sendKeys(sUsername);
      sDriver.findElement(By.xpath(".//*[@id='ap_password']")).sendKeys(sPassword);
      sDriver.findElement(By.xpath(".//*[@id='signInSubmit']")).click();
     
  }
}



Next, Pass the Parameters in testng.xml and run it. The output will look like this-


 


TestNG DataProviders

Passing Parameters with Dataproviders

When you need to pass complex parameters or parameters that need to be created from Java (complex objects, objects read from a property file or a database, etc.), parameters can be passed using Data providers. A Data Provider is a method annotated with @DataProvider. This annotation has only one string attribute: its name. If the name is not supplied, the data provider’s name automatically defaults to the method’s name. A data provider returns an array of objects.
The following examples demonstrate how to use data providers.

 Let's start by creating a new TestNG class 'DataProviderTest'

1)  Define the method logons() which is defined as a Dataprovider using the annotation. This method returns array of object array.

2) Add a method test() to your DataProviderTest class. This method takes two strings as input parameters.

3) Add the annotation @Test(dataProvider = “LoginValidation”) to this method. The attribute dataProvider is mapped to “LoginValidation”.

package automationFramework;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.safari.SafariDriver;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class DataProviderTest {
    public static WebDriver sDriver = new SafariDriver();
   
  @DataProvider(name= "LoginValidation")
  public static Object[][] credentials() {
 return new Object[][] { { "user1", "pass1" }, { "user2", "pass2" }};

}
  @Test(dataProvider="LoginValidation")
  public void testOne(String sUsername,String sPassword ) throws InterruptedException {
      sDriver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
      //Open website
      sDriver.get("http://amazon.com");
      //Verify Page title
      WebElement myAccountLink = sDriver.findElement(By.id("nav-link-yourAccount"));
     
      //Adding assertion check here. Test will only continue if below statement is True.
      Assert.assertTrue(myAccountLink.isDisplayed());
      //My Account Link will be clicked only if the above condition is true
      myAccountLink.click();
     
      Thread.sleep(1000);
      sDriver.findElement(By.xpath(".//*[@id='ap_email']")).sendKeys(sUsername);
      sDriver.findElement(By.xpath(".//*[@id='ap_password']")).sendKeys(sPassword);
      sDriver.findElement(By.xpath(".//*[@id='signInSubmit']")).click(); 
  }
}

 
Run testng.xml file and see the Test Result. The output will look like this and it will show all the parameters - 




 

TestNG Asserts example and explanation

Assertions in TestNG

Asserts helps us to verify the conditions of the test and decide whether test has failed or passed. A test is considered successful ONLY if it is completed without throwing any exception.

There will be many situations in the test where you just like to check the presence of an element. All you need to do is to put an assert statement on to it to verify its existence.

Here we are verifying if the page title is equal to 'Google' or not. If the page title is not matching with the text / title that we provided, it will fail the test case.

Different Asserts Statements
1) Assert.assertTrue() & Assert.assertFalse()

To explain you what is assertion, lets us look into below code sample.
I am going to create new TestNG class 'AssertTest'.

package automationFramework;

import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.safari.SafariDriver;
import org.testng.Assert;
import org.testng.annotations.Test;

public class AssertTest {
    public static WebDriver sDriver = new SafariDriver();
   
  @Test
  public void testOne() throws InterruptedException {
      sDriver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
      //Open website
      sDriver.get("http://amazon.com");
      //Verify Page title
      WebElement myAccountLink = sDriver.findElement(By.id("nav-link-yourAccount"));
     
      //Adding assertion check here. Test will only continue if below statement is True.
      Assert.assertTrue(myAccountLink.isDisplayed());
    //My Account Link will be clicked only if the above condition is true
      myAccountLink.click();
     
      Thread.sleep(1000);
  }
}


Let's run the code and verify the output.

 Assert.assertFalse() works opposite of Assert.assertTrue(). It means that if you want your test to continue only if when some certain element is not present on the page. You will use Assert false, so it will fail the test in case of the element present on the page.


Like wise there are many Assertions provided by the TestNG. The below are the few which are used commonly.
assertEqual(String actual,String expected) :- It takes two string arguments and checks whether both are equal, if not it will fail the test.

assertEqual(String actual,String expected, String message) :- It takes three string arguments and checks whether both are equal, if not it will fail the test and throws the message which we provide.
assertEquals(boolean actual,boolean expected) :- It takes two boolean arguments and checks whether both are equal, if not it will fail the test.

assertEquals(java.util.Collection actual, java.util.Collection expected, java.lang.String message) :- Takes two collection objects and verifies both collections contain the same elements and with the same order. if not it will fail the test with the given message.

Assert.assertTrue(condition) :- It takes one boolean arguments and checks that a condition is true, If it isn't, an AssertionError is thrown.

Assert.assertTrue(condition, message) :- It takes one boolean argument and String message. It Asserts that a condition is true. If it isn't, an AssertionError, with the given message, is thrown.

Assert.assertFalse(condition) :- It takes one boolean arguments and checks that a condition is false, If it isn't, an AssertionError is thrown.

Assert.assertFalse(condition, message) :- It takes one boolean argument and String message. It Asserts that a condition is false. If it isn't, an AssertionError, with the given message, is thrown.

Selenium Logging using Log4j and TestNG Reporter Logger

I am going to show couple of ways to perform logging using Log4j as well as TestNG Reporter.

Let's start with create new TestNG class 'LoggingDemo'. I am just writing single test to open amazon.com website and clicking on Account link.

Install log4j from http://logging.apache.org/log4j/2.x/index.html. I am using log4j 2 in this example.
After the download is complete, Add Log4j jar libraries to eclipse project just like we added selenium jars.


Initialize log4j and TestNG reporter log and I am going to use both in this class.

package automationFramework;

import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.apache.commons.logging.Log;
import org.apache.log4j.xml.DOMConfigurator;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.safari.SafariDriver;
import org.testng.Reporter;
import org.testng.annotations.Test;

public class LoggingDemo {
    private static WebDriver sDriver = new SafariDriver();
    private static Logger Log = Logger.getLogger(Log.class.getName());
   
  @Test
  public static void testOne() throws InterruptedException {
     
      Log.info("New driver has been initiated");
      DOMConfigurator.configure("log4j.xml");
      sDriver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
      Log.info("Implicit wait applied on the driver for 10 seconds");
      sDriver.get("http://amazon.com");
      Log.info("Web application launched");
     
      // Let's set TestNG reporter log now.
      Reporter.log("Application Lauched successfully....");
      sDriver.findElement(By.id("nav-link-yourAccount")).click();
      Log.info("Click action performed on My Account link");
      Thread.sleep(1000);
      sDriver.quit();
      Log.info("Browser closed");
     
      // This is the third main event
      Reporter.log("User is Logged out and Application is closed...");
  }
}


Log4j output will look like this in console -

Oct 05, 2016 11:54:57 AM automationFramework.LoggingDemo testOne
INFO: New driver has been initiated
Oct 05, 2016 11:54:57 AM automationFramework.LoggingDemo testOne
INFO: Implicit wait applied on the driver for 10 seconds
Oct 05, 2016 11:54:59 AM automationFramework.LoggingDemo testOne
INFO: Web application launched
Oct 05, 2016 11:54:59 AM automationFramework.LoggingDemo testOne
INFO: Click action performed on My Account link
Oct 05, 2016 11:55:00 AM automationFramework.LoggingDemo testOne
INFO: Browser closed

 
Now, Let's see TestNG Reporter log by going to output folder and click on 'Reporter output'


Log4J is low level logging whereas TestNG Reporter logger is high level logging.
 

TestNG Prioritizing/Sequencing and Skipping a Test Case

In TestNG "Priority" is used to schedule the test cases. When there are multiple test cases, we want to execute test cases in order. Like First we need to execute a test case "Registration" before login.
In order to achive, we use need to add annotation as @Test(priority=??).

If you don't mention the priority, it will take all the test cases as "priority=0" and execute.
If we define priority as "priority=", these test cases will get executed only when all the test cases which don't have any priority as the default priority will be set to "priority=0"

Let's create a new TestNG class 'MultipleTestCases' without setting Priority and execute it without setting.
Note - By default, methods annotated by @Test are executed alphabetically. Take a look over the next topic to see how to prioritize @Test.

package automationFramework;

import org.openqa.selenium.WebDriver;
import org.testng.annotations.Test;

public class MultipleTestCases {
    public WebDriver sDriver;
  @Test
  public void testOne() {
      System.out.println("This is test One");
  }
  @Test
  public void testTwo() {
      System.out.println("This is test Two");
  }
  @Test
  public void testThree(){
      System.out.println("This is test Three");
  }
  @Test
  public void testFour(){
      System.out.println("This is test four");
  }
}


Update TestNG.xml and execute the test.

<suite name = "Test - Suite">
    <test name="website QA">
        <classes>
            <class name="automationFramework.MultipleTestCases" />
        </classes>
    </test>
</suite>


The output will be like this -


So like I mentioned above, Without setting priority Test cases are executed in alphabetical order.
Now let's set Priority in the above example and run the test again.

 package automationFramework;

import org.openqa.selenium.WebDriver;
import org.testng.annotations.Test;

public class MultipleTestCases {
    public WebDriver sDriver;
  
  @Test(priority = 0)
  public void testOne() {
      System.out.println("This is test One");
  }
  @Test(priority = 1)
  public void testTwo() {
      System.out.println("This is test Two");
  }
  @Test(priority=2)
  public void testThree(){
      System.out.println("This is test Three");
  }
  @Test(priority = 3)
  public void testFour(){
      System.out.println("This is test four");
  }
}





Skipping Test Case

Sometimes, it happens that our code is not ready and the test case written to test that method/code fails. In such cases, annotation @Test(enabled = false) helps to disable this test case.
If a test method is annotated with @Test(enabled = false), then the test case that is not ready to test is bypassed.
Now, let's see @Test(enabled = false) in action.

To use two or more parameters in a single annotation, separate them with a comma:
@Test(priority = 3, enabled = false)

Let's continue to use 'MutipleTestCases' class and SKIP testcase 1 and testcase 2 and see the output.

package automationFramework;

import org.openqa.selenium.WebDriver;
import org.testng.annotations.Test;

public class MultipleTestCases {
    public WebDriver sDriver;
   
  @Test(priority = 0)
  public void testOne() {
      System.out.println("This is test One");
  }
  @Test(priority = 1, enabled = false)
  public void testTwo() {
      System.out.println("This is test Two");
  }
  @Test(priority=2, enabled = false)
  public void testThree(){
      System.out.println("This is test Three");
  }
  @Test(priority = 3)
  public void testFour(){
      System.out.println("This is test four");
  }
}


 And the output is -


Tuesday, October 4, 2016

Annotations in Selenium TestNG, Test Case Grouping and Dependent Test Case

In this blog, I am going to focus on the importance of different types of annotations and their usage.


Before writing test scripts or setting up a project, we should know the hierarchy in which the annotations work. The execution will always remain the same.


For example, compile and run the below script and notice the execution order. It will be as following:
  • BeforeSuite
  • BeforeTest
  • BeforeClass
  • BeforeMethod
  • Test Case 1
  • AfterMethod
  • BeforeMethod
  • Test Case 2
  • AfterMethod
  • AfterClass
  • AfterTest
  • AfterSuite
Let's consider below example -

import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
public class Sequencing {
@Test
public void testCase1() {
System.out.println("This is the Test Case 1");
}
@Test
public void testCase2() {
System.out.println("This is the Test Case 2");
}
@BeforeMethod
public void beforeMethod() {
System.out.println("This will execute before every Method");
}
@AfterMethod
public void afterMethod() {
System.out.println("This will execute after every Method");
}
@BeforeClass
public void beforeClass() {
System.out.println("This will execute before the Class");
}
@AfterClass
public void afterClass() {
System.out.println("This will execute after the Class");
}
@BeforeTest
public void beforeTest() {
System.out.println("This will execute before the Test");
}
@AfterTest
public void afterTest() {
System.out.println("This will execute after the Test");
}
@BeforeSuite
public void beforeSuite() {
System.out.println("This will execute before the Test Suite");
}
@AfterSuite
public void afterSuite() {
System.out.println("This will execute after the Test Suite");
}
}
Output of the above code will be like this:


It is clearly visible that the @Suite annotation is the very first and the very lastly executed. Then @Test followed by @Class. Now if you notice, the @Method has executed twice. As @Test is a method in the class, hence @Method will always executed for each @Test method.

Test Case Grouping in TestNG

Group test is a new innovative feature in TestNG, which doesn’t exist in JUnit framework. It permits you to dispatch methods into proper portions and perform sophisticated groupings of test methods. Not only can you declare those methods that belong to groups, but you can also specify groups that contain other groups. Then, TestNG can be invoked and asked to include a certain set of groups (or regular expressions), while excluding another set. Group tests provide maximum flexibility in how you partition your tests and doesn't require you to recompile anything if you want to run two different sets of tests back to back.

Groups are specified in your testng.xml file using the <groups> tag. It can be found either under the <test> or <suite> tag. Groups specified in the <suite> tag apply to all the <test> tags underneath.

Now, let's take an example to see how group test works.

Create a new TestNG class 'ModuleASuite'. Then create 4 test methods, group tests as 'Regression' and one as 'Smoke Test'. See example below.

package com.example.group;
import org.testng.annotations.Test;
public class groupExamples {
 @Test(groups="Regression")
 public void testCaseOne()
 {
 System.out.println("Im in testCaseOne - And in Regression Group");
 }
 @Test(groups="Regression")
 public void testCaseTwo(){
 System.out.println("Im in testCaseTwo - And in Regression Group");
 }
 @Test(groups="Smoke Test")
 public void testCaseThree(){
 System.out.println("Im in testCaseThree - And in Smoke Test Group");
 }
 @Test(groups="Regression")
 public void testCaseFour(){
 System.out.println("Im in testCaseFour - And in Regression Group");
 }
}

 Now, Update the TestNG.xml file. We will execute the group “Regression” which will execute the test methods which are defined with group as “Regression”

<suite name = "Test - Suite">
    <test name="website QA">
        <groups>
            <run>
            <include name="Regression"/>
            </run>
        </groups>
        <classes>
            <class name="automationFramework.ModuleASuite" />
        </classes>
    </test>
</suite>


Run TestNG.xml and the output will be like this -







Dependent Test Case


Sometimes, you may need to invoke methods in a Test case in a particular order or you want to share some data and state between methods. This kind of dependency is supported by TestNG as it supports the declaration of explicit dependencies between test methods.
TestNG allows you to specify dependencies either with:
  • Using attributes dependsOnMethods in @Test annotations OR
  • Using attributes dependsOnGroups in @Test annotations.
Take a look over the below example:

package automationFramework;

import org.testng.annotations.Test;

public class ModuleBSuite {

      @Test (dependsOnMethods = { "OpenBrowser" })
      public void SignIn() {
          System.out.println("This will execute second (SignIn)");
      }

      @Test
      public void OpenBrowser() {
          System.out.println("This will execute first (Open Browser)");
      }

      @Test (dependsOnMethods = { "SignIn" })
      public void LogOut() {
          System.out.println("This will execute third (Log Out)");
      }
}

Update and run TestNG and the output will be like this - 

<suite name = "Test - Suite">
    <test name="website QA">
        <classes>
            <class name="automationFramework.ModuleBSuite" />
        </classes>
    </test>
</suite>





 

TestNG Selenium - Create Test Suites





In TestNG framework, we need to create testng.xml file to create and handle multiple test classes. This is the xml file where you will configure your test run, set test dependency, include or exclude any test, method, class or package and set priority etc.

Step 1 : Create a TestNG XML
1) Right click on Project folder, go to New and select ‘File‘ as shown in below image.


2) In New file wizard, add file name = ‘testng.xml‘ as shown in below given image and click on Finish button
 

3) It will add testng.xml file under your project folder.

After giving appropriate names, now your testng.xml file will looks like this:

<suite name = "Test - Suite">
    <test name="website QA">
        <classes>
            <class name="automationFramework.TestNG" />
        </classes>
    </test>
</suite>



 
Very first tag is the Suite tag<suite>, under that it is the Test tag<test> and then the Class tag<classes>. You can give any name to the suite and the test but you need to provide the correct name to the <classes> tag which is a combination of your Package name and Test Case name.

When you run testng.xml, it  will execute only those tests, which are mentioned in the testng.xml. The rest of the test cases under ‘automationFramework’ package will remain untouched.

TestNG with WebDriver Introduction and setup

TestNG is a testing framework inspired from JUnit and NUnit but introducing some new functionalities that make it more powerful and easier to use

Features of TestNG

  • Support for annotations
  • Support for parameterization
  • Advance execution methodology that do not require test suites to be created
  • Support for Data Driven Testing using Dataproviders
  • Enables user to set execution priorities for the test methods
  • Supports threat safe environment when executing multiple threads
  • Readily supports integration with various tools and plug-ins like build tools (Ant, Maven etc.), Integrated Development Environment (Eclipse).
  • Facilitates user with effective means of Report Generation using ReportNG.

TestNG is designed to cover all categories of tests:  unit, functional, end-to-end, integration, etc.

TestNG Plugin Installation in Eclipse
  1. Launch eclipse IDE -> Click on the Help option within the menu -> Select “Eclipse Marketplace” option within the dropdown.


  2. Enter the keyword “TestNG” in the search textbox and click on “Go” button as shown below. 
  3. Click on the “Go” button and click on the Install button to install TestNG.
  4. Click on “Confirm” button. Next, the application would prompt you to accept the license and then click on the “Finish” button.
  5. The installation is initiated now and the progress can be seen as following:
 Restart Eclipse. Next, Verify that TestNG appears in eclipse Preference. Click on Eclipse menu tab -> Preferences. TestNG should be visible in the Preference.




Annotations in TestNG

@BeforeSuite: The annotated method will be run before all tests in this suite have run.
@AfterSuite: The annotated method will be run after all tests in this suite have run.
@BeforeTest: The annotated method will be run before any test method belonging to the classes inside the tag is run.
@AfterTest: The annotated method will be run after all the test methods belonging to the classes inside the tag have run.
@BeforeGroups: The list of groups that this configuration method will run before. This method is guaranteed to run shortly before the first test method that belongs to any of these groups is invoked.
@AfterGroups: The list of groups that this configuration method will run after. This method is guaranteed to run shortly after the last test method that belongs to any of these groups is invoked.
@BeforeClass: The annotated method will be run before the first test method in the current class is invoked.
@AfterClass: The annotated method will be run after all the test methods in the current class have been run.
@BeforeMethod: The annotated method will be run before each test method.
@AfterMethod: The annotated method will be run after each test method.
@Test: The annotated method is a part of a test case.

Now, Let's create first TestNG class. 


Right click on src and click on TestNG -> Create TestNG class


Fill out Package name and Class name along with select couple of annotations. In this example i am using @BeforeMethod and @AfterMethod and rewriting out FirstTestCase.





Let’s take an example of FirstTestCase and divide the test case in to three parts .
@BeforeMethod : Launch Safari and direct it to the Base URL
@Test : Find Page title and print console message
@AfterMethod : Close Safari browser

package automationFramework;

import org.testng.annotations.Test;
import org.testng.annotations.BeforeMethod;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.safari.SafariDriver;
import org.testng.annotations.AfterMethod;

public class TestNG {
    public WebDriver sDriver;
   
  @Test
  public void main() {
      String pageTitle = sDriver.getTitle().toString();
      System.out.println(pageTitle);
  }
  @BeforeMethod
  public void beforeMethod() {

      // Create a new instance of the Safari driver
      sDriver = new SafariDriver();
     
      //Put a Implicit wait, this means that any search for elements on the page could take the time the implicit wait is set for before throwing exception
      sDriver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
     
      String webSiteURL = "https://www.amazon.com/";
      //Launch the website
      sDriver.get(webSiteURL);
  }

  @AfterMethod
  public void afterMethod() {
      // Close the driver
      sDriver.close();
  }
}


Run the test by right click on the test case script and select Run As > TestNG Test.

TestNG produces reports in various formats.


  



Open project folder -> test-output and view index.html, emailable-report.html. Also view Default test.html inside Default suite folder.