Saturday, September 28, 2019

Post#128.Data driven Testing using TestNG


TestNG Data Providers
Data Provider feature helps you to write data-driven tests, which essentially means that same test method can be run multiple times with different data-sets. It helps in providing complex parameters to the test methods as it is not possible to do this from testng.xml file.
Please note that @DataProvider is the second way of passing parameters to test methods (first way we already discussed in @Parameters example).

You can use it to handle a broad range of complex parameters like the following.
§  Java objects.
§  Objects read from a database.
§  Data from Excel or property file etc.

Facts about “@dataprovider”:
§  This annotation has one string attribute which is its name. If you don’t specify a name, then the method’s name serves as the default name.
§  A data provider method prepares and returns a 2-d list of objects by default.
§  A data-driven test would run once for each set of data specified by the data provider object.

To use the DataProvider feature in your tests you have to declare a method annotated by @DataProvider and then use the said method in the test method using the ‘dataProvider‘ attribute in the Test annotation.

1) Using @DataProvider and Test in Same Class
The below test class contains a test method which takes one argument as input and prints it to console when executed. A DataProvider method is also available in the same class by using the @DataProvider annotation of TestNG. The name of the said DataProvider method is mentioned using the name attribute of the @DataProviderannotation. The DataProvider returns a double Object class array with two sets of data i.e. “Sujoy” and “Ankit”.
package DataProvider;

import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class DataProviderEx {
            @DataProvider(name = "data-provider")
    public Object[][] dataProviderMethod() {
                        //Created two dimensional array with 2 rows and 1 columns.
                          //2 rows represents test has to run 2 times.
                          //1 columns represents 1 data parameters.

                          Object[][] Cred = new Object[2][1];
                          Cred[0][0] = "Sujoy";
                          Cred[1][0] = "Ankit";
                          return Cred;
    }

    @Test(dataProvider = "data-provider")
    public void testMethod(String data) {
        System.out.println("Data is: " + data);
    }
}
Now run above test. Output of above test run is given below:
Data is: Sujoy
Data is: Ankit

PASSED: testMethod("Sujoy")
PASSED: testMethod("Ankit")
As you can see from the above test result the respective test method in the class was executed two times. The execution of the test method is dependent upon the number of data-sets passed by the DataProvider method, in this case as two different sets of data were returned by the DataProvider, the test method was executed two times.

2) Using @DataProvider and Test in Different Class
To understand this, add two classes with the names DataProviderClass and TestClass as below.

DataProvider.java

import org.testng.annotations.DataProvider;

public class DataProviderClass
{
    @DataProvider(name = "data-provider")
    public static Object[][] dataProviderMethod()
    {
        return new Object[][] { { "data one" }, { "data two" } };
    }
}

TestClass.java

import org.testng.annotations.Test;

public class TestClass
{
    @Test(dataProvider = "data-provider", dataProviderClass = DataProviderClass.class)
    public void testMethod(String data)
    {
        System.out.println("Data is: " + data);
    }
}

Now run above test. Output of above test run is given below:
Data is: data one
Data is: data two
PASSED: testMethod("data one")
PASSED: testMethod("data two")

As you can see from the above test results the test method was executed two times depending upon the data passed to it by DataProvider method. In this scenario the DataProvider method was in a different class. In such a case the dataProviderMethod() has to be declared static so that it can be used by a test method in a different class for providing data.

Real-time Example:
Navigate to http://newtours.demoaut.com/  and Login with different set of test Data.
package Testng_Pack;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class Sample_Login {
  WebDriver driver = new FirefoxDriver();
  @BeforeTest
    public void setup() throws Exception {
         driver.manage().window().maximize();
         driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
         driver.get("http://newtours.demoaut.com/");
    }
   @AfterTest
 public void tearDown() throws Exception {
   driver.quit();
     }
  //This method will return two dimensional array.
 //This method behaves as data provider for LogIn_Test method.
 @DataProvider
 public Object[][] LoginCredentials(){
  //Created two dimensional array with 4 rows and 2 columns.
  //4 rows represents test has to run 4 times.
  //2 columns represents 2 data parameters.
  Object[][] Cred = new Object[4][2];
  Cred[0][0] = "UserId1";
  Cred[0][1] = "Pass1";
  Cred[1][0] = "UserId2";
  Cred[1][1] = "Pass2";
  Cred[2][0] = "UserId3";
  Cred[2][1] = "Pass3";
  Cred[3][0] = "UserId4";
  Cred[3][1] = "Pass4";
  return Cred; //Returned data
 }
  //Give data provider method name as data provider.
 //Passed 2 string parameters as LoginCredentials() returns 2 parameters In object.
 @Test(dataProvider="LoginCredentials")
 public void LogIn_Test(String Usedid, String Pass){
   driver.findElement(By.name("userName")).clear();
driver.findElement(By.name("userName")).sendKeys(Usedid);
   driver.findElement(By.name("password")).clear();
      driver.findElement(By.name("password")).sendKeys(Pass);
   driver.findElement(By.name("login")).click();
   driver.findElement(By.linkText("Home")).click();
  System.out.println("Clicked Successfully");
  }
}


No comments:

Post a Comment