Book Image

Instant Selenium Testing Tools Starter

By : Unmesh Gundecha
Book Image

Instant Selenium Testing Tools Starter

By: Unmesh Gundecha

Overview of this book

<p>Selenium is a software testing framework for automating web applications for testing purposes. It uses components such as Selenium IDE, Selenium Client API, and Selenium Webdriver to test web applications, which provides an easy-to-use platform and lets you test your applications more effectively and efficiently.<br /><br />"Instant Selenium Testing Tools Starter" was born out of the need for a short, yet all-encompassing book that would give you a solid foundation in creating and running tests with Selenium testing tools. This book will enable you to harness the power of Selenium and put it to good use throughout the testing process, quickly and efficiently.<br /><br />The "Instant Selenium Testing Tools Starter" can be used as an end-to-end guide or as a desk reference, with sections that deal with all the key aspects of automating tests for web applications. A step-by-step description of key features is provided with the help of simple and concise examples. Each chapter will help you understand the key features of Selenium with tips and tricks that will become the foundation of your knowledge in the future.</p>
Table of Contents (7 chapters)
Instant Selenium Testing Tools Starter
Credits
About the Author
About the Reviewers
www.PacktPub.com
packtlib.packtpub.com

Top 5 features you'll want to know about


As you start using Selenium, you will realize that there are a wide variety of things that you can do with it. In this section, you will learn about the 5 most important Selenium IDE and WebDriver programming features that you will certainly want to know about. Here, you will learn how to work with running tests on different types of web browsers, locating elements, working with WebElements, synchronization, and capturing screenshots during test runs.

1 – Running tests on various browsers

