Google Analytics

Search

To search for specific articles you can use advanced Google features. Go to www.google.com and enter "site:darrellgrainger.blogspot.com" before your search terms, e.g.

site:darrellgrainger.blogspot.com CSS selectors

will search for "CSS selectors" but only on my site.


Tuesday, January 10, 2012

waitForElement

If you have Ajax calls or javascript which updates the page after the page has finished loading, you may have to wait for that code to finish before you can interact with the page. Essentially, waiting for page load is not sufficient.

The best way to deal with this is watch for something in the DOM which signals the script has finished executing. However, this is not always the easiest solution. If you are not the developer or familiar with javascript, it could take you days to figure out what event or change you need to wait for.

A better solution is to wait for whatever you want to interact with to be done. If you are waiting for a SELECT tag to be loaded with OPTION tags via Ajax there is no need to wait for the entire page to finish loading. You can just wait for the OPTION you wait to appear on the SELECT.

The best wait to do this is:

  1. wait for a short period of time (250ms)
  2. check for element
  3. if element does not exist go to 1
There is one problem with this algorithm. If the element never appears, this becomes an infinite loop. So we add a time out:
  1. maxTime = 5 seconds
  2. timeSlice = 250 ms
  3. elapsedTime = 0
  4. wait for timeSlice
  5. elapsedTime += timeSlice
  6. check for element
  7. if element does not exist AND elapsedTime < maxTime go to 4
Finally, this method must return true or false, where false means we did not find the element:
  1. maxTime = 5 seconds
  2. timeSlice = 250 ms
  3. elapsedTime = 0
  4. wait for timeSlice
  5. elapsedTime += timeSlice
  6. check for element
  7. if element does not exist AND elapsedTime < maxTime go to 4
  8. if elapsedTime < maxTime return true // found it
  9. else return false // timed out
In Selenium and Java this might look like:

public WebElement waitForElement(By by) {
    WebElement result = null;
    long maxTime = 5 * 1000; // time in milliseconds
    long timeSlice = 250;
    long elapsedTime = 0;

    do {
        try{
            Thread.sleep(timeSlice);
            elapsedTime += timeSlice;
            result = driver.findElement(by);
        } catch(Exception e) {
        }
    } while(result == null && elapsedTime < maxTime);

    return result;
}

.

2 comments:

Anand said...

Thanks for the post.
quick question...if I already have implicit wait, then do I have to still implement this wait?

Darrell said...

Standard answer: It depends. Generally speaking I have found that the wait feature of Selenium is hit or miss. So many people are doing so many different things on web sites that I just find it easier to use something like waitForElement all the time. The overhead is fairly minimal. On the other hand, if you don't use it and it turns out you need it, finding timing issues can be difficult and time consuming.