Wednesday, August 15, 2012

CSS Locator / CSS Selector Tutorial

CSS locating strategy is the fastest way to identify an element compared to any other locating strategy currently available. Many of the automation frameworks now uses CSS as a locating strategy for locating elements. In this blog I will explain about how to identify an element using CSS locators.

1. Locate an element using id.
<input id="textid" value="textid" type="text"/>    
<button id="buttonid">Button wiht id</button>

Consider the above html code of a text box and a button, you can locate the above elements in html using there "id" attribute value.
In CSS  an element with id is identified by appending "#" to the start of its id attribute value. For ex the above text element can be located as "#textid". Similarly the button element can be identified as "#buttonid"


2. Locate an element using class attribute.
<input class="textusingcls" value="Text with single class" type="text"/>    
<button class="btnusingcls">Button with single Class</button>

Consider the above html code of a text box and a button, you can locate the above elements in html using there "class" attribute value.
In CSS  an element with class is identified by appending "." to the start of its class attribute value. For ex the above text element can be located as ".textusingcls". Similarly the button element can be identified as ".btnusingcls"

Locating an element having more than one class, for ex. consider the following html code.
<input class="textcls1 textcls2" value="Text with multiple class" type="text"/>    
<button class="buttoncls1 buttoncls2">Button with multiple Class</button>
The above element can be identified by replacing the spaces between the class values with "." . The above elements can be located as ".textcls1.textcls2" and ".buttoncls1.buttoncls2" respectively.

3. Locate an element using html tag.
<input id="textid" value="textid" type="text"/>    
<button id="buttonid">Button wiht id</button>

Consider the above html code of a text box and a button. To locate the above elements using there html tags in css, you just have to use the tag name. For ex. The above two elements can be located as "input" and "button" respectively.

4. Locate an element using html tag, class, id all together.
<input id="textidcls" class="textidcls" value="Text with id and class" type="text"/>    
<button id="buttonidcls" class="buttonidcls">Button with id and Class</button>

Consider the above html code of a text box and a button. You can locate the above element using a combination of html tag, id and class all together. To do that just append all the three independent locator together. For the above element the unique locators will be "input#textidcls.textidcls" and "button#buttonidcls.buttonidcls" respectively.

5. Locate element based on Parent element:
<input class="textcls" value="Text" type="text"/>  
<button class="buttoncls">Button</button>
<div id="parent">
    <div id="project-label">4. Locate Child element:</div>
    <input class="textcls" value="Text" type="text"/>    
    <button class="buttoncls">Button</button>
    <div>
        <input class="textcls" value="Text" type="text"/>    
        <button class="buttoncls">Button</button>
    </div>
</div>

Consider the above html code, if you try to find the text element using css locator ".textcls" you will get 3 elements in return. In case you need to find the text box under the div element with id "parent" you can locate it using the locator "#parent .textcls", but this also gives you 2 text box elements that are under the element with id "parent".
To find the direct child element of the "#parent" element you can use the ">" sign of css locator. So if you use the locator "#parent > .textcls" it will give you the direct child of "parent" element.
In css if you use space between the parent and child element, it will return all the child elements under the said parent irrespective of the hierarchy.

6. Identify an element using attribute value:
<input test="excttxt" value="Text for exact attr. value" type="text"/> </br>
<input test="strttxt1234" value="Text for starts with option" type="text"/> </br>
<input test="1234endtxt" value="Text for ends with option" type="text"/> </br>
<input test="12cntntxt34" value="Text for contains option" type="text"/> </br>

Consider the above html code, there are 4 text boxes each having a different value for attribute "test".Each element can be uniquely identified by using the following strategies:
  • By exact attribute value: 'input[test="excttxt"] '
  • By using starts with: 'input[test^="strttxt"]'
  • By using ends with: 'input[test$="endtxt"]'
  • By using contains: 'input[test*="cntntxt"]'

I had created a dummy html page which can be download from the following link: CSS-Locator-demo
To use the demo for identifying a locator:
1. Unzip the downloaded zip and open the page "css_locator.html" in chrome or firefox.
2. Now go to console in the browser. For Chrome: Right Click -> Inspect Element -> Console. For Firefox: Right Click ->Inspect with Firebug -> Console.
3. Use the jquery way of identifying element in the cosole. To do that type $('<Ur CSS locator>') under console and press enter.
Jquery will find the matching element for the said css locator and display it on the console as a link. If you hover on the said link it will highlight the said element.

More info on CSS selector at W3C link

Wednesday, July 18, 2012

Android automation tools/frameworks


As we all know the market of android based devices is increasing day by day. Due to this lot of companies are developing android based applications. These applications can be categorized as following:
  • Native apps - Apps that are developed using native android classes and runs on the device android OS.
  • Webapps - These apps are actually web-applications  that are customized to work with Android based mobile devices.
  • Hybrid apps - These apps are the mix of Native and Web based development. Such kinds of apps have some Native coding to interact with device hardware resources like camera,recorder, speaker etc. along with some web based components to directly serve the pages from a web-application itself.
With such a variety of apps in the market the QA will have a difficult task in hand, that is to automate such applications. There are a lot of tools and frameworks available in the market that can help you with automating the android apps. In this blog I will list a few of them and basic info about it. Following are some of the opensource apps available in the market:
  • Robotium - Android automation framework built over Android instrumentation testing provided by the Android itself. This is currently one of the major frameworks available that can be used a base for your android app automation. More info at: http://code.google.com/p/robotium/
  • NativeDriver - Extension of Selenium webdriver for Native android automation.This currently discontinued and no further support or development is being done on it. More info at: http://code.google.com/p/nativedriver/
  • Bot-bot - An Opensource android automation project built over Robotium and NativeDriver frameworks. Comes with recording features to record user actions and export them as test case. It currently supports recording user actions of native application elements and new work is going on to support recording on Web-based/Hybrid apps. More info at: http://imaginea.github.com/bot-bot/
  • MonkeyTalk -  Monkey talk is based on Android instrumentation testing provided by android. It have recorder which can be used as a eclipse plugin. The tool seems to be unstable and there is not much changes/ bug fixes that is seen.
  • Calabash - Calabash is another android/ios automation tool available in the market which uses cucumber as its base. More info is available at: https://github.com/calabash/calabash-android
Will keep on updating the list whenever I find something new.

Saturday, May 12, 2012

Generate TestNG-xslt report using Maven

Earlier I had covered in my blog on how to generate a TestNG-xslt report for your TestNG test-case execution using Ant. Following is the link to it:
http://blog.varunin.com/2010/05/generating-selenium-reports-using.html

As many of the recent projects are now using maven as their build tool ,test-cases are also required to integrate itself to the existing build. In this blog I will mention about how to generate a TestNG-xslt report for your TestNG test-case execution using Maven.
Following is the "pom.xml" file for executing TestNG test-cases and to generate a "TestNG-xslt" report for the same:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.testng.app</groupId>
  <artifactId>my-testng</artifactId>
  <packaging>jar</packaging>
  <name>my-testng</name>
  <version>1.0-SNAPSHOT</version>
  <url>http://maven.apache.org</url>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.5</version>
        <configuration>
          <suiteXmlFiles>
            <suiteXmlFile>testng.xml</suiteXmlFile>
          </suiteXmlFiles>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <encoding>iso-8859-1</encoding>
          <source>1.6</source>
          <target>1.6</target>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <reporting>
    <plugins>
    <!-- TestNG-xslt related configuration. -->
      <plugin>
        <groupId>org.testng.xslt</groupId>
        <artifactId>testng-xslt-plugin</artifactId>
        <version>1.1</version>
        <configuration>
          <!-- Output directory for the report -->
          <outputDir>${project.basedir}/target/testng-xslt-report</outputDir>
          <sortTestCaseLinks>true</sortTestCaseLinks>
          <testDetailsFilter>FAIL,SKIP,PASS,CONF,BY_CLASS</testDetailsFilter>
          <showRuntimeTotals>true</showRuntimeTotals>
        </configuration>
      </plugin>
    </plugins>
  </reporting>

  <dependencies>
    <dependency>
      <groupId>org.testng</groupId>
      <artifactId>testng</artifactId>
      <version>6.1.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <pluginRepositories>
    <pluginRepository>
      <id>testng-xslt-plugin</id>
      <url>http://www.cosminaru.ro/maven/</url>
    </pluginRepository>
  </pluginRepositories>

