Tuesday 21 May 2013

Construction of Xpath and Css selectors


Construction of Xpath and CSS selectors


As we know that webdriver supports for different types of locators to identify the web elements(objects i.e username, password etc). 

The different kinds of locators are ,
  • id
  • name
  • xpath
  • css selector
  • class name
  • tag name etc.


The priority of choosing the locator type is id/name, CSS selector and xpath.

Let see how to construct the xpath/css selector for web elements.

Xpath construction:


Let we consider the below login form. In this we will construct the xpath for user name, password text boxes, submit and reset buttons.



The HTML source code for this login page is as follows,


<html>
<title>Welcome to the application!!</title>
<body>
<form name="loginForm">
<table border="1">
<tr>
<td>User Name: </td>
<td>
<input name="username_name" id="username_id" type="text"
class="article-head"/>
</td>
</tr>
<tr>
<td>Password: </td>
<td>
<input name="password_name" id="password_id" type="password"
class="article-head"/>
</td>
</tr>
<tr>
<td>
<input name="login_name" id="login_id" label="Submit" type="button" class="article-head" onClick="submitAction()"/>
</td>
<td>
<input name="reset_name" id="reset_id" label="Reset" type="button" class="article-head" onClick="cancelAction()"/>
</td>
</tr>
</table>
</form>
</body>
</html>

Xpath for user name text field:

Absolute path: html/body/form/table/tr[1]/td[2]/input
Relative path: //input[@id='username_id']
                         //input[@name='username_name']
                         //input[1]

   Also we can use AND OR operators here, as below

                         //input[@id='username_id' and @name='username_name']

Xpath for Submit button:

Absolute path: html/body/form/table/tr[3]/td[1]/input
Relative path: //input[@id='login_id']
                         //input[@name='login_name']
                         //input[3]

   Also we can use AND OR operators here, as below

                         //input[@id='login_id' and @name='login_name']

As same as we can construct the xpath for password text field and reset button.

Xpath for dynamically changing objects:

Let we consider a situation. We want to construct the xpath for the user name text field, which has only two attributs id and type. Also the id is not a constant one, which is dynamic as below,

<input id="username_45833" type="text">

The number in the id name is changing dynamically for every build. In this case using  //input[@id='username_45833'] is not the correct idea.

To accomplish this we have to use the starts-with() function available in the xpath as below

//input[starts-with(@id, 'username_')].

Also we can use ends-with() and contains() method above. For more information about understanding the xpath read here 

Monday 20 May 2013

How to setup Selenium grid

Selenium Grid:


Selenium grid concept is used to distribute test cases and run multiple test cases at the same time in
  • The same machine - same browsers/ different browsers
  • Different machines - same browsers/ different browsers
  • Different OS etc.
While reading about selenium grid you could have seen two technical terms names hub and node mainly.

Hub is a central point, which allocates the available browsers to the nodes
Node is nothing but, it is an instance which  needs to be registered in the hub.

Grid Set up:

  1. Run tests cases in the same machine
  2. Run test cases in different machines

Run tests cases in the same machine:

I have two tests in the xml suite file. I want to run these two tests parallel in the same machine.

Step 1: Start the hub


Open the command prompt and go to the directory where the selenium-server.jar is available. Then type the following command and hit the enter.

                  java -jar selenium-server.jar -role hub

Here we are starting the selenium server with the hub role. It starts at the port 4444 as default. If you want to start the hub in different port you can use the parameter -port ( java -jar selenium-server.jar -role hub -port 6666)

Now hub is started and if you go to this link http://localhost:4444 you will see the grid details

Step 2: Create/Register node in hub


Open the command prompt and go to the directory where the selenium-server.jar is available. Then type the following command and hit the enter.

                  java -jar selenium-server.jar -role node -hub http://localhost:4444/grid/register

This will register the node with the hub. Now if you look http://localhost:4444/grid/console you will the available browsers for our test.

Also you can particularly specify the browser name, maximum instances, port and rc/webdriver etc as below,

java -jar selenium-server-.jar -role webdriver -hub http://localhost:4444/grid/register -port 5556 -browser browserName=firefox,maxInstances=10














Sample script using Appium for native iOS application

iOS automation using Appium:


Appium is an open source automation tool for native and hybrid apps. It supports for both Android and iOS platforms. Appium drives the device/emulator/simulator using the Apple's UIAutomation library or Android's UiAutomator framework using Selenium's Webdriver JSON wire protocol. So we can use the languages for scripting, which all supported by Selenium.

Requirements:

  • MAC OS X 10.7 or higher
  • Xcode and command line tools(xcode version 4.6.2 would be fine)
  • Node.js
  • Appium.app
  • Eclipse
  • TestNG

1. Prepare the application to be automated:


We need the .app file for appium automation. So download any iOS application and build the .app file.

I downloaded the iOS app named iPhoneCoreDataRecipes from the apple website. The app looks like as below,

                                                            Sample Recipe iOS application

Steps:


  • Download the application from  iPhoneCoreDataRecipes
  • Extract it and import it into the xcode.
  • Run the project, Ensure that the simulator is opened up with the application.
  • Open the terminal and go to the project folder
  • Run the following command to build the .app file

                     xcodebuild -sdk iphonesimulator6.1

It will build the app and generate the Recipe.app file in yourProjectfolder/Build/Release-iphonesimulator, which is the only one we need to give in our automation script.

Now the application is ready to be automated :)

2. Prepare the machine for iOS automation:


We need node.js to work with appium if we didn't use appium.app. Just follow the below steps,

  • Install node.js from the site http://nodejs.org/
  • Install webdriver API to the node with the below command,

                       sudo npm install wd
           here npm represents that Node.js Package Manager

  • Install Appium to the machine with the below command

                      sudo npm install appium -g

  • Now start the appium server with the below command,

                      appium &

Now appium server is started in the default port 4723 and the IP Address 0.0.0.0 (http://0.0.0.0:4723) as below,

                                                              Appium server is started


3. Prepare the automation script:


Actually I do all the scripts using java language. So I use Eclipse IDE and TestNG for scripting.

The goal of the following script is add the recipe named 'Pizza' in the recipe list and verify its presence.

package com.qa.test;

import java.io.File;
import java.net.URL;
import java.util.List;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

public class TestRecipe {

public WebDriver driver = null;

@BeforeMethod
public void setUp() throws Exception {
// set up appium
File appDir = new File("/Users/Elang/Documents/iPhoneApps/iPhoneCoreDataRecipes/Build/Release-iphonesimulator");
File app = new File(appDir, "Recipes.app");
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(CapabilityType.BROWSER_NAME, "iOS");
capabilities.setCapability(CapabilityType.VERSION, "6.1");
capabilities.setCapability(CapabilityType.PLATFORM, "Mac");
capabilities.setCapability("app", app.getAbsolutePath());
driver = new RemoteWebDriver(new URL("http://0.0.0.0:4723/wd/hub"), capabilities);
}

@AfterMethod
public void tearDown() throws Exception {
driver.quit();
}


@Test
public void testAddRecipes() throws InterruptedException {

String recipeName = "Pizza";
String recipeDescription = "My lovable dish";
String preparationTime = "1 hour";

driver.findElement(By.name("Add")).click();
driver.findElement(By.xpath("//textfield[1]")).sendKeys(recipeName);
driver.findElement(By.name("Save")).click();

driver.findElement(By.name("Edit")).click();

driver.findElement(By.xpath("//tableview[1]/textfield[2]")).sendKeys(recipeDescription);
driver.findElement(By.xpath("//tableview[1]/textfield[3]")).sendKeys(preparationTime);

driver.findElement(By.name("choosePhoto")).click();
driver.findElement(By.xpath("//tableview[1]/cell[1]/text[1]")).click();
driver.findElement(By.xpath("//tableview[1]/cell[1]/image[1]")).click();
driver.findElement(By.name("Done")).click();

driver.findElement(By.xpath("//navigationBar[1]/button[1]")).click();

                // Verify the presence of added recipe.
List<WebElement> recipesDetails = driver.findElements(By.xpath("//tableview[1]/cell"));
//System.out.println("No. of Recipes: "+recipesDetails.size());
boolean result = false;
for(WebElement recipeDetails : recipesDetails) {
//System.out.println("details: "+recipeDetails.getAttribute("name"));
if(recipeDetails.getAttribute("name").equals(recipeDescription+", "+preparationTime+", "+recipeName)) {
result = true;
}
}
Assert.assertTrue(result, "Recipe is not present");
}

}

I used Appium inspector to identify the element locators. See here about how to use the appium inspector.

For the example of Android native app automation in WINDOWS platform, please look at here.


References: