InfoQ

Article

Testing Ajax Applications with Selenium

Posted by Jeff Xiong, Mike Williams, Josh Price on Sep 25, 2006

Community
Java,
Agile,
.NET,
Ruby
Topics
Software Testing ,
Javascript
Tags
TDD ,
Selenium

Selenium at a Glance

Q: In a typical online store, many operations require user input in order to complete a purchase. As software developer, how can you ensure the quality and correctness of your implementation?

RelatedVendorContent

Agile Development: A Manager's Roadmap for Success

The Agile Project Manager

Unix, Linux Uptime & Reliability Increase While Patch Management Woes Plague Windows (Yankee Group)

Right Collaboration Architecture Drives Business Transformation

Learning to be a Good Product Owner: Foundation Skills

Related Sponsor

VersionOne is recognized by Agile practitioners as the leader in Agile project management tools. Companies such as Adobe, BBC, CNN, Dow, HP, IBM, Sony and 3M have turned to VersionOne to help deliver greater value to their customers.

For those of you who develop web applications for a living, it's a question you might encounter often. It would be really useful to be able to test the functionality of your application. But how?

Selenium is an functional testing tool written by ThoughtWorks specifically for Web applications. Selenium tests run directly in a browser, just like real users do. Selenium works in Internet Explorer, Mozilla, and Firefox on Windows, Linux, and Macintosh.

Take a look at the online demo to see Selenium in action. Click the "All" button in the top-right corner to start the test cases running, and with any luck everything should pass with beautiful green bars. Note that actions are a lighter shade of green than assertions, this is because they don't actually test anything like verify or assert commands. If an assertion fails, the failing command will go red and Selenium will stop executing. If on the other hand a verify command fails, it will go red, but won't bring the test to a grinding halt.

Test suites and cases in Selenium are written in HTML - actually they are just HTML <table>s. Every row in test suite is a reference to a test case, such as:

 <tr><td><a href="MyTest.html">MyTest</a></td></tr>

A test-case is represented by an HTML document written in "Selenese", containing a table with 3 columns, room enough for a command and two arguments. A typical test case looks like:

When you start a test-run (e.g. by pressing "All"), the Selenium TestRunner interprets the HTML test-case document, and drives your web-application, which appears in the bottommost frame.

By simulating user actions, Selenium allows you to test your application through it's user-interface. It most certainly does not replace unit-testing, but we often use it to automate functional acceptance tests for web-applications. It can be integrated into a continuous-integration build, for regular automated regression testing. For an in depth look at Selenium, please refer to the online documentation "Selenium: Usage".

Here Comes Ajax

Selenium is particularly useful when some of your web-application functionality is implemented on the browser, in JavaScript.

Ajax, short for Asynchronous JavaScript and XML, is a web development technique for creating interactive web applications. The intent is to make web pages feel more responsive by exchanging small amounts of data with the server behind the scenes, so that the entire web page does not have to be reloaded each time the user makes a change. This is meant to increase the web page's interactivity, speed, and usability.

The "Loading" flag is one of the indications of Ajax

That's the technical definition, but to most of us, Ajax means web pages that act like GMail or Flickr. When you click a link, it will not cause a page reload; instead the browser will converse with the server and refresh just a part of current page. The time delay between clicking a link and seeing the results is what makes things tricky.

Let's say we have a web page containing a text field and a button. The initial value of the text field is "oldValue". If you click the button, some Ajax magic will happen and the value of the text field will be changed to "newValue", without reloading the page. How do we go about testing this? The obvious approach approach is to open the page, click the button, then check the value of the text field. However when we did that in Selenium, the test case failed!

The reason for the test failure is perhaps not so obvious. What happens is that the asynchronous nature of the Ajax call means that the result doesn't come back from the server immediately. So the value of the field changed a few seconds after the button click, but Selenium checked the value immediately and got the old value! So if Selenium doesn't know to wait for the result, how can we get the brilliant Ajax effect tested?

Wait For It...

So how do we get Selenium to wait for the result? One way to solve the problem is to use the clickAndWait command instead of click; the "AndWait" suffix indicates that Selenium should wait for a page-reload. This might seem like it would work, but there's a catch: because the page is not reloaded, clickAndWait will make Selenium keep waiting forever. This clearly isn't going to work.