One of the key features of Selenium is support for running tests on a variety of web browsers available. You can develop a test on one browser and run it on all the supported browsers as needed. This feature is essential for cross-browser testing of your web application. You can run tests on combinations of operating systems and web browsers.

  • Option 1 – running Selenium IDE tests on various browsers

    In the Quick start section, we created a test in Selenium IDE; however, as we saw, it only allows us to record and reply tests in Firefox. We can use the Selenium standalone server to run tests that are created with Selenium IDE on different browsers other than Firefox using the following steps:

    1. Download the latest release of Selenium standalone server from http://code.google.com/p/selenium/downloads/list.

    2. Open a command prompt/console window and type the following command:

      java -jar selenium-server-standalone-2.29.0.jar -htmlSuite *googlechrome http://demo.magentocommerce.com/ C:\SearchTests.html C:\Result.html
      

      Note

      We have used *googlechrome in the preceding command to run the tests in Google Chrome. You can also use *iexplore (Internet Explorer), *safari (Safari), and*firefox (Firefox) to run tests on these browsers.

      This command will launch the Selenium standalone server. We used the –htmlSuite option through which we can tell the server to execute the tests created using Selenium IDE. We also specified the browser on which we want to run the tests and the name of the test suite along with the path and name for the output result file. The server will launch Google Chrome and execute all the tests from the specified test suite.

  • Option 2 – running Selenium WebDriver tests on various browsers

    Selenium WebDriver implements support for various web browsers through driver classes, which provide driver specific functionality to the tests. The following list is of the major drivers supported by WebDriver:

    • Firefox

      FirefoxDriver is widely used and is a mature driver supporting most of the WebDriver core APIs including HTML5. Firefox driver is supported on major OS platforms including Windows, Linux, and Mac OS X.

      Language

      Syntax

      Java

      WebDriver driver = new FirefoxDriver();

      C#

      IWebDriver driver = new FirefoxDriver();

      Ruby

      driver = Selenium::WebDriver.for :firefox

      Python

      driver = webdriver.Firefox()

      For more information on FirefoxDriver, see http://code.google.com/p/selenium/wiki/FirefoxDriver.

    • Google Chrome

      ChromeDriver is supported by installing a standalone ChromeDriver server, which uses a JSON wire protocol to communicate between the Chrome browser and your test. chromeDriver is supported on major OS platforms including Windows, Linux, and Mac OS X. Chrome has certain minor support limitations and does not support the HTML5 API.

      Language

      Syntax

      Java

      WebDriver driver = new ChromeDriver();

      C#

      IWebDriver driver = new ChromeDriver();

      Ruby

      driver = Selenium::WebDriver.for :chrome

      Python

      driver = webdriver.Chrome()

      For more information on ChromeDriver, see http://code.google.com/p/selenium/wiki/ChromeDriver.

    • Internet Explorer

      InternetExplorerDriver is now a standalone server, which implements WebDriver's wire protocol. The driver supports running 32-bit and 64-bit versions of the browser on Windows.

      Language

      Syntax

      Java

      WebDriver driver = new InternetExplorerDriver();

      C#

      IWebDriver driver = new InternetExplorerDriver();

      Ruby

      driver = Selenium::WebDriver.for :ie

      Python

      driver = webdriver.Ie()

      For more information on InternetExplorerDriver, see http://code.google.com/p/selenium/wiki/InternetExplorerDriver.

    • Safari

      SafariDriver is added to the list of supported browsers recently. It is implemented as a Safari browser extension instead of the client/server model used in ChromeDriver and InternetExplorerDriver. It communicates with the WebDriver client using WebSockets supported on the Mac OS X and Windows platforms.

      Language

      Syntax

      Java

      driver = new SafariDriver();

      C#

      IWebDriver driver = new SafariDriver();

      Ruby

      driver = Selenium::WebDriver.for :safari

      Python

      driver = webdriver.Remote("http://localhost:4444/wd/hub ",webdriver.DesiredCapabilities.SAFARI)

      For information on SafariDriver, see http://code.google.com/p/selenium/wiki/SafariDriver.

    • Opera

      OperaDriver is developed by Opera Software and its community. It is supported on all major OS platforms and is available as a core API and standalone server.

      Language

      Syntax

      Java

      WebDriver driver = new OperaDriver();

      C#

      IWebDriver driver = new RemoteWebDriver(new Uri("http://localhost:4444/wd/hub

      "), DesiredCapabilities.Opera());

      Ruby

      driver = Selenium::WebDriver.for :opera

      Python

      driver = webdriver.Opera()

      For more information on OperaDriver, see http://code.google.com/p/selenium/wiki/OperaDriver.

    • iPhone/iPad

      IPhoneDriver allows testing web applications on iOS using a special application that uses UIWebView (a WebKit browser accessible for third-party applications) on iOS devices. This is done by installing and running a iWebDriver app on the iOS device or simulator.

      Language

      Syntax

      Java

      WebDriver driver = new IPhoneDriver();

      C#

      IWebDriver driver = new RemoteWebDriver(new Uri("http://localhost:3001/wd/hub"), DesiredCapabilities.IPhone());

      Ruby

      driver = Selenium::WebDriver.for :iphone

      Python

      driver = webdriver.Remote("http://localhost:3001/wd/hub", webdriver.DesiredCapabilities.IPHONE)

      For more information on iPhoneDriver, see http://code.google.com/p/selenium/wiki/IPhoneDriver.

    • Android

      AndroidDriver allows testing of web applications on the Android browser. Similar to iPhoneDriver, an Android application running on the device or emulator is used to run the tests.

      Language

      Syntax

      Java

      WebDriver driver = new AndroidDriver();

      C#

      IWebDriver driver = AndroidDriver();

      Ruby

      driver = Selenium::WebDriver.for :android

      Python

      driver = webdriver.Remote("http://localhost:3001/wd/hub", webdriver.DesiredCapabilities.ANDROID)

      For more information on AndroidDriver, see http://code.google.com/p/selenium/wiki/AndroidDriver.

    • RemoteWebDriver

      RemoteWebDriver is a critical component of Selenium that allows testing on browsers located on remote machines. You can use RemoteWebDriver for running your tests in a distributed architecture. The RemoteWebDriver consists of a client and server. The server is simply a Java Servlet running within the Jetty Servlet container. This servlet interacts with the various browsers. In the beginning of this section we saw selenium-server-standalone, which is the RemoteWebDriver server. The client is an instance of RemoteWebDriver, which communicates with the server via a JSON wire protocol similar to other drivers. We can specify what configuration is needed for testing by using DesiredCapabilities. For example we need to test an application on an iPad, and we can configure the RemoteWebDriver in the following way to run the test:

      WebDriver driver = new RemoteWebDriver(new URL("http://localhost:3001/wd/hub"), DesiredCapabilities.ipad());

      For more information on RemoteWebDriver, see http://code.google.com/p/selenium/wiki/RemoteWebDriver.

2 – Locating elements

One of the key features of Selenium is its ability to locate different types of elements used on a page and the ability to interact with them. Selenium provides various ways or strategies to locate elements and perform actions such as clicking, typing text, selecting an option from the element, or performing verification on the state or property of the element, such as a text value. We can also check if the element is enabled or disabled, is checked or unchecked.

  • Selenium IDE: For locating elements using Selenium IDE, you need to specify locator details in the Target field.

  • Selenium WebDriver: For locating elements using WebDriver, the driver interface provides the findElement() and findElements() methods, which take locator expressions and search for the matching element(s).

The following table describes some of the important locator strategies that you can use with IDE or WebDriver API:

Strategy

Description

Selenium IDE

Selenium WebDriver (Java)

identifier=<id>

Locates the first element that has the specified value for the @id attribute. IDs are uniquely assigned by developers for key elements on a page. This strategy is considered the most reliable and faster.

id=search

driver.findElement(By.id("search"))

name=<name>

Locates the first element with the specified value for the @name attribute.

name=search

driver.findElement(By.name("search"))

link=<textPattern>

Locates the link (anchor) element that matches the specified pattern in link text.

link=Nokia 2610 Phone

driver.findElement(By.linkText("Checkout") or driver.findElement(By.partialLinkText("Inbox ("))

(You can specify a partial link text instead of complete link text. This might be useful when links partially contain dynamic values.)

css=<cssSelectorSyntax>

Locates elements using CSS selectors (refer to http://goo.gl/a9v7T and http://goo.gl/c1IRf for more details). CSS selectors are useful when the above selectors do not work to identify elements uniquely. You can also use XPath as an alternative, but CSS is considered faster with respect to strategy as compared to XPath.

css=input.search (this will locate input element whose @class attribute has value 'search')

driver.findElement(By.cssSelector("input.search"))

xpath=<xpathExpression>

Locates elements using an XPath query. XPath is used to query XML documents and while HTML is subset of XML and browsers represent HTML documents as XHTML. We can use this strategy to locate elements.

xpath=//input[@class='search']

driver.findElement(By.xpath("//input[@class='search']"))

dom=<javascriptExpression>

This strategy uses JavaScript expressions to find elements from the document object model (DOM).

dom=document.getElementById("search")

NA

In addition to the aforementioned strategies, Selenium WebDriver supports the following strategies:

Strategy

Description

WebDriver API (Java) example

By class name

Locates the first element that has the specified value for the @class attribute

driver.findElements(By.className("search"))

By tag name

Locates elements

using their HTML tag

For example, we can locate all the link (anchor) elements from a page with driver.findElements(By.tagName("a"))

Note

Refer to Packt Publishing's Selenium Testing Tools Cookbook (http://www.packtpub.com/recipes-to-master-selenium-2-testing-tools-cookbook/book) for more information on locators.

3 – Working with HTML elements

Selenium provides an extensive support for the standard HTML elements used on a web page. You can interact with the HTML elements by using built-in commands and APIs for building simple to complex tests. The following table shows some key commands and API methods for interacting with a page and its elements:

Purpose

Selenium IDE

Selenium WebDriver (Java)

Click on an element

click

element.click()

Type a text

type

element.sendKeys()

Check a checkbox/radio button

check

If(!element.isSelected() {

element.click()

}

Uncheck Checkbox/Radio Button

uncheck

If(element.isSelected() {

element.click()

}

Select item(s) in a list or drop-down list

select

addSelection (for multi select)

element.selectByVisibleText("Option"); or

element.selectByVisibleValue("Option"); or

element.selectByVisibleIndex(1);

Remove selection from a list or a drop-down list

removeSelection

removeAllSelection

element.deselectByVisibleText("Option");

or

element.deselectByVisibleValue("Option");

or

element.deselectByVisibleIndex(1);

Get the inner text from the element

storeText

element.getText()

Get attribute value

-

element.getAttribute("attribute")

Selenium WebDriver provides the WebElement class for interacting with HTML elements.

4 – Synchronizing steps

When Selenium scripts are played back, the application may not always respond with the same speed, especially for applications using AJAX. For example, it might take a few seconds for the following:

  • To load page contents

  • For a window or pop up message to open

  • For a progress bar to reach 100 percent

  • For a status message to appear

  • For a button to become enabled

You can handle these anticipated timing problems by synchronizing your script to ensure that Selenium waits until your application is ready before performing a certain step. There are several options that you can use to synchronize your script using Selenium IDE and Selenium WebDriver.

Selenium IDE

Selenium IDE provides various built-in waitFor commands for handling synchronization problems in tests. The following is a is list of some waitFor commands:

Command

Condition

waitForPageToLoad

Delays execution until the page is fully loaded in the browser

waitForElementPresent

Delays execution until the specified element is present on the page

waitForElementNotPresent

Delays execution until the specified element is removed from the page

waitForTextPresent

Delays execution until the specified text is present on the page

waitForFrameToLoad

Delays execution until the contents of the frame are fully loaded in the browser

waitForAlertPresent

Delays execution until an alert window is displayed on the page

A number of these commands are run implicitly when other commands are being executed. For example, with respect to the clickAndWait command, when you click on an element, the waitForPageToLoad command is also executed.

Selenium WebDriver

Selenium WebDriver provides implicit and explicit wait conditions to handle synchronization problems. You can use these conditions in the following ways:

  • Option 1 – the implicit wait condition

    When an implicit wait condition is implemented, if Selenium WebDriver cannot find an element in the DOM, it will wait for a defined amount of time for the element to appear in the DOM. In other terms, an implicit wait condition polls the DOM for a certain amount of time when trying to find an element(s) if it is not immediately available. The default setting is 0. Once set, the implicit wait condition is set for the life of the WebDriver object's instance. Here is a sample test using the implicit wait condition:

    @Test
    public void testWithImplicitWait()
    {
      //Go to the Demo AJAX Application
      WebDriver driver = new FirefoxDriver();
      driver.get("http://dl.dropbox.com/u/55228056/AjaxDemo.html");
    
      //Set the Implicit Wait time Out to 10 Seconds
      driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
    
      try {
          //Get link for Page 4 and click on it
          WebElement page4button = driver.findElement(By.linkText("Page4"));
          page4button.click();
    
          //Get an element with id page4 and verify it's text
          WebElement message = driver.findElement(By.id("page4"));
          assertTrue(message.getText().contains("Nunc nibh tortor"));
      } catch (NoSuchElementException e) {
        fail("Element not found!!");
        e.printStackTrace();
      } finally {
        driver.close();
      }
    }

    However, an implicit wait condition may slow down your tests when an application responds normally, as it will wait for each element appearing in the DOM and increase the overall execution time. It is recommended to avoid or minimize the use of an implicit wait condition.

    Note

    Minimize or avoid using an implicit wait condition in your scripts and try to handle synchronization issues with an explicit wait condition, which provides more control as compared to an implicit wait condition.

  • Option 2 – the explicit wait condition

    The explicit wait condition provides a better control compared with an implicit wait condition. Unlike an implicit wait condition, you can write custom code or conditions for a wait before proceeding further in the code. An explicit wait condition can only be implemented in cases where synchronization is needed and the rest of the script is working fine.

    The Selenium WebDriver provides the WebDriverWait and ExpectedCondition classes for implementing an explicit wait condition. You can use these classes in the following way:

    @Test
    public void testExplcitWaitTitleContains()
    {
      //Go to the Google Home Page
      WebDriver driver = new FirefoxDriver();
      driver.get("http://www.google.com");
    
      //Enter a term to search and submit
      WebElement query = driver.findElement(By.name("q"));
      query.sendKeys("selenium");
      query.click();
    
      //Create Wait using WebDriverWait.
      //This will wait for 10 seconds for timeout before title is updated with search term
      //If title is updated in specified time limit test will move to the text step
      //instead of waiting for 10 seconds
      WebDriverWait wait = new WebDriverWait(driver, 10);
      wait.until(ExpectedConditions.titleContains("selenium"));
    
      //Verify Title
      assertTrue(driver.getTitle().toLowerCase().
      startsWith("selenium"));
      driver.quit();
    }

    The ExpectedCondition class provides a set of predefined conditions to wait before proceeding further in the code. The following table shows some common conditions that we frequently come across when automating web browsers supported by the ExpectedCondition class:

Predefined condition

Selenium WebDriver (Java)

An element is visible and enabled

elementToBeClickable(By locator)

An element is selected

elementToBeSelected(WebElement element)

Presence of an element

presenceOfElementLocated(By locator)

Specific text present in an element

textToBePresentInElement(By locator, java.lang.String text)

Element value

textToBePresentInElementValue(By locator, java.lang.String text)

Title

titleContains(java.lang.String title)

5 – The Page Object pattern

The Page Object pattern provides tests for an interface, where a test can operate on the logical functionality offered by the page in a manner similar to the user accessing the page, but by hiding its internals. For example, if we build a Page Object for a login page that will provide a method to log in by accepting the username and password, and will take the user to the home page of the application. The test need not worry about what type of input controls are used for the login page, their locator details, navigation, and so on.

Tests should use objects of a page at a high level, where any change in layout or attributes used for the fields in the underlying page should not break the test.

Selenium WebDriver provides outstanding support for implementing the Page Object pattern via its PageFactory class. The Page Object pattern brings the following advantages for your tests:

  • It helps in building a layer of abstraction separating automation code, which knows about locating application elements and the one which interacts with these elements for actual testing

  • It provides a central repository of pages from the application for tests

  • It provides high maintainability and reduction in code duplication

The login page class provides an interface to the login page of the application to the tests as shown in the following diagram:

Here is Page Object for the login page of the test application.

The login page class contains locator details for the key elements needed for user login functionality. Elements from the login page are defined as private members of the LoginPage class. The test code will not have access to these elements. The LoginPage class provides a public login() method to the tests. The test needs to pass the e-mail address and password for a registered user to this method. The constructor of the LoginPage class uses the PageFactory.initElements() method to initialize WebElements defined in the class in the following way:

package demo.magentocommerce.pages;


import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;

public class Login {

  @FindBy(id="email")
  private WebElement emailField;

  @FindBy(id="pass")
  private WebElement passwordField;

  @FindBy(id="send2")
  private WebElement loginButton;

  public Login(WebDriver driver) {
    PageFactory.initElements(driver, this);
  }

  public void login(String email, String password) {
    emailField.sendKeys(email);
    passwordField.sendKeys(email);
    loginButton.click();
  }
}

Here is a sample test using the LoginPage class. The instance of the LoginPage class is created by passing the current driver instance. The login() method is called in the following way:

...
//Navigate to the Login Page
WebDriver driver = new FirefoxDriver();
driver.get("http://demo.magentocommerce.com/customer/account/login/");

//Create an instance of Login page and call the Login function 
LoginPage loginPage = new LoginPage(driver);
loginPage.login("[email protected]","xxxx");

//Verify the user is logged in
...

Note

Refer to Packt Publishing's Selenium Testing Tools Cookbook for more information on Page Object pattern's advanced techniques.