Agile Zone is brought to you in partnership with:

I am a programmer and architect (the kind that writes code) with a focus on testing and open source; I maintain the PHPUnit_Selenium project. I believe programming is one of the hardest and most beautiful jobs in the world. Giorgio is a DZone MVB and is not an employee of DZone and has posted 636 posts at DZone. You can read more from them at their website. View Full User Profile

Getting started with Selenium 2

10.25.2011
| 11732 views |
  • submit to reddit

Selenium 2 features new Api and implementations which goes under the name of WebDriver. It's a simpler, faster, object-oriented Api that applies to modern web application testing problems. No more sending hexedecimal numbers into an element for writing text!

A crucial innovation is that you do not need to run a Selenium Server to use the WebDriver Java Api locally, for example to run Firefox on a Linux system like I do. The server can be run independently, but just for compatibility with Selenium 1.x, in grids for distributed testing, or to provide support for bindings in other languages.
WebDriver runs directly the browser, as Selenium always did; it does not run in a JavaScript cage. The supported bindings currently are Java, C#, Python, and Ruby; PHP and Perl can access WebDriver via 3rd party bindings.

The drivers

WebDriver is the name of the Java interface that the various browser drivers implement; you will alway write code tha tonly depends on this interface.
The main drivers provided are:

  • HTMLUnit, which uses Rhino as JS and does not render pages. It's not a real browser, but it's really fast and supports JavaScript although the support is disabled by default (but easily re-enabled).
  • Firefox
  • Internet Explorer, tested up to the 8.x version, and working only on Windows machines.
  • Google Chrome to test an example of Webkit browser.

Other drivers include Opera, Android, and iPhone, with the last two running on actual devices or emulators.

The features

At least in the Java Api, readability is greatly enhanced by the usage of little configuration objects like By.id() and ExpectedCondition.

The interaction with the DOM is mostly blocking, and there are different ways to wait for events:

  • explicit waits, which span from a simple sleep in the worst case to waiting until a condition (like the presence of text) is satisfied. You need to add code in order to wait: that's why they're called explicit.
  • Implicit waits, where Selenium continues to poll the DOM until an element is found (because it was created or added), with the option of a timeout. Implicit wais are set once at startup, and you'll hopefully never have to worry again about further synchronization.

I saw even support for screenshots in the documentation, in case you want to test brittle pixel-perfect layouts.

A Java example (the most immediate Api)

I downloaded the Java bindings a a single archive, but you can use Maven as suggested in the official documentation. I placed on the class path the selenium-java-2.9.0.jar and all the jars provided in libs.

I then run this test taken from the docs (slightly modified):

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;


public class GoogleSearchTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        System.out.println(System.currentTimeMillis());
        // TODO Auto-generated method stub
        // Create a new instance of the Firefox driver
        // Notice that the remainder of the code relies on the interface,
        // not the implementation.
        WebDriver driver = new FirefoxDriver();

        // And now use this to visit Google
        driver.get("http://www.google.com");
        // Alternatively the same thing can be done like this
        // driver.navigate().to("http://www.google.com");

        // Find the text input element by its name
        WebElement element = driver.findElement(By.name("q"));

        // Enter something to search for
        element.sendKeys("Cheese!");

        // Now submit the form. WebDriver will find the form for us from the element
        element.submit();

        // Check the title of the page
        System.out.println("Page title is: " + driver.getTitle());
        
        // Google's search is rendered dynamically with JavaScript.
        // Wait for the page to load, timeout after 10 seconds
        (new WebDriverWait(driver, 10)).until(new ExpectedCondition<Boolean>() {
            public Boolean apply(WebDriver d) {
                return d.getTitle().toLowerCase().startsWith("cheese!");
            }
        });

        // Should see: "cheese! - Google Search"
        System.out.println("Page title is: " + driver.getTitle());
        
        //Close the browser
        driver.quit();
        System.out.println(System.currentTimeMillis());
    }
}

It took about 8 seconds to run with Firefox on Linux. Repeated executions seem to be very stable.

I'll have to do more serious testing anyway, to check the typical pain points of in-browser testing:

  • events such as clicks and focus; the support seems more reliable as they are now generated by controlling the interface of the browser instead of by executing JavaScript code.
  • rich text editing;
  • waiting for the completion of Ajax calls;
  • errors in translation between Api in different languages, for example by calling WebDriver from a PHP process.

Work in progress

I am not entering into design of a HTTP-based test suite for now (exploring patterns such as Page Object). Selenium 2 support in other languages such as PHP is also an important field to explore as we would like to have a test suite written in a single language for each of our applications: a single command to run and a single report to read. WebDriver exposes a REST-like access so theoretically it is possible to write a binding in any language which can perform HTTP requests.

Selenium's documentation is being rewritten to show WebDriver's capabilities, and it is definitely a work in progress. However, due to its popularity, expressive power and trusted source (ThoughtWorks) it would probably be the standard platform for end-to-end testing of web applications for the years to come.

Published at DZone with permission of Giorgio Sironi, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)