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.

Thursday, June 26, 2014

Page Refresh in Selenium WebDriver

There are many ways that we can refresh a web page in Selenium Webdriver tests. Here are listed some of them: 
1) Using refresh() method of WebDriver
driver.navigate().refresh();
This is most commonly used method. 
2) Using F5 key
driver.findElement(By.name("q")).sendKeys(Keys.F5);
This is also commonly used method. We must use it in any text field of the web page as it uses Send keys method. 
3) Using Actions class of WebDriver
Actions actions = new Actions(driver);
actions.keyDown(Keys.CONTROL).sendKeys(Keys.F5).perform();
4) Using jQuery
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("history.go(0)");
5) Using navigate( ).to( ) method of WebDriver
driver.navigate().to(driver.getCurrentUrl());
6) Using ASCII code
driver.findElement(By.name("q")).sendKeys("\uE035");

Navigate Back, Forward and to an Url in Selenium Webdriver

Below scenarios explains how we can navigate across the browser for various web pages.
WebDriver driver = new FirefoxDriver();
driver.get("http://aksahu.blogspot.in/");

Navigate to an Url:
driver.navigate().to("http://knowledgebase-wiki.appspot.com/");
This navigates the page to "http://knowledgebase-wiki.appspot.com/"

Navigate Back:
driver.navigate().back();
This navigates back to the previous page "http://aksahu.blogspot.in/"

Navigate Forward:
driver.navigate().forward();
This navigates the page forward to "http://knowledgebase-wiki.appspot.com/"

Friday, May 16, 2014

Array to List and List to Array in Java

While testing web applications we came across many list of elements or an element with list of data. In such cases we may need the following conversation instead of iterating over an array or a list.
 
Please refer the below simple example to convert a string array to a list and vice versa. But be careful about the order of elements, If required you may use collection methods to do so.

Lets take an arry of strings as below
String[] elementsAsArray = new String[]{"ele1","ele2","ele3"};

Array to List:
List arrayAsList = Arrays.asList(elementsAsArray);

List to Array:
String[] listAsArray = arrayAsList.toArray(new String[arrayAsList.size()]);

Sunday, March 16, 2014

Switch between windows or tabs in Selenium Webdriver

Please refer the below set of code to understand how can we switch between different windows in Selenium. Open a web page:
WebDriver driver = new FirefoxDriver();
driver.get("http://aksahu.blogspot.in/");
Open a new window:
WebElement elemLink = driver.findElement(By.linkText("Web Driver"));
Actions actions = new Actions(driver);
actions.moveToElement(elemLink);
actions.contextClick(elemLink).sendKeys(Keys.ARROW_DOWN)
  .sendKeys(Keys.ARROW_DOWN).sendKeys(Keys.ENTER).build()
  .perform();
For opening in a new tab/window see the post Open in new Tab or new Window in Selenium Webdriver

Switch between two tabs or windows:

(1) 
If you want to switch to a specific window, see below:
String windowHandle = driver.getWindowHandle();

Now if you want to switch to second windows use the below code:
for(String winHandle : driver.getWindowHandles()){
    driver.switchTo().window(winHandle);
}
Switch to the parent window:
driver.switchTo().window(windowHandle);

(2)
Or, simply you can do as below to switch between two tabs or windows:
ArrayList tabs = new ArrayList (driver.getWindowHandles());

//Switch to new window
driver.switchTo().window(tabs.get(1));
driver.close();//do some action in new window(2nd tab)

//Switch to main/parent window
driver.switchTo().window(tabs.get(0));
driver.getTitle();//do some action in main window(1st tab)

Saturday, March 15, 2014

Open in new Tab or new Window in Selenium Webdriver