Another possibility is to insert a pause between the click and assertValue. So lets pause for 5 seconds in between, to give the server enough time to respond. This approach works most of the time, but it may fail if the server takes more than 5 seconds. This might happen for any number of reasons, slow network, overloaded test machine, and so on. You can keep increasing the pause before checking the result, but this will make your tests run slower and slower. So this clearly isn't the best solution because it's not guaranteed to work and makes your tests run much slower than necessary.

Fortunately Selenium has provided support for doing exactly what we want. When a field value changes in the current page, you can use the waitForValue command to make Selenium wait until the expected value appears.

So in order to make the failing test pass we need to replace the failing assertValue command with the following:

When executing this command, Selenium will suspend the execution of current test case and wait for the expected value. When the string "newValue" appears in the text field, the suspended test will go on. One thing to note: if you misspelled the expected value, Selenium will wait for 30 seconds before timing out.

As you may have already guessed, there are lots more commands that can be used to test Ajax effects. For example, if you want to check some plain text updated with Ajax, there's waitForText; if you want to check the title of current page, there's waitForTitle; if you want to verify that an HTML element is removed, there's waitForElementNotPresent. Actually, for every Selenium Accessor, there is a waitForXxxx and a waitForNotXxxx commands corresponding. Whenever you use verifyXxxx or assertXxxx to check something, there will always be a waitForXxxx for testing asynchronous effects.

What happens if the predefined waitForXxxx and waitForNotXxxx commands don't meet your needs? Well for this there is the waitForCondition command which allows you to specify a Boolean expression in Javascript which causes Selenium to wait until the expression evaluates to true. The declaration of waitForCondition is:

waitForCondition		script		timeout (in ms)

This could come in handy when testing more complicated Ajax effects.

Actually if you dig into the source code of Selenium, you'll find that all of the predefined waitForXxxx and waitForNotXxxx cousins are implemented using waitForCondition. Grig Gheorghiu wrote a splendid blog entry on this topic: Ajax testing with Selenium using waitForCondition. When Grig wrote the entry, waitForCondition was just a user extension of Selenium, but now it's part of Selenium core.

Summary

In this brief article, we introduced Selenium, a web acceptance testing tool. Also we discussed how to test Ajax applications with waitForXxxx Selenium commands, as well as demonstrated how to test a simple Ajax effect - an asynchronous text update - with Selenium.

If you want to know more about the waitForXxxx commands, Selenium developers provided a few sample test cases which will show you how to test some common Ajax effects, such as in place editing, auto completion and drag-drop. These samples are based on script.aculo.us, a popular Ajax library which you maybe already be familiar with.

Biography

Jeff Xiong serves ThoughtWorks as an Application Developer with four years of experience in the creation of large-scale enterprise applications and the integration of disparate systems.

Mike Williams is a Senior Developer with fifteen years of industry experience. Besides his Java experience, Mike is an enthusiastic user of dynamic/scripting languages.

Josh Price serves ThoughtWorks as a Developer. He has eight years of experience building enterprise systems using Java and J2EE.

very cool feature by Alex Popescu Posted Sep 25, 2006 4:41 PM
Re: very cool feature by Stefan Tilkov Posted Sep 28, 2006 3:39 AM
Good Article by jessica winslet Posted Apr 1, 2009 7:31 AM
Re: Good Article by Victor Hugo Saavedra Posted Oct 20, 2009 3:03 PM
Commercial tool support by Patrick Lightbody Posted Sep 28, 2006 8:55 AM
Re: Commercial tool support by Alex Popescu Posted Sep 28, 2006 4:49 PM
AJAX functional Testing by Alex F Posted Feb 16, 2007 11:40 AM
Re: AJAX functional Testing by meenakshi ghosh Posted Sep 4, 2008 12:53 PM
  1. Back to top

    very cool feature

    Sep 25, 2006 4:41 PM by Alex Popescu

    I must confess that in the past all my AJAX pages were tested using pause(), and not only because of Selenium limitations, but also because it gave me a way to see what happens when the server timeouts (which by the way is something that must be tested).

    Now, regarding the new commands I am noticing in the above example that you need to provide twice the future value (the waitForX command and also to the assert). I am wondering what were the reasons behind this decission, instead of having a single command/assertion that does both jobs (wait for result and assert).

    ./alex
    --
    :Architect of InfoQ.com:
    .w( the_mindstorm )p.
    Co-founder of InfoQ.com

  2. Back to top

    Re: very cool feature

    Sep 28, 2006 3:39 AM by Stefan Tilkov

    For Ruby, an alternative is to use the unit testing support built into script.aculo.us.

  3. Back to top

    Commercial tool support

    Sep 28, 2006 8:55 AM by Patrick Lightbody

    We're also very excited about this new release. The original work on the multiWindow mode actually came out of the commercial work we've been doing on HostedQA and AutoQ. The reason is that we didn't want our customers running tests in an iframe (like Selenium requires by default) as opposed to running in a normal browser window. (You can see what the reports/screenshots look like for some popular opensource projects here).

    If you find that you like Selenium, but wished it had some additional features (auto deployment of Java/Rails applications and databases, screenshot support, or refactoring features), then it might be worthwhile to check out our stuff. The nice thing is you can use Selenium IDE to import tests and you are free to export your tests at any time. Combine that with a free trial, and it's pretty much no-risk to check out.

    The next feature we're going to be pushing back in to the Selenium project is HTTPS support. Up until now, there was no way to test HTTPS applications with Selenium RC, but as of this week we've donated some code to the project that will allow this.

  4. Back to top

    Re: Commercial tool support

    Sep 28, 2006 4:49 PM by Alex Popescu

    Great job Pat! And thanks for contributing it back to the community.

    ./alex
    --
    :Architect of InfoQ.com:
    .w( the_mindstorm )p.
    Co-founder of InfoQ.com

  5. Back to top

    AJAX functional Testing

    Feb 16, 2007 11:40 AM by Alex F

    You can also check SWExplorerAutomation SWEA from webiussoft.com. SWEA was specially designed to support AJAX (DHTML) applications. SWEA supports windows (alerts, login) and html dialogs, popup windows, mouse input simulation, file downloads, frames (cross domain) and more. SWEA can test scripts can be used in NUnit and Visual Studio unit tests.

  6. Back to top

    Re: AJAX functional Testing

    Sep 4, 2008 12:53 PM by meenakshi ghosh

    Can anyone let me know how to capture a piece of data that is created randomly in a test flow using selenium HTML scripts?

    I need to know what command we can use to capture that random data generated in a page. Also I need to store the data and pass as a string in some other page.

    Can anyone throw some lights on this one?

  7. Back to top

    Good Article

    Apr 1, 2009 7:31 AM by jessica winslet

    I am trying to see if Selenium is good for testing my applicaton or not. Am using the Selenium Ide. I want to know where the core files are installed along with
    meilleur site de jeux de casino the IDE? I need to change the sample files where?

  8. Back to top

    Re: Good Article

    Oct 20, 2009 3:03 PM by Victor Hugo Saavedra

    Excelent.

    I don't know de waitForXXX, but i can't know the end httpRequest de ajax???


    sorry by my english, I speak and write only spanish, I am from Chile
    --
    Atte.
    Victor Hugo Saavedra.
    vhspiceros.blogspot.com

Educational Content

Brian Marick on 4 Challenges and 5 Guiding Values of Agile Software Development

Brian Marick takes us through a quick tour of the most important values and challenges to adopting Agile successfully (they aren't the typical challenges and values we hear in the community).

Are You a Software Architect?

The line between development and architecture is tricky. Does it exist at all? Is an ivory tower actually needed? There's a balance in the middle, but how do you move from developer to architect?

Agile – A Way of Life and Pragmatic Use of Authority

The word 'authority' sometimes produces an allergic response in hard-line agilists. Freedom and authority – both are bad if misused and both are good if used in right spirit for a noble cause.

Getting Started with Grails, Second Edition

"Getting Started with Grails" brings you up to speed on this modern web framework. Companies as varied as LinkedIn, Wired, and Taco Bell are all using Grails. Are you ready to get started as well?

Using ITIL V3 as a Foundation for SOA Governance

Those familiar with only ITIL V2 often scoff at the thought that ITIL could serve as a governance framework for SOA. With ITIL V3, the focus of the framework shifted towards service-orientation.

Adrian Colyer on AspectJ, tc Server and dm Server

SpringSource CTO Adrian Colyer discusses AspectJ, SpringSource's dm Server and tc Server products, OSGi and Scrum.

Adam Wiggins on Heroku

Heroku's Adam Wiggins talks about Rails, Background Jobs, Add-Ons, Ruby, and how Heroku manages to work around Ruby's inefficiencies using Erlang and other languages.

SOA as an Architectural Pattern: Best Practices in Software Architecture

For Grady Booch the foundation of a good architecture is patterns, SOA being just one of many patterns. In this Second Life presentation, Booch attempts to bring more clarity on what architecture is.