The Complete Magazine on Open Source

The Long and Short of Waits in Web Applications Using Selenium

710 0

The time taken to load a Web page impacts the user experience in a big way. Often, a Web page carries many Web elements which take time to load, and if this is too long, users tend to shift to another Web page, resulting in the loss of valuable business opportunities. This article focuses on one way to handle these delays while testing such applications using selenium for its functional accuracy

Most Web applications we deal with are developed using Ajax and JavaScript. In such cases, when a page is loaded by the browser, the Web elements will take some time to load and the loading time can be different in each run. This leads to different exceptions, resulting in a report with the wrong results even though the Web app is working correctly.

Handling the delays with accuracy

On noticing a delay in the appearance of a UI element on the page, let’s suppose we use Thread.sleep() to handle it. The next time we run the test, the UI element loads instantly. But what about Thread.sleep(), which we introduced into our code? It still halts the execution, thereby inducing the extra wait time even though it’s not required. Finally, executing our entire test suite takes its own sweet time to finish. Though the results are accurate and reliable, in a practical world, this approach makes no sense when manual intervention testing of the application gets the job done in one minute, compared to our automated script, which takes three minutes due to the extra overhead delay of sleep() that we introduced.

So to make automation robust and accurate, as well as to synchronise our test tool with the application under test by handling these delays dynamically, we use waits provided by Selenium.

Types of waits

  • Implicit wait: An implicit wait is to instruct WebDriver to poll the DOM for a certain amount of time when trying to find an element or elements, if these are not immediately available. The default setting is 0. Once set, the implicit wait is set for the life of the WebDriver object instance.

Declaration:

driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

When to use: Not recommended, but better than using Thread.sleep().

  • PageLoadTimeout wait: This wait is focused on the time a Web page needs to be loaded – the pageLoadTimeout limits the time that the script allots for a Web page to be displayed before proceeding with other operations on the Web elements present on the page. If the page loads within the time, then the script continues. If the page does not load within the timeout, the script will be stopped by a TimeoutException.

Declaration:

driver.manage().timeouts().pageLoadTimeout(50, TimeUnit.SECONDS);

Figure 1: Types of waits

When to use: Whenever you need to ensure a page is loaded in the optimum time before proceeding to perform an operation on WebElements.

  • SetScriptTimeout: This wait is applicable only for JavascriptExecutor, which provides us two methods for script execution — executeScript and executeAsyncScript.

The executeScript method will block the execution of the next line of code till the execution of this method is completed, and then it moves to the next line of code. The executeAsyncScript method does not block the execution of the next line of code till the execution of this method is completed.

Since the executeAsyncScript method doesn’t block the execution of the next line of code, we use driver.manage().timeouts().setScriptTimeout(5,SECONDS); to specify the amount of time for an asynchronous script to finish the execution before throwing an error.

Declaration:

driver.manage().timeouts().setScriptTimeout(5, TimeUnit.SECONDS);

When to use: Used to specify the amount of time for an asynchronous script to finish execution, or else it will take its own time to execute and may allow a bug to slip away.

  • FluentWait: Each FluentWait instance defines the maximum amount of time to wait for a condition, as well as the frequency with which to check the condition. The user may configure the wait to ignore specific types of exceptions while waiting, such as NoSuchElementExceptions when searching for an element on the page, and to ignore the exception to continue with script execution in case the element is not found.

Declaration:

Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)

.withTimeout(30, TimeUnit.SECONDS).pollingEvery(5, TimeUnit.SECONDS).ignoring(NoSuchElementException.class);

WebElement clickseleniumlink = wait.until(new Function<WebDriver, WebElement>() {public WebElement apply(WebDriver driver) {

return driver.findElement(By.xpath(“//*[@id=’login-button’]”));

}

});

When to use: Used when the element takes a different loading time to appear each time we run the test.

  • Explicit wait: This allows the user to direct the driver to wait for certain conditions to occur before proceeding further in the code. WebDriverWait by default calls the ExpectedCondition every 500 milliseconds until it returns successfully.

Declaration:

WebDriverWait wait = new WebDriverWait(driver, 10);

wait.until(ExpectedConditions.elementToBeClickable(By.xpath(“//*[@id=’login- button’]”))).click();

When to use: When the element takes a long time to load and also when there is a need to check the property of an element (e.g., element is clickable).

Effective use of waits in a real world

Using a combination of pageLoadTimeout + SetScriptTimeout and ExplicitWait in your framework ensures that the page is loaded at the optimal time, and that all asynchronous scripts are executed in a stipulated time. ExplicitWait helps to check the various properties of different elements based on the type of operation that needs to be performed. If there are any failures, it’s easy to find the root cause for them. Using this combination of waits in your framework can deliver the most robust and accurate results.