Blog/

Selenium

Selenium Tips: Infinite Loops Take Forever

Sauce Labs Author

Sauce Labs Author

December 10, 2018

Selenium Tips: Infinite Loops Take Forever

In Selenium, it's a common for the tool to get ahead of the browser. Thus, the element we want to click on does not exist yet - but it will!

We’ll start with a sample html page that pauses four seconds before injecting a link onto the page. In practice, this would probably be a wait for javascript to make a REST API call and push the results into the document.

Our naive test for the link in simple ruby:

element = @driver.find_element :xpath, "//a[text() = 'Sauce Labs']"assert_equal('https://www.saucelabs.com/', element.attribute('href'));

It only fails because the link does not exist on the page (yet). The simple fix, in the terrible_example, is to add a sleep.

Don’t do that.

Our next attempt will be infinite_loop.rb, which uses a while loop to wait for the link text to appear on the page:

#And now we'll do the text for the HREF to appear page_source = @driver.page_source includes_sauce = page_source.include? "Sauce Labs"; while not (includes_sauce)  sleep(0.01);  page_source = @driver.page_source;  includes_sauce = page_source.include? "Sauce Labs"; end

This works just fine, until we have some sort of error where the text never appears - the exact kind of bug our software is looking for. Now when that happens we’ll be stuck in an infinite loop. That’s no good.

We’ll write two functions to do this. First, we can pull body_contains logic into a method:

  def body_contains(driver,expected_content)     source = driver.page_source;     puts "expected ( " +  expected_content + " ) \n\n";     puts "source ( " +  source + " ) \n\n";     puts (source.include? expected_content).to_s();     return source.include? expected_content;   end

Then we can write the containher function:

  #Adapted with permission from other Sauce Labs Examples   def contains_with_timeout(driver, expected, timeout=60)    start = Time.now();    found = false;    puts start.to_s();    puts Time.now().to_s();

 while (Time.now()-start<timeout) and not found        if body_contains(driver, expected)            found = true;        else          sleep(0.25);        end    end    return found;   end

It won’t take much to adapt this so that contains_with_timeout is actually anything_with_timeout, where the comparison method is passed in during the function call.

For now, here’s the code for our wait:

contains_with_timeout(@driver,"Sauce Labs");

Read the code yourself in github as timer.rb. The directory in github contains all three full running example and the sample HTML page. Experiment with changing the timeouts and delays to see the errors fire.

That’s right, I said four.

WAIT, THERE'S MORE!

Selenium webdriver includes Explicit Wait, the fourth example in our set.

That code is as simple as:

#And now we'll do the text for the HREF to appear wait = Selenium::WebDriver::Wait.new(:timeout => 15) # seconds begin    element = wait.until { @driver.find_element(:id => "truth") } ensure

end assert_equal('https://www.saucelabs.com/', element.attribute('href'));

So go ahead, use the webdriver explicit wait.

We just thought you might appreciate knowing how to do it yourself.

On This Page

Free trial

Sign up Free

Start testing smarter with the world's largest continuous testing cloud — now with AI built in.

Start Testing

Keep reading.

VIEW ALL POSTS
Selenium
VIEW ALL POSTS