In a web application, the elements are loaded at different time intervals of the entire page load. There is a possibility of ElementNotVisibleException if the element that we are trying to find is not present when the webdriver tries to find it. To address this problem, we can use webdriver waits, it helps to have certain amount of time pass by before execution of the next steps or before a webdriver tries to find an element.
There are mainly two types of waits
- Explicit waits
- Implicit waits
The explicit wait is used to wait for a certain condition to occur before executing the next steps. If the element is not found within the specified timeframe, code will throw the TimeoutException.
WebDriver driver = new FirefoxDriver(); driver.get("http://www.abc.com"); // The webdriverwait class object has a new wait of 10 seconds before throwing // the TimeoutException WebDriverWait wait = new WebDriverWait(driver, 10); // The webdriver is set to wait for 10 seconds until the myDynamicElement // element is present in the DOM. If the driver doesn't find the element within // 10 seconds then it will throw a TimeoutException. WebElement myDynamicElement = wait.until(ExpectedConditions.presenceOfElementLocated(By.id("myDynamicElementId")));
The following are few of the ExpectedConditions that can be used in Explicit Wait:
textToBePresentInElement(WebElement element, String text)
textMatches(By locator, Pattern pattern)
numberOfElementsToBeMoreThan(By locator, Integer number)
numberOfElementsToBeLessThan(By locator, Integer number)
numberOfElementsToBe(By locator, Integer number)
attributeToBe(WebElement element, String attribute, String value)
attributeContains(By locator, String attribute, String value)
visibilityOfNestedElementsLocatedBy(By parent, By childLocator)
presenceOfNestedElementLocatedBy(By locator, By childLocator)
The Implicit wait is used to let the webdriver wait for a certain amount of time when trying to find an element that is not immediately available in the webpage. The default wait time is 0 seconds. Once set, this wait time is applicable for all the web elements and it will last forever for the object instance.
WebDriver driver = new FirefoxDriver(); // Below statement sets an implicit wait for 10 seconds driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); // get any website that delays in loading the content. driver.get("http://www.abc.com"); // WebDriver will now wait for at most 10 seconds to find this element WebElement myDynamicElement = driver.findElement(By.id("myDynamicElement"));
Which one to choose?
In most cases one would prefer explicit wait because it gives a control over finding each web element based on a specified condition, for example for some web elements we are concerned with their presence in the DOM but for others we are concerned on their visibility on the page.
Implicit wait is preferable when one wants to set a specific time out for the presence of any web element in the DOM. This wait time is remains the same for the entire WebDriver instance for finding web elements. It could also be altered.
One could also use both Implicit and Explicit waits together where implicit wait provides a default timeout for finding presence of web elements but explicit wait will allow to be more specific for certain web elements where some conditions needs to be fulfilled for that element in order to be used for any operation.
It is not recommended to use
Thread.sleep() to implement webdriver wait. For eg. Thread.sleep(10000) will get the execution wait for 10 seconds even though the web element on which the action has to be performed is present earlier than the specified time. Similarly there can be web elements that can take more than the specified time to load. Hence, Thread.sleep() could be unreliable or may end up making your tests take more time to run than needed.