New Tab:
Use the below code to complete the action in a new tab.
WebDriver driver = new FirefoxDriver();
driver.get("http://aksahu.blogspot.in/");
You can  do by either of the below ways
driver.findElement(By.linkText("Tips & Tricks")).sendKeys(Keys.CONTROL + "t");
Or
WebElement aLink = driver.findElement(By.linkText("Tips & Tricks"));
Actions actions = new Actions(driver);
actions.moveToElement(aLink);
actions.contextClick(aLink)
       .sendKeys(Keys.ARROW_DOWN)
       .sendKeys(Keys.ENTER).build().perform();

New Window:
Use the below code to complete the action in a new window.
WebDriver driver = new FirefoxDriver();
driver.get("http://aksahu.blogspot.in/");
Open a web page in a new window:
String script = "var d=document,a=d.createElement('a');a.target='_blank';a.href='%s';a.innerHTML='.';d.body.appendChild(a);return a";
Object element = ((JavascriptExecutor) driver).executeScript(String.format(script, "http://aksahu.blogspot.in/"));
if (element instanceof WebElement) {
    WebElement anchor = (WebElement) element;
    anchor.click();
    ((JavascriptExecutor) driver).executeScript("var a=arguments[0];a.parentNode.removeChild(a);", anchor);
} else {
     throw new JavaScriptException(element, "Unable to open Window", 1);
}
Open a link in a new window:
WebElement elemLink = driver.findElement(By.linkText("Web Driver"));
Actions actions = new Actions(driver);
actions.moveToElement(elemLink);
actions.contextClick(elemLink)
       .sendKeys(Keys.ARROW_DOWN)
       .sendKeys(Keys.ARROW_DOWN)
       .sendKeys(Keys.ENTER).build().perform();

Wednesday, February 19, 2014

Maximize and Resize browser window in Selenium Webdriver

Maximize browser window:
You can maximize your current browser window by simply calling the maximize() method of WebDriver as below:
WebDriver driver = new FirefoxDriver();
driver.manage().window().maximize();
Sometimes the above doesn't work in some versions of browsers like chrome. So you can use below code alternatively:
Point targetPosition = new Point(0, 0);
driver.manage().window().setPosition(targetPosition);

String w = "return screen.availWidth";
String h = "return screen.availHeight";
JavascriptExecutor javascriptExecutor = (JavascriptExecutor) driver;
int width = ((Long) javascriptExecutor.executeScript(w)).intValue();
int height = ((Long) javascriptExecutor.executeScript(h))
  .intValue();
Dimension targetSize = new Dimension(width, height);

driver.manage().window().setSize(targetSize);

Resize browser window:
Sometimes in the test we need to resize the browser window to a certain window size. In such cases we can use the below to do:
driver.manage().window().setSize(new Dimension(320, 480));

Friday, January 03, 2014

Selenium tricks for CSS and Xpath locators

In this post you will learn some CSS rules and how to use CSS selectors and Xpath locators in Selenium.

(1) Id:
An element's id is defined as "[@id='idName']" in Xpath but "#idName" in CSS.
For example, a 'div' element with id 'panel' will be represented as below:
In Xpath locator
//div[@id='panel']
In CSS selector
css=div#panel

(2) Class:
An element's class is defined as "[@class='className']" in Xpath but ".className" in CSS.  
For example, a 'div' element with class 'panelClass' will be represented as below:
In Xpath locator
//div[@class='panelClass']
In CSS selector
css=div.panelClass
For element with multiple class we need to separate with space(" ") in Xpath and dot(".") in case of CSS. See below example,
In Xpath locator
//div[@class='panelClass1 panelClass2']
In CSS selector
css=div.panelClass1.panelClass2

(3) Any Attributes:
For selecting an element by its any of the attribute(say "name" is an attribute of a 'div' element and "type" in an "input" element) is given below:
In Xpath locator
//div[@name='continue']
//input[@type='button'] 
In CSS selector
css=div[name='continue']
css=input[type='button'] 

(4) Direct Child:
A direct child of an element is denoted as "/" in Xpath and ">" in CSS selector. See the example below for a direct child "li" for a "ul" element:
In Xpath locator
//ul/li
In CSS selector
css=ul > li

(5) Child or Subchild:
A direct child of an element is denoted as "//" in Xpath and a wehite-space(" ") in CSS selector. See the example below for a child/subchild "li" for a "ul" element:
In Xpath locator
//ul//li
In CSS selector
css=ul li
Note that "ul li" and "ul > li" are different. If you are confusing please go through this article.

(6) nth Child:
For finding 'nth' child, in Xpath we denote as "[n]" and in CSS we denote as ":nth-of-type(n)". See the below example,
  1. Coffee
  2. Tea
  3. Milk
  4. Soup
  5. Soft Drinks
In Xpath locator
//ul[@id='drinks']/li[5]
In CSS selector
css=ul#drinks li:nth-of-type(5)
Also you can use ":nth-child" but the difference between ":nth-child" and ":nth-of-type(n)" is:
li:nth-child(2)
This means, select an element if It is a paragraph element and the second child of a parent.

li:nth-of-type(2)
This means, select the second paragraph child of a parent. This is less conditional.

See here for more details on difference between the above two.

If we want to select the "fifth li element" (Soft Drinks) in this list, we can use the nth-of-type, which will find the fifth li in the list.
css=ul#drinks li:nth-of-type(5)
On the other hand, if we want to get the "fifth element" only if it is a li element, we can use a filtered nth-child which will select again (Soft Drinks) here.
css=ul#drinks li:nth-child(5)
(7) Parent of an element:
Parent of an element can be represented as "/.." in Xpath and ":parent" in CSS selectors. For example, if you want to indicate parent of the list item of class 'blue'
  • first
  • second
  • third
  • fourth
  • fifth
In Xpath locator
//li[@class='blue']/..
In CSS selector
css=li.blue:parent

(8) Next Sibling:
Next sibling is nothing but next adjacent element which is inside the same parent on the page. An adjacent sibling combinator selector allows you to select an element that is directly after another specific element. For example, If you want to select the sibling of "li" element with class "blue" which is 'second' list item,
In Xpath locator
//li[@class='blue']/../li[2]
In CSS selector
css=li.blue + li
Similarly, if you want to indicate 'third' list item, see the below
In Xpath locator
//li[@class='blue']/../li[3]
In CSS selector
css=li.blue + li + li

(9) Match by Innertext:
There is a javascript methodcontains() which can be used to check the inner text of a web element. For example a link with text "Sign in"
In Xpath locator
//a[contains(text(),'Sign in')]
or
//a[contains(string(),'Sign in')] 
In CSS selector
css=a:contains('Sign in')

(10) Match by Sub-string:
This is interesting and is described below. With this we can match strings with its partial text. E.g. prefix, suffix or any pattern(sub-string)
(i) Match a Sub-string(pattern):
Taking an example of a 'div' with an 'id' that contains the text "pattern"
...
In Xpath locator, we need to use "contains()" to match a sub-string
//div[contains(@id,'pattern')]
In CSS selector, we need to use "*=" for matching a sub-string
css=div[id*='pattern']

(ii) Match a prefix:
Taking an example of a 'div' with an 'id' that starts with the text "prefixString"
...
In Xpath locator, we need to use "starts-with" to match a prefix
//div[starts-with(@id,"prefixString")]
In CSS selector, we need to use "^=" for matching a prefix
css=div[id^='prefixString']

(iii) Match a suffix:
Taking an example of a 'div' with an 'id' that starts with the text "suffixString"
...
In Xpath locator, we need to use "ends-with" to match a suffix Note that "ends-with()" is a standard XPath 2.0 function only, it won't work if you are using Xpath 1.0 engine
//div[ends-with(@id,"suffixString")]
In CSS selector, we need to use "$=" for matching a suffix
css=div[id$='suffixString']
The summary of sub-string match is listed out in the following table:
Match a Sub-string Match a Prefix Match a Suffix
Xpath contains() starts-with() ends-with()
CSS *= ^= $=