While running any web application it’s necessary to take loading time into consideration. If your code tries to access any element that is not yet loaded, WebDriver will throw an exception and your script will stop.
There are three types of Waits -
Implicit waits are used to set the waiting time throughout the program, while explicit waits are used only on specific portions.
An implicit wait is to tell WebDriver to poll the DOM for a certain amount of time when trying to find an element or elements if they are not immediately available. Implicit waits are basically your way of telling WebDriver the latency that you want to see if specified web element is not present that WebDriver is looking for. The default setting is 0. Once set, the implicit wait is set for the life of the WebDriver object instance. Implicit wait is declared in the instantiation part of the code using the following snippet.
Example in Java:
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
// You need to import the following class - import java.util.concurrent.TimeUnit;
Example in C#:
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(15));
So in this case, you are telling WebDriver that it should wait 15 seconds in cases of specified element is not available on the UI (DOM).
You may encounter instances when some element takes more time to load. Setting implicit wait for such cases doesn’t make sense as browser will wait unnecessarily for the same time for every element, increasing the automation time. Explicit wait helps here by bypassing implicit wait altogether for some specific elements.
Explicit waits are intelligent waits that are confined to a particular web element. Using explicit waits you are basically telling WebDriver at the max it is to wait for X units of time before it gives up.
Explicit waits are done using the WebDriverWait and ExpectedConditions classes. In the below example, we shall wait up to 10 seconds for an element whose id is username to become visible before proceeding to the next command. Here are the steps.
Example in Java:
//Import these two packages:
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
//Declare a WebDriverWait variable. In this example, we will use myWaitVar as the name of the variable.
WebDriverWait myWaitVar = new WebDriverWait(driver, 30);
//Use myWaitVar with ExpectedConditions on portions where you need the explicit wait to occur. In this case, we will use explicit wait on the username input before we type the text tutorial onto it.
myWaitVar.until(ExpectedConditions.visibilityOfElementLocated(By.id(“username”)));
driver.findElement(By.id(“username”)).sendKeys(“tutorial”);
ExpectedConditions class has some predefined common conditions to wait for an element. Click here to see list of these conditions in Java binding.
Example in C#:
using OpenQA.Selenium;
using OpenQA.Selenium.Support.UI;
using OpenQA.Selenium.PhantomJS;
// You can use any other WebDriver you want, such as ChromeDriver.
using (var driver = new PhantomJSDriver())
{
driver.Navigate().GoToUrl("http://somedomain/url_that_delays_loading");
// We aren't going to use it more than once, so no need to declare this a variable.
new WebDriverWait(driver, TimeSpan.FromSeconds(10))
.Until(ExpectedConditions.ElementIsVisible(By.Id("element-id")));
// After the element is detected by the previous Wait,
// it will display the element's text
Console.WriteLine(driver.FindElement(By.Id("element-id")).Text);
}
In this example, system will wait for 10 seconds until the element is visible. If the element will not be visible after the timeout, the WebDriver will throw a WebDriverTimeoutException
.
Please note: If the element is visible before the 10 second timeout, system will immediately proceed for further process.
Unlike implicit and explicit wait, fluent wait uses two parameters. Timeout value and polling frequency. Let’s say we have timeout value as 30 seconds and polling frequency as 2 seconds. WebDriver will check for element after every 2 seconds until timeout value (30 seconds). After timeout value is exceeded without any result, exception is thrown. Below is a sample code which shows implementation of fluent wait.
Example in Java:
Wait wait = new FluentWait(driver).withTimeout(30, SECONDS).pollingEvery(2, SECONDS).ignoring(NoSuchElementException.class);
WebElement testElement = wait.until(new Function() {
public WebElement apply(WebDriver driver) {
return driver.findElement(By.id("testId"));
}
});
Another advantage of using fluent wait is, we can ignore specific types of exceptions (Eg. NoSuchElementExceptions) while waiting. Due to all these provisions, fluent wait is helpful in AJAX applications as well as in scenarios when element load time fluctuates often. Strategic use of fluent wait significantly improves automation efforts.