DataProvider - Data Driven Testing with Selenium and TestNG (original) (raw)
Data-Driven testing generally means executing a set of steps with multiple sets of data.
Selenium does not provide any out-of-the box solution for data driven testing but leaves it up to the user to implement this on his own. People who are familiar with QuickTest Professional or QTP would know Datatables (Global & Action) that allows the scripter to link a action or a function with multiple rows of data.
TestNG is a framework that makes data-driven testing possible in selenium. TestNG is a testing framework created in line with Junit but with added features that makes it suitable for use in regression test automation projects. DataProvider is one such feature in testng; it allows a test method to be executed with multiple sets of data.
A DataProvider is data feeder method defined in your class that supplies a test method with data. You may hook up any test method with a DataProvider and make the test method execute once for every row of your test data.
@DataProvider(name = "DP1")
public Object[][] createData() {
Object[][] retObjArr={{"001","Jack","London"},
{"002","John","New York"},
{"003","Mary","Miami"},
{"004","George","california"}};
return(retObjArr);
}
@Test (dataProvider = "DP1")
public void testEmployeeData(String empid, String empName, String city){
selenium.type("id", empid);
selenium.type("name", empName);
selenium.click("submit_button");
selenium.waitForPageToLoad("30000");
assertTrue(selenium.isTextPresent(city));
}
In the example above createData() is the DataProvider function that is sending out test data in the form of array of array of objects (object[][]). The test method testEmployeeData() hooks onto the DataProvider by declaring that its data should be supplied by the DataProvider named "DP1". On execution testEmployeeData() will be executed 4 times, once with each row of object[][]. Note that the dimension of the array returned by the DataProvider must match the parameter type of the test method. This means if your test method takes 3 parameters then array returned by the DataProvider must have its second dimension equal to 3. Try to visualize the array of array as a table where each row constitutes one test case.
In the example above the test data is defined withing the DataProvider function. But ideally you want to keep your test data in spreadsheet like media and not in the test script. To achieve this instead of declaring the test data array within the DataProvider function we should call a function that fetches the data from an excel sheet and returns an array of array object to the DataProvider.
I will share with you my way of storing data in XL sheets. I store test data in the form of tables within an excel sheet. There could be any number of tables within an excel sheet. Each table is marked by an startTag and an endTag. The startTag and endTag is the Name of the table. The startTag is placed one cell diagonally above the cell from where the first row of table data begins. And the endTag is placed one cell diagonally below the cell from where last row of table data ends. A table always begins with a column header row although this row is just for our understanding and is ignored in the computation. Below is the image of a sample test data excel sheet. Click on the image to see a bigger version of it. Also below the image you can see the google doc with the test data I will use in an example later in this post.
Below is the function that fetches the table from the excel sheet and returns it as an array of array of String type. It uses Java Excel API to fetch data from excel sheet.
It takes 3 parameters
1. xlFilePath - the path of XL file/workbook containing the data, the path is relative to java project
2. sheetName- name of the xl sheet that contains the table
3. tableName- Name of the table that you wish to fetch
The function returns a String type array of array.
public String[][] getTableArray(String xlFilePath, String sheetName, String tableName){
String[][] tabArray=null;
try{
Workbook workbook = Workbook.getWorkbook(new File(xlFilePath));
Sheet sheet = workbook.getSheet(sheetName);
int startRow,startCol, endRow, endCol,ci,cj;
Cell tableStart=sheet.findCell(tableName);
startRow=tableStart.getRow();
startCol=tableStart.getColumn();
Cell tableEnd= sheet.findCell(tableName, startCol+1,startRow+1, 100, 64000, false);
endRow=tableEnd.getRow();
endCol=tableEnd.getColumn();
System.out.println("startRow="+startRow+", endRow="+endRow+", " +
"startCol="+startCol+", endCol="+endCol);
tabArray=new String[endRow-startRow-1][endCol-startCol-1];
ci=0;
for (int i=startRow+1;i<endRow;i++,ci++){
cj=0;
for (int j=startCol+1;j<endCol;j++,cj++){
tabArray[ci][cj]=sheet.getCell(j,i).getContents();
}
}
}
catch (Exception e) {
System.out.println("error in getTableArray()");
}
return(tabArray);
}
Now we will put all of this together in an example. We will keep the test data in excel sheets and use the above function to fetch from it.
Note:
1. testng jar should be in the class path. You may download the latest testng jar file from here.
2. testng eclipse plugin must be installed. Get it from the same location as the testng jar file mentioned above.
3. jxl jar should be in the class path Java Excel API. You can get this from here. Download the jexcelapi.zip, unzip to get the jxl.jar
4. Selenium-server and selenium-java-client-driver and junit jar (selenium classes need junit) files must in class path.
5. The file data1.xls is kept at test\\Resources\\Data\\data1.xls
I have attached this file to the blog as a google doc, please copy paste its contents to a excel file. Rename the excel-sheet to DataPool and the save the excel file as data.xls. The path mentioned is relative to the project.
The test method testDataProviderExample() below navigates to www.imdb.com and performs search for movie titles. On the movie details page it verifies the presence of director name, movie plot and the name of the lead actor. This routine is repeated for all the rows of the test-data table.
import com.thoughtworks.selenium.*;
import org.junit.AfterClass;
import org.openqa.selenium.server.SeleniumServer;
import org.testng.annotations.*;
import java.io.File;
import jxl.*;
public class DataProviderExample extends SeleneseTestCase{
@BeforeClass
public void setUp() throws Exception {
SeleniumServer seleniumserver=new SeleniumServer();
seleniumserver.boot();
seleniumserver.start();
setUp("http://www.imdb.com/", "*firefox");
selenium.open("/");
selenium.windowMaximize();
selenium.windowFocus();
}
@DataProvider(name = "DP1")
public Object[][] createData1() throws Exception{
Object[][] retObjArr=getTableArray("test\\Resources\\Data\\data1.xls",
"DataPool", "imdbTestData1");
return(retObjArr);
}
@Test (dataProvider = "DP1")
public void testDataProviderExample(String movieTitle,
String directorName, String moviePlot, String actorName) throws Exception {
//enter the movie title
selenium.type("q", movieTitle);
//they keep switching the go button to keep the bots away
if (selenium.isElementPresent("nb15go_image"))
selenium.click("nb15go_image");
else
selenium.click("xpath=/descendant::button[@type='submit']");
selenium.waitForPageToLoad("30000");
//click on the movie title in the search result page
selenium.click("xpath=/descendant::a[text()='"+movieTitle+"']");
selenium.waitForPageToLoad("30000");
//verify director name is present in the movie details page
verifyTrue(selenium.isTextPresent(directorName));
//verify movie plot is present in the movie details page
verifyTrue(selenium.isTextPresent(moviePlot));
//verify movie actor name is present in the movie details page
verifyTrue(selenium.isTextPresent(actorName));
}
@AfterClass
public void tearDown(){
selenium.close();
selenium.stop();
}
public String[][] getTableArray(String xlFilePath, String sheetName, String tableName) throws Exception{
String[][] tabArray=null;
Workbook workbook = Workbook.getWorkbook(new File(xlFilePath));
Sheet sheet = workbook.getSheet(sheetName);
int startRow,startCol, endRow, endCol,ci,cj;
Cell tableStart=sheet.findCell(tableName);
startRow=tableStart.getRow();
startCol=tableStart.getColumn();
Cell tableEnd= sheet.findCell(tableName, startCol+1,startRow+1, 100, 64000, false);
endRow=tableEnd.getRow();
endCol=tableEnd.getColumn();
System.out.println("startRow="+startRow+", endRow="+endRow+", " +
"startCol="+startCol+", endCol="+endCol);
tabArray=new String[endRow-startRow-1][endCol-startCol-1];
ci=0;
for (int i=startRow+1;i<endRow;i++,ci++){
cj=0;
for (int j=startCol+1;j<endCol;j++,cj++){
tabArray[ci][cj]=sheet.getCell(j,i).getContents();
}
}
return(tabArray);
}
}//end of class
Just copy paste the above in a java file, reference the necessary jars in the build path, put the test-data excel file in the correct location and it should work just fine. To run right click the java file in eclipse and select Run As-->TestNG Test.
Watch video of how to create a data driven test script from scratch step by step
Part 1
Part 2
Part 3
Part 4
Feel free to post queries here.
edit on 10 july 2010: removed try/catch from getTableArray(), it's easier to debug spreadsheet file name/sheet name mismatch this way.