Selenium 101: Navigating Waits and Sleeps

  February 22, 2018

Understanding waits and sleeps is an essential component of forming a comprehensive Selenium testing strategy.

Waits can be used in Selenium to make our tests less flaky, help us debug, and to generally slow down our testing experience. Now, you might not want to do that for production code, but we'll go through some examples later where it can be really helpful.

Waits are a necessity when dealing with heavily dynamic web pages filled with JavaScript. Browser pages don't load all at once; elements get added over time as they're received from the network. So if our tests expect a page element to be present immediately, they won't find it, and our test will fail, even though that element might load a few milliseconds later. Waits help us add a bit of time in our test to wait for the latency of the browser, or the promise in a JavaScript action, such as clicking a button.

There are also multiple types of waits including:

  • Implicit Waits
  • Explicit Waits
  • Sleeps

We'll go over the best ways to use each one.

Implicit Waits

Implicit waits are a way to tell our entire test to poll the DOM, or wait and recheck for a certain amount of time, for an element to be present to continue on to the next step or fail our test.

You can simply write an implicit wait of, say, 10 seconds at the start of your test and your test will wait at most 10 seconds for any object in the DOM to be present before continuing its instructions.

Notice we said at most - if the DOM element is present before your Implicit Wait time, the test will continue.

Here's how we might use an implicit wait on CrossBrowserTesting:

var webdriver = require('selenium-webdriver');

//create driver object for chromedriver

var driver = new webdriver.Builder()

.forBrowser('chrome')

.build();

driver.manage().timeouts().implicitlyWait(10);

function searchForCrossBrowserTesting() {

searchbar = driver.findElement(webdriver.By.name('q'))

.then(function(searchbar) {

searchbar.sendKeys('CrossBrowserTesting.com');

searchbar.submit();

});

}

function clickTreehouse() {

clickLink = driver.findElement(webdriver.By.linkText("Cross Browser Testing Tool: 1500+ Real Browsers & Devices"))

.then(function(clickLink) {

clickLink.click();

});

}

driver.get('http://google.com')

.then(searchForSmartBear())

.then(clickSmartBear());

driver.quit()

In the example, we have added the implicit wait to the driver which will persist throughout all the commands. In this particular case, it will wait for 10 milliseconds to find the element and give time load the DOM to find the element. It will return an error if the driver is not able to find it in the given timeframe.

Note that Increasing the implicit wait timeout should be used judiciously as it will have an adverse effect on test run time.

What happens without using an implicit wait? Once the implicit wait is set, it will set for the life of the webdriver object, and if there is no implicit wait the default is set to zero.

The load time for different websites varies from each other. As we learned, implicit waits tell webdriver to wait for a particular number of seconds. If implicit wait is not included there will be error thrown up by the program because the webdriver did not wait until the DOM is completely loaded and it was not able to find out the “login-in-message".

Explicit Waits

Explicit waits are more direct and narrow than their implicit cousins and help us pinpoint our wait times, giving us the flexibility to place a specific wait time on each individual web element. You must set your specific explicit wait time on each command, which is the biggest drawbacks to Explicit Waits. However, they come with a huge advantage to testers who use them correctly.

Explicit waits allow us to make incredibly robust tests with pinpoint accuracy allowing for a wait of 8 seconds for an animation to finish loading, but only a 1.5-second wait for a button.

Let's look at an example:

var webdriver = require('selenium-webdriver');

//create driver object for chromedriver

var driver = new webdriver.Builder()

.forBrowser('chrome')

.build();

function searchForCrossBrowserTesting() {

searchbar = driver.wait(webdriver.until.elementLocated(webdriver.By.name('q')), 500)

.then(function(searchbar) {

searchbar.sendKeys('SmartBear.com');

searchbar.submit();

});

}

function clickCrossBrowserTesting() {

clickLink = driver.wait( webdriver.until.elementLocated(webdriver.By.linkText("Cross Browser Testing Tool: 1500+ Real Browsers & Devices")),

.then(function(clickLink) {

clickLink.click();

});

}

driver.get('http://google.com')

.then(searchForCrossBrowserTesting())

.then(clickCrossBrowserTesting());

driver.quit();

In function searchForCrossBrowserTesting the webdriver will wait up to 500 milliseconds for locating an element “ q ” before throwing a TimeoutException. A successful return value for the function is a True Value i.e., boolean.

If the explicit waits are not included in the commands and the webdriver is not able to complete certain condition before running the next commands in the code, there will be an error while running the code.

Explicit waits are used when we know particular element will take more time to visible, so we put expected condition of time to wait.

Sleeps

Sleeps are used for to put your entire script to sleep for a set amount of time, and they will not be “woken up”. Waits will stop waiting once an object is found, making it sometimes difficult to debug tests. With sleeps, we can add consistent pauses to our tests - allowing you to watch exactly what’s happening with your test.

An example of using a sleep would look like the following:

var webdriver = require('selenium-webdriver');

var sleep = require('sleep');

//create driver object for chromedriver

var driver = new webdriver.Builder()

.forBrowser('chrome')

.build();

function searchForCrossBrowserTesting() {

searchbar = driver.findElement(webdriver.By.name('q'))

.then(function(searchbar) {

searchbar.sendKeys('CrossBrowserTesting.com');

searchbar.submit();

});

}

function clickCrossBrowserTesting() {

clickLink = driver.findElement(webdriver.By.linkText("Cross Browser Testing Tool: 1500+ Real Browsers & Devices"))

.then(function(clickLink) {

clickLink.click();

sleep.sleep(15)//sleep for 5 seconds

});

}

driver.get('http://google.com')

setTimeout(function() {

searchForCrossBrowserTesting();

setTimeout(function() {

clickCrossBrowserTesting();

setTimeout(function() {

driver.quit();

}, 5000)

}, 5000);

}, 5000);

Sleeps completely stop script execution even if the next element you're looking for has been loaded into the page, so they can make your tests take significantly longer to run. For this reason, you should avoid using sleeps in production tests where possible. Sleeps should generally be used only for debugging. Sleeping briefly while the page loads might be all right in production tests if waits simply can't do the job, but it should be for a few milliseconds at most.

Conclusion

Implicit waits, explicit waits, and sleeps all have different use cases when it comes to testing with Selenium. Understanding when and how to use each will help you run passing tests and properly debug. As you begin learning Selenium testing, waits and sleeps will be an invaluable tool to write successful test automation.

Check out the rest of our blogs for more on Selenium 101: