views:

100

answers:

5

Our team has been testing our application with Selenium as it's heavily JavaScript driven we've always had issues with tests occasionally failing. As the number of tests has increased the probability of at least one two tests failing in a complete run has become a certainty.

What we recently figured out is that we probably have a race condition where selenium will click links before the initialization JavaScript has had a chance to attach event handlers to the element that is being clicked. Of course at this point the effects we're looking for don't happen and we get a failing test.

For the time being we've added a slight delay before clicks to give the initialization JavaScript code time to finish, this is obviously a bit hackish, adds time to overall test execution, and doesn't guarantee tests won't still fail so we're looking for a better solution.

The best idea we've come up with so far is to inject a hidden element into the DOM that Selenium can wait for, before firing the click event to know that it's ready. This will be a lot of extra overhead in terms of developer time when we're working our asynchronous events, removing and adding the element. Also it adds extra stuff to our pages that really isn't necessary for the application.

Does anyone have any better strategies? What have you done to effectively solve this problem?

+1  A: 

I did exactly like you : add some delay and wait for some elements to be present on the page. And I'm perfectly fine with it. Maybe switching to Webdriver / selenium 2.0 would help though. Test execution can be trimmed down if you work with an in-memory database or sharing the same selenium/selenium server between tests, or even with parallelization (easy with TestNG for instance).

Pierre Gardin
There is, of course, also the excellent Selenium Grid for running lots of tests at once across multiple machines.
Chris Knight
A: 

We moved to Selenium 2 (WebDriver) and are using Page Objects pattern with PageFactory/AjaxElementLocatorFactory - an example of this is here

ZloiAdun
A: 

Have you tried the waitForElementPresent command, and then make it click ?

Erwan
A: 

To eliminate race conditions use Selenium's runScript(String initCondition) combined with waitForCondition(String jsConditional, String timeout) methods.

For example, if the AJAX functionality you want to test causes a new element to be added to the dom you can use something like the following.

String jsPoll = "";
jsPoll += "selenium.browserbot.getCurrentWindow()";
jsPoll += ".document.getElementById('DOMID')";
selenium.waitForCondition(jsPoll, "30000");

The condition will evaluate true when the element is added and the method will continue. If your AJAX function swaps elements (ie: one div for another similarly identified div), you can initialize your conditional with something like the following.

String jsInit = "";
jsInit += "!selenium.browserbot.getCurrentWindow()";
jsInit += ".document.getElementById('DOMID').setAttribute('SELENIUMTEST','1')";
String jsPoll = "";
selenium.runScript(jsInit);
jsPoll += "selenium.browserbot.getCurrentWindow()";
jsPoll += ".document.getElementById('DOMID').getAttribute('SELENIUMTEST') != 1";
selenium.waitForCondition(jsPoll, "30000");

The condition evaluates true when the element is swapped out by the AJAX function.

CitizenForAnAwesomeTomorrow
A: 

IMHO delays are not a good solution (only a workaround).

We use the image recognition feature of iMacros for testing tricky AJAX (and Flash). For selenium, maybe you can combine it with AutoHotKey (which has basic image search included and is popular as desktop app testing tool)? http://www.autohotkey.com/docs/commands/ImageSearch.htm

Ruby8848