</project>
Run the following command to run your test cases and generate the TestNG-xslt report.

mvn clean test site

To know more about the TestNG-xslt configuration parameters please refer to my earlier blog post:
http://blog.varunin.com/2010/05/generating-selenium-reports-using.html

Wednesday, February 8, 2012

Native android application automation using bot-bot

Its been long time that I had written a blog here. I was busy with writing an android automation tool for native android application testing, named as "bot-bot". Please take a look at it and let us know your comments. This is work-in-progress and there are lot-of features that still have to implement.

Following are some of the links giving information on bot-bot:
Webpage:
http://imaginea.github.com/bot-bot/

Github page:
https://github.com/Imaginea/bot-bot

Most of the things are covered in the webpage or in Github.
In case of issues you can contact me or send a mail.

Tuesday, October 25, 2011

Selenium Grid with WebDriver

I had earlier covered in my blog on how to execute your RC cases in selenium grid. But with the commencement of Selenium-2/Webdriver, grid setup has been changed. In the following blog I will cover how to set-up your grid and the changes that will be required for easy execution of cases.


Following things are required:
1. Selenium 2.xx version server jar and Java library. The latest one can be downloaded from the link: Selenium-2
2. Java 1.6 and above
3. TestNg jar . You can download it from the link: TestNG
4. Eclipse with TestNG plugin installed(optional)
5. ChromeDriver. Can be downloaded from: ChromeDriver


The Test Code
Following is an example of test-class that have a test case to search google for "testing" and verifying after clicking it on a link.

import java.net.MalformedURLException;
import java.net.URL;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverBackedSelenium;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

import com.thoughtworks.selenium.Selenium;

import junit.framework.Assert;

public class Google {
 private Selenium selenium;
 @Parameters({"browser","port"})
 @BeforeClass
 public void beforeClass(String browser,String port){
  DesiredCapabilities capability= new DesiredCapabilities();
  capability.setBrowserName(browser);
  try {
   WebDriver driver= new RemoteWebDriver(new URL("http://localhost:".concat(port).concat("/wd/hub")), capability);
   selenium = new WebDriverBackedSelenium(driver, "http://www.google.com");
  } catch (MalformedURLException e) {
   
   e.printStackTrace();
  }
 }
 
