Showing posts with label TestNG. Show all posts
Showing posts with label TestNG. Show all posts

Wednesday, August 20, 2014

Data driven testing in Selenium WebDriver with TestNG using Excel

When we want to implement data driven testing using Excel, you need to understand how to read from an Excel sheet. You can read an Excel sheet by using Apache POI

You need to use the below jars for reading from an excel file. 
  1. poi-3.7-20101029.jar
  2. poi-ooxml-3.7-20101029.jar
  3. poi-ooxml-schemas-3.7-20101029.jar
  4. xmlbeans-2.3.0.jar
  5. dom4j-1.6.1.jar
I am using Apache POI 3.7 but you can download the latest jars from downloads page of Apache POI(http://poi.apache.org/download.html). Make sure you have added all the above jars to your project build path.

An example excel file(either .xslx or .xls formats) is given below:



The below self explanatory class is used for reading any cell of an excel sheet.
//Keywords class DataDrivenExcel.java
package example.aks.data.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

/**
 * This class allows us the use of an Excel spreadsheet to provide input data to
 * a test or set of tests.
 * 
 * @author A. K. Sahu
 * 
 */

public class DataDrivenExcel {

 private Workbook wb;
 private Sheet ws;

 /**
  * Opens a excel sheet
  * 
  * @param fileName
  *            name of the file where you want data
  * @param sheetName
  *            name of the sheet in the excel file
  */
 public DataDrivenExcel(String fileName, String sheetName) {
  try {
   if (fileName.indexOf("xlsx") < 0) { //for .xls format
    wb = new HSSFWorkbook(new FileInputStream(new File(fileName)));
    ws = wb.getSheet(sheetName);
   } else { //for .xlsx format
    wb = new XSSFWorkbook(fileName);
    ws = (XSSFSheet) wb.getSheet(sheetName);
   }
  } catch (IOException io) {
   System.err.println("Invalid file '" + fileName
     + "' or incorrect sheet '" + sheetName
     + "', enter a valid one");
  }
 }

 /**
  * Gets a cell value from the opened sheet
  * 
  * @param rowIndex
  *            starting with 0 index
  * @param columnIndex
  *            starting with 0 index
  * @return
  */
 public String getCell(int rowIndex, int columnIndex) {
  Cell cell = null;
  try {
    cell = ws.getRow(rowIndex).getCell(columnIndex);
  } catch (Exception e) {
   System.err.println("The cell with row '" + rowIndex + "' and column '"
     + columnIndex + "' doesn't exist in the sheet");
  }
  return new DataFormatter().formatCellValue(cell);
 }
}
The test class that uses the above keywords of the DataDrivenExcel class looks like below which is also self explanatory.
//Usage in the TestNG test class DataDrivenTest.java
package example.aks.data.test;

import java.util.ArrayList;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import example.aks.data.util.DataDrivenExcel;

/**
 * This class explains the usage of data driven excel
 * 
 * @author A. K. Sahu
 * 
 */
public class DataDrivenTest {

 @DataProvider(name = "loginToAppWithAllRoles")
 public Object[][] getLoginDataForAllRoles() throws Exception {

  DataDrivenExcel userData = new DataDrivenExcel(
    "D:/workspace/DataDriven/data/SampleExcel.xlsx", "Sheet1");

  ArrayList<Object> dataList = new ArrayList<Object>();

  int i = 1;// excluding header row
  int totalRows = 6;
  while (i < totalRows) {
   System.out.println("loginToAppWithAllRoles : line : " + i);

   Object[] dataLine = new Object[4];
   dataLine[0] = userData.getCell(i, 0);
   dataLine[1] = userData.getCell(i, 1);
   dataLine[2] = userData.getCell(i, 2);
   dataLine[3] = userData.getCell(i, 3);

   dataList.add(dataLine);

   i++;
  }

  Object[][] data = new Object[dataList.size()][];
  for (i = 0; i < dataList.size(); i++)
   data[i] = dataList.get(i);

  return data;
 }

 @Test(dataProvider = "loginToAppWithAllRoles", 
       description = "Login with different roles")
 public void testLogin(String userID, String username, String password,
   String role) {

  WebDriver driver = new FirefoxDriver();

  driver.get("http://yoursiteurl.com");

  // Do required actions using the input data, i am just printing here
  System.out.println("userID:" + userID);
  System.out.println("username:" + username);
  System.out.println("password:" + password);
  System.out.println("role:" + role);

  driver.quit();
 }
}
Similarly, you can use an excel file with .xls format.
Important Note: 
In the above test class we used
Object[] dataLine = new Object[4];
Number here should match with the number of parameters for the test case that using this dataprovider.

The  output after executing the tests looks like below:
TestNG Console

Console output

Note: While you are running the tests if you encounter any problem recheck about the below:
  1. Make sure all the above mentioned jars are added to your build path.
  2. The object size defined in the data provider is equal to the number of parameters defined in the test method.
  3. You are reading an existing cell value with a valid row and column index.

Tuesday, November 26, 2013

Get name of test method in teardown

Sometimes we need name of the test method that has just executed in the tear down method for various purposes such as:
  • If you take screenshot in tear down and want to give last executed method name as a part of screenshot name.
  • May be someone want to track something in the log with the test method information.
  • If you have different classes containing test methods and tear down method, and you want to use test method information in tear down method.
@AfterMethod
public void yourTearDownMethod(ITestResult result) {
  System.out.println("method name:" + result.getMethod().getMethodName();
}
Similar way, you can get other information about the test method by result.getMethod().getXXX()

Thursday, June 20, 2013

Ant task to run all tests by the specified group name

Following ant task shows us how to run all testng tests those are specified with the group "alltests" in the test classes. We can actually do this by two ways. 

Type-I(from testng suite) 
The following target runs all the tests with group "alltests". In this case it will search for all the tests that are specified with group "alltests" and only for the tests/classes/packages specified in the testng.xml(test suite) only. After executing the tests it creates the testng report in the "reprots.testng" directory specified in ant property.
 

 
 
  
   
  
 
Type-II(directly from the classes) 
The following target runs all the tests with group "alltests". In this case it will search for all the tests that compiled and there in the "classes" directory specified in the ant property. After executing the tests it creates the testng report in the "reprots.testng" directory specified in ant property.
 

 
 
  
   
   
   
  
 
The report generated by testng looks like the below snapshot:


Sunday, March 25, 2012

Ant task/script for generating TestNg report

Here is an example explaining an ant task for generating TestNG report after execution of classes defined in TestNG xml file.
  1. <property name="src.dir" value="src" />
  2. <property name="lib.dir" value="lib" />
  3. <property name="log.dir" value="logs" />
  4. <property name="build.loc" value="build" />
  5. <property name="classes.dir" value="${build.loc}/classes" />
  6. <property name="reports.dir" value="${build.loc}/reports" />
  7. <property name="testNG.report" value="${reports.dir}/TestNG" />
  8. <property name="suite.dir" value="suite" />
  9. <!-- Class-Path -->
  10. <path id="classpath">
  11.     <pathelement location="${classes.dir}"/>
  12.     <fileset dir="${lib.dir}" includes="*.jar"/>
  13. </path>
  14. <!-- Delete directories that are not needed -->
  15. <target name="delete-dir" >
  16.         <delete dir="${build.loc}"/>
  17.         <echo> /* Deleted existing Compiled Directory Classes */ </echo>
  18. </target>
  19. <!-- Create Directories -->
  20. <target name="create-source-dir" depends="delete-dir">
  21.     <mkdir dir="${classes.dir}"/>
  22.     <mkdir dir="${testNG.report}"/>
  23.     <echo> /* Created Directories */ </echo>
  24. </target>
  25. <!-- Compiling Tests -->
  26. <target name="compile-classes" depends="create-source-dir">
  27.     <javac destdir="${classes.dir}" includeantruntime="false" debug="true" srcdir="${src.dir}">
  28.         <classpath refid="classpath"/>
  29.     </javac>
  30.     <echo> /* Compiled Directory Classes */ </echo>
  31. </target>
  32. <!-- Running Tests and TestNG report generation -->
  33. <target name="testNGreport" depends="compile-classes">
  34.     <taskdef resource="testngtasks" classpathref="classpath"/>
  35.     <testng classpathref="classpath" outputDir="${testNG.report}" haltOnfailure="true">
  36.           <xmlfileset dir="." includes="${suite.dir}/testng.xml" />
  37.     </testng>
  38.     <echo> /* Run Directory Classes */ </echo>
  39. </target>
By the above target 'testNGreport' you can load TestNG task in ant and execute you selenium tests. It is just that ant would access your testng.xml file to execute tests. This is same as how you be executing tests from with eclipse using TestNG - Eclipse plugin. 
Below is the testNG file that is used in the above build file.
//TestNG.xml
  1. <suite name="Suite1" verbose="1" >
  2.   <test name="Regression1">
  3.     <classes>
  4.       <class name="test.sample.ExampleTest1"/>
  5.       <class name="test.sample.ExampleTest2"/>
  6.     </classes>
  7.   </test>
  8. </suite>

Thursday, March 15, 2012

Selenium RC with TestNG

Here is an example explaining how to use TestNG with Selenium RC i.e using TestNG  to run selenium rc tests.

//GoogleTestTestNG.java
  1. package test.example;
  2. import org.testng.annotations.AfterClass;
  3. import org.testng.annotations.BeforeClass;
  4. import org.testng.annotations.Test;
  5. import com.thoughtworks.selenium.DefaultSelenium;
  6. import com.thoughtworks.selenium.Selenium;
  7. /**
  8.  * Search Google example.
  9.  *
  10.  * @author aksahu
  11.  */
  12. public class GoogleTestTestNg {
  13.    
  14.     Selenium selenium;
  15.    
  16.     @BeforeClass
  17.     public void startSelenium(){
  18.         selenium = new DefaultSelenium("localhost"4444"*firefox""http://www.google.com");
  19.         selenium.start();
  20.         selenium.windowMaximize();
  21.     }
  22.    
  23.     @Test
  24.     public void testGoogleSearch(){    
  25.         selenium.open("/");
  26.         selenium.type("id=lst-ib""selenium");
  27.         selenium.click("name=btnK");
  28.         selenium.click("link=Selenium - Web Browser Automation");
  29.         selenium.waitForPageToLoad("30000");
  30.     }
  31.    
  32.     @AfterClass
  33.     public void stopSelenium(){    
  34.         selenium.stop();
  35.     }
  36. }

          This test launches firefox browser and executes the google search test.The selenium session is started in startSelenium() method which is called before any test run in the test class and ends with stopSelenium() method which 'll call after the tests run.

Tuesday, January 03, 2012

Running Selenium tests in parallel

This post explains how to set up a concurrent execution environment and considerably reduce your testing times.
We can run multiple testcases across different browsers at a time using TestNG's configuration file.

          Below is the class that defines four methods, 'startSeleniumServer()' method is for start the server (if not started in the current port) before suite i.e before test classes in suite started runnig and the method 'stopSeleniumServer()' is for stop the server after the suite i.e after runnig  the test classes in suite (you can make these to execute class level as well, if necessary).The method 'startSelenium()' accepts two parameters i.e 'port' and 'browser' from the TestNG's configuration file.This method initiates the selenium, starting the browser before each test run and the method 'stopSelenium()' ends the test session, killing the browser.
//MasterTest.java
  1. package master;
  2. import org.openqa.selenium.server.RemoteControlConfiguration;
  3. import org.openqa.selenium.server.SeleniumServer;
  4. import org.testng.annotations.AfterClass;
  5. import org.testng.annotations.AfterSuite;
  6. import org.testng.annotations.BeforeClass;
  7. import org.testng.annotations.BeforeSuite;
  8. import org.testng.annotations.Parameters;
  9. import com.thoughtworks.selenium.DefaultSelenium;
  10. import com.thoughtworks.selenium.Selenium;
  11. public class MasterTest {
  12.    
  13.     protected RemoteControlConfiguration rc ;
  14.     protected SeleniumServer seleniumServer ;
  15.     public Selenium selenium;
  16.    
  17.     @BeforeSuite
  18.     public void startSeleniumServer()throws Exception{
  19.         rc = new RemoteControlConfiguration();  
  20.         seleniumServer = new SeleniumServer(rc);
  21.         if(!seleniumServer.getServer().isStarted()){  
  22.             seleniumServer.start();        
  23.         }
  24.     }
  25.    
  26.     @Parameters({"port","browser"})
  27.     @BeforeClass
  28.     public void startSelenium(int port,String browser) {
  29.         System.err.println("INFO: The test '"+this.getClass().getName()+"' is running on browser '"+browser+"'");
  30.         selenium = new DefaultSelenium("localhost", port, browser, "http://www.google.co.in");
  31.         selenium.start();
  32.         selenium.windowMaximize();
  33.         selenium.windowFocus();
  34.     }
  35.    
  36.     @AfterClass
  37.     public void stopSelenium() throws Exception {
  38.         selenium.stop();
  39.      }
  40.    
  41.     @AfterSuite
  42.     public void stopSeleniumServer()throws Exception {
  43.         seleniumServer.stop();
  44.     }      
  45. }
              Below is the class that runs in firefox browser.This class extends from 'MasterTest' so that before 'FirefoxTest' the selenium server will start, if not started and after this test run the selenium server will stop.
    //FirefoxTest.java
    1. package master;
    2. import org.testng.annotations.Test;
    3. public class FirefoxTest extends MasterTest {      
    4.    
    5.     @Test
    6.     public void firefoxTest() throws Exception {
    7.         selenium.setSpeed("1000");
    8.         selenium.open("/");
    9.         selenium.type("id=lst-ib""selenium");
    10.         selenium.click("name=btnG");
    11.         selenium.click("link=Selenium - Web Browser Automation");
    12.         selenium.waitForPageToLoad("30000");
    13.     }
    14. }
              Below is the class that runs in google chrome browser.This class also extends from 'MasterTest' so that before 'ChromeTest' the selenium server will start, if not started and after this test run the selenium server will stop.
    // ChromeTest .java
    1. package master;
    2. import org.testng.annotations.Test;
    3. public class ChromeTest extends MasterTest {       
    4.    
    5.     @Test
    6.     public void chromeTest() throws Exception {
    7.         selenium.setSpeed("1000");
    8.         selenium.open("/");
    9.         selenium.waitForPageToLoad("30000");
    10.         selenium.type("id=lst-ib""selenium rc");
    11.         selenium.click("name=btnG");
    12.         selenium.click("css=em");
    13.         selenium.waitForPageToLoad("30000");
    14.     }
    15. }
              Below is the class that runs in Internet Explorer browser.This class also extends from 'MasterTest' so that before 'IETest' the selenium server will start, if not started and after this test run the selenium server will stop.
    // IETest .java
    1. package master;
    2. import org.testng.annotations.Test;
    3. public class IETest extends MasterTest {
    4.    
    5.     @Test
    6.     public void ieTest() throws Exception {
    7.         selenium.setSpeed("1000");
    8.         selenium.open("/");
    9.         selenium.type("id=lst-ib""selenium");
    10.         selenium.click("name=btnG");
    11.         selenium.click("link=Selenium - Web Browser Automation");
    12.         selenium.waitForPageToLoad("30000");
    13.     }  
    14. }
              Finally, here is the TestNG's configuration file that runs all the tests giving 'port' and 'browser' as input parameters to the 'MasterTest' in each and every test run.
              The attribute 'thread-count' allows to specify how many threads should be allocated for the execution. Here i have used thread-count="3" i.e  3 threads are allocated for the tests execution.Another attribute here i have used  is 'parallel'.It takes 3 values i.e 
    parallel="methods":
        TestNG will run all the test methods in separate threads.
    parallel="tests": 
        TestNG will run all the methods in the same <test> tag in the same thread, but each <test> tag will be in a separate thread.
    parallel="classes": 
        TestNG will run all the methods in the same class in the same thread, but each class will be run in a separate thread.
    //testng.xml
    1. <suite name="Parallel Run Suite" parallel="classes"  thread-count="3">
    2.     <test name="Test-1">
    3.         <parameter name="port" value="4444" />
    4.         <parameter name="browser" value="*firefox" />
    5.         <classes>
    6.             <class name="master.FirefoxTest" />
    7.         </classes>
    8.     </test>
    9.    
    10.     <test name="Test-2">
    11.         <parameter name="port" value="4444" />
    12.         <parameter name="browser" value="*googlechrome" />
    13.         <classes>
    14.             <class name="master.ChromeTest" />
    15.         </classes>
    16.     </test>
    17.    
    18.     <test name="Test-3">
    19.         <parameter name="port" value="4444" />
    20.         <parameter name="browser" value="*iexplore" />
    21.         <classes>
    22.             <class name="master.IETest" />
    23.         </classes>
    24.     </test>
    25.    
    26. </suite>
              So, when you will run the above TestNG's configuration file, firstly, it will run 'FirefoxTest' in firefox browser,secondly, it will run 'ChromeTest' in chrome browser and thirdly, it will run 'IETest' in internet explorer browser in the order, one after one.If you want to run all these 3 tests concurrently in 3 browsers respectively, make parallel="tests" in the TestNG's configuration file.