 @Test
 public void search() {
  selenium.open("/");
  selenium.type("id=lst-ib", "testing");
  selenium.click("//input[@value='Google Search']");
  for (int second = 0;; second++) {
   if (second >= 60)
    Assert.fail("timeout");
   try {
    if (selenium
      .isElementPresent("link=Software testing - Wikipedia, the free encyclopedia"))
     break;
   } catch (Exception e) {
   }
   try {
    Thread.sleep(1000);
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
  selenium.click("link=Software testing - Wikipedia, the free encyclopedia");
  for (int second = 0;; second++) {
   if (second >= 60)
    Assert.fail("timeout");
   try {
    if (selenium.isTextPresent("Software testing"))
     break;
   } catch (Exception e) {
   }
   try {
    Thread.sleep(1000);
   } catch (InterruptedException e) {

    e.printStackTrace();
   }
  }
 }
 @AfterClass
 public void afterClass(){
  selenium.stop();
 }
 
}
In the above class I am using the TestNG "Parameter" property to provide different data set to the "BeforeClass" method "beforeClass". The beforeClass method accepts two properties "browser" and a "port".
These values are used for initialization of driver and in-turn for initialization of selenium object. In the above code I am using the "WebDriverBackedSelenium" class for creation of the selenium object, so that its easy for guys who had worked on Selenium-1 to understand the code. If you want the code to be purely WebDriver, you can directly use the "driver" object for defining your test-cases.
The main part in this test case is how the driver object is being created:
DesiredCapabilities capability= new DesiredCapabilities();
capability.setBrowserName(browser);
WebDriver driver= new RemoteWebDriver(new URL("http://localhost:".concat(port).concat("/wd/hub")), capability);
The above code creates an object of DesiredCapability and then set the browser value to it. Now using this "capability" object I am creating the webdriver object using the "RemoteWebDriver" class. This tells the selenium on which browser the test-case needs to run and where the server is located. In this example I am assuming the server to be running locally. In case it is on different system the "localhost" needs to be re-placed with the ip of the said system.

TestNG configuration
For parallel execution you need to use the TestNG configuration. Following is an "testng.xml" file for the above said test class. The said configuration executes the test-cases across different browser.


<suite name="Selenium TestNG Suite" parallel="tests"
    thread-count="5">

    <test name="Selenium TestNG - 1">
        <parameter name="browser" value="firefox" />
        <parameter name="port" value="4444" />
        <classes>
            <class name="com.test.testng.Google" />
        </classes>
    </test>
    <test name="Selenium TestNG - 2">
        <parameter name="browser" value="chrome" />
        <parameter name="port" value="4444" />
        <classes>
            <class name="com.test.testng.Google" />
        </classes>
    </test>

</suite>


In the above configuration, I am configuring TestNG to run "tests" in parallel. Also there are two different tests inside a suite. For each test a different "browser" parameter value has been configured.

Selenium-Grid server
Now start your grid using the following commands. Run each command in a seperate terminal or command prompt by going to the directory containing your selenium-server-standalone-2.x.x.jar. In the following example I am using the 2.7.0 version of selenium.

For Hub:

java -jar selenium-server-standalone-2.7.0.jar -role hub


For a firefox based node:

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


For google-chrome based node:

java -Dwebdriver.chrome.driver=/path/to/chromedriver -jar selenium-server-standalone-2.7.0.jar -role webdriver -hub http://localhost:4444/grid/register -port 5555 -browser browserName=chrome

Before running  the above command  you need to provide the chrome-driver path to the property "-Dwebdriver.chrome.driver".

Now run your testng.xml from eclipse by selecting it -> Right click -> Run as -> TestNG suite(this will work only if you have TestNG plugin installed in your eclipse.)
Or you can choose other ways to execute "testng.xml" like from command prompt, using ant or maven.
Once you run the above testng.xml. TestNG will execute the cases from the Google class on grid across different browsers firefox and google-chrome as configured.


You can do configurations for environment like OS (Linux,Windows), browser, browser-version and all and then you can run you cases on particular type of environment by configuring them accordingly. More details can be found at the following URL:
http://code.google.com/p/selenium/wiki/Grid2

Thursday, October 20, 2011

Data-Driven testing using Junit and TestNG


Most of the guys who are into automation may be knowing the term Data-Driven testing. But the word will still be new for some fresh faces in the field of automation. In this blog I will explain what is Data-Driven testing and will give an example of Data-driven testing using Junit and TestNG frameworks.

Data-Driven testing as the name suggests is a test driven by the Data. For ex. You have a user detail form where you need to enter details of multiple users and save them. Here if you have 5 different user data available and you have to write automation cases for these, you may end up writing 5 different automation test cases(one for each user data).
If you apply a Data-Driven approach you will end up with only one test-case, that is filling the form with user data and then submitting it. The test case will get executed based on the data provided to it. In this case it will be 5 and hence the test case will get executed 5 times with different data-set.

The advantage of using a Data-driven approach is that you reduce your effort in writing/maintaing test-cases for your different type of data. In case of additions or deletion of new/old entries , you just have to change the data and not your actual test-case.

Following I will mention a Data-Driven approach for searching on google with different data using Junit and TestNg frameworks:


Using Junit:
import static org.junit.Assert.fail;

import com.thoughtworks.selenium.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverBackedSelenium;
import org.openqa.selenium.firefox.FirefoxDriver;

import java.util.Arrays;
import java.util.List;

@RunWith(Parameterized.class)
public class JunitGoogleBase {
  public Selenium selenium;
  WebDriver driver;
  private String testData;
  
  public JunitGoogleBase(String testData){
   this.testData=testData;
  }
  
  @Parameters
   public static List< Object[]> data() {
    return Arrays.asList(new Object[][]{{"testing"},{"Software testing"}});
   }

  @Before
  public void setUp() throws Exception {
   driver= new FirefoxDriver();
   selenium = new WebDriverBackedSelenium(driver, "http://www.google.com"); 
   selenium.open("http://www.google.com");
  }

  @Test
  public void testSearch() throws Exception {
   selenium.open("/");
   selenium.type("id=lst-ib", testData);
   selenium.click("//input[@value='Google Search']");
   for (int second = 0;; second++) {
    if (second >= 60) fail("timeout");
    try { if (selenium.isElementPresent("link=Software testing - Wikipedia, the free encyclopedia")) break; } catch (Exception e) {}
    Thread.sleep(1000);
   }
   selenium.click("link=Software testing - Wikipedia, the free encyclopedia");
   for (int second = 0;; second++) {
    if (second >= 60) fail("timeout");
    try { if (selenium.isTextPresent("Software testing")) break; } catch (Exception e) {}
    Thread.sleep(1000);
   }
   
  }

  @After
  public void tearDown() throws Exception {
   selenium.stop();
   
  }
}

Using TestNg:

import com.thoughtworks.selenium.*;


import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverBackedSelenium;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;



public class TestNGGoogleBase {
  public Selenium selenium;
  WebDriver driver;
  
  @DataProvider(name="parameter")
   public static Object[][] data() {
    return new Object[][]{{"testing"},{"Software testing"}};
   }

  @BeforeMethod
  public void setUp() throws Exception {
   driver= new FirefoxDriver();
   selenium = new WebDriverBackedSelenium(driver, "http://www.google.com"); 
   selenium.open("http://www.google.com");
  }

  @Test(dataProvider="parameter")
  public void testSearch(String testData) throws Exception {
   selenium.open("/");
   selenium.type("id=lst-ib", testData);
   selenium.click("//input[@value='Google Search']");
   for (int second = 0;; second++) {
    if (second >= 60) Assert.fail("timeout");
    try { if (selenium.isElementPresent("link=Software testing - Wikipedia, the free encyclopedia")) break; } catch (Exception e) {}
    Thread.sleep(1000);
   }
   selenium.click("link=Software testing - Wikipedia, the free encyclopedia");
   for (int second = 0;; second++) {
    if (second >= 60) Assert.fail("timeout");
    try { if (selenium.isTextPresent("Software testing")) break; } catch (Exception e) {}
    Thread.sleep(1000);
   }
  }

  @AfterMethod
  public void tearDown() throws Exception {
   selenium.stop();
  }
 

}
The main difference in the above two functions is that you provide a Paramaterized option to the class in Junit and supply data to the constructor of the said class. Where as in TestNG you do the same at the test-method level.

Its simple to do data-driven testing in TestNG framework as you can provide a different data providing function for each test-method, but the same is not possible in Junit.

Tuesday, October 4, 2011

Running tests on Google Chrome using Webdriver

While automating your web-application using webdriver, many may have faced problems in executing your cases on Google-chrome. Whenever you try to use webdriver object for executing your cases on chrome using the following code:

DesiredCapabilities capability = DesiredCapabilities.chrome();

you most probably get the following error:

The path to the chromedriver executable must be set by the webdriver.chrome.driver system property; for more information, see http://code.google.com/p/selenium/wiki/ChromeDriver. The latest version can be downloaded from http://code.google.com/p/chromium/downloads/list

The solution to this error that has been mentioned in the given URL  "http://code.google.com/p/selenium/wiki/ChromeDriver" is  to set the chromedriver path to the variable "webdriver.chrome.driver". But how exactly to set the path and use it for your test execution is not given there. So I though to just document it here on my blog.

For setting the  "webdriver.chrome.driver" value and for using google-chrome to execute your automated tests, you can use one of the following methods:


Method - 1:
Start the selenium server using the following command:
java -Dwebdriver.chrome.driver=/path/to/chromedriver  -jar selenium-server-standalone-2.7.0.jar

And in your Java code you use the chrome driver in the following way:

 DesiredCapabilities capability = DesiredCapabilities.chrome();
WebDriver driver = new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"), capability);

The advantage of using this method is that you can execute your test-cases in a remote machine and this is advantageous when you want to run it on grid.


Method - 2:
Set the system property  "webdriver.chrome.driver" using System.setProperty()  in your code and then try to execute your cases on Chrome.

System.setProperty("webdriver.chrome.driver", "/path/to/chromedriver");
WebDriver driver = new ChromeDriver();

This method works well when your tests are getting execute on a local machine and you are not starting any selenium server.

Following are some important links for Chrome driver:
Webdriver Chromedriver page:
http://code.google.com/p/selenium/wiki/ChromeDriver


ChromeDriver download page for downloading the ChromeDriver server:
http://code.google.com/p/chromium/downloads/list