Hello Folks,
In this post we are going to see something interesting concepts about waits in Selenium WebDriver.
Generally Selenium professionals know that there are three types of waits in Selenium WebDriver:-
- Implicit Wait
- Explicit Wait
- Fluent Wait
In fact there are only two types of waits:-
- Implicit wait
- Explicit wait
We can implement Explicit wait in two ways:-
- FluentWait
- WebDriverWait
Selenium official document talks the same. They have not mentioned Fluent wait separately .
Brief about both waits as per Selenium Documentation:-
Implicit Wait:-
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. The default setting is 0
. Once set, the implicit wait is set for the life of the WebDriver object instance.
WebDriver driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get("some URL"); WebElement myDynamicElement = driver.findElement(By.id("someID"));
Explicit Wait:-
An explicit wait is code you define to wait for a certain condition to occur before proceeding further in the code. WebDriverWait
in combination with ExpectedCondition
(Note- ExpectedCondition
is an interface while ExpectedConditions is a class)
is one way to do this. That condition can be implemented either using ExpectedConditions methods or override apply() methods and write your own condition.
Example Code:-
WebDriver driver = new FirefoxDriver(); driver.get("some url"); WebDriverWait wait = new WebDriverWait(driver, 10); // Using readymade wat conditions wait.until(ExpectedConditions.presenceOfElementLocated(By.id("someID"))); // Using own way of waiting boolean foo = wait.until(new Function < WebDriver, Boolean > () { public boolean apply(WebDriver driver) { return driver.findElement(By.id("foo")).isDisplayed(); } });
FluentWait is a class in Selenium WebDriver which implements Wait interface and WebDriverWait is direct known subclass to it. It means all are in same hierarchy. Fluent wait is an implementation of the Wait interface that may have its timeout and polling interval configured on the fly. WebDriverWait is a specialization of FluentWait that uses WebDriver instances. To be more clear, FluentWait is a generic class (public class FluentWait<T> implements Wait<T>) while WebDriverWait is specialization of FluentWait (public class WebDriverWait extends FluentWait<WebDriver>). WebDriverWait is designed to work for WebDriver exclusively.
So if we implement Explicit wait using either FluentWait or WebDriverWait, we can configure with desired polling interval and ignore one or more exceptions. Refer below examples:-
Explicit Wait as FluentWait:-
Waitwait = new FluentWait (driver).withTimeout(Duration.ofSeconds(30)) .pollingEvery(Duration.ofSeconds(5)) .ignoring(NoSuchElementException.class); WebElement foo = wait.until(new Function () { public WebElement apply(WebDriver driver) { return driver.findElement(By.id("foo")); } });
Explicit wait as WebDriverWait:-
WebDriver driver = new FirefoxDriver(); driver.get("Some URL"); WebElement myDynamicElement = (new WebDriverWait(driver, 10)) .until(ExpectedConditions.presenceOfElementLocated(By.id("someID")));
We can use either readymade methods available in ExpectedConditions class or we can create our own wait conditions by overriding apply() method of Function interface in until() method. Maximum wait conditions methods of ExpectedConditions class overrides apply() method.
FluentWait class has different methods to configure wait instance. For example:- withTimeout(), pollingEvery(), ignoring() etc. This class is generic so all methods as well.
In WebDriverWait class which is specialization of FluentWait with WebDriver and provides a way to configure wait instance easily. For example:-
When we write below line:-
WebDriverWait wait = new WebDriverWait(driver, 30);
It calls constructor of FluentWait<WebDriver> and set default polling interval time (DEFAULT_SLEEP_TIMEOUT) which is 500 ms and ignore instances of NotFoundException that are encountered (thrown) by default in the ‘until’ condition. You can change default polling interval and ignoring exceptions as well as shown below:-
WebDriverWait wait1 = new WebDriverWait(driver,30);
wait1.pollingEvery(Duration.ofSeconds(2));
wait1.ignoring(ElementClickInterceptedException.class);
You can also user overloaded WebDriverWait constructor to set interval time as below:-
WebDriverWait wait1= new WebDriverWait(driver, 30, 5000);
Above statement works in the same way except instead of setting default polling interval time as 500 ms. It will set polling interval time as 5 seconds.
So to summarize, WebDriverWait is a FluentWait (Inheritance) and FluentWait is Explicit wait in Selenium WebDriver.
It is also not correct that in WebDriverWait we can use only ExpectedConditions class wait methods and in FluentWait , we can use only apply() method. We can set custom polling interval and ignore exceptions in both implementation i.e. WebDriverWait & FluentWait.
Explicit Wait as WebDriverWait with ExpectedConditions and apply() method:-
package WaitExamples; import java.time.Duration; import java.util.Date; import java.util.function.Function; import org.openqa.selenium.By; import org.openqa.selenium.ElementNotInteractableException; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; import io.github.bonigarcia.wdm.WebDriverManager; public class ExplicitWaitAsWebDriverWaitExample { public static void main(String[] args) throws InterruptedException { WebDriverManager.chromedriver().setup(); WebDriver driver = new ChromeDriver(); driver.manage().window().maximize(); driver.get("http://www.itgeared.com/demo/1502-javascript_countdown.html"); // Configuring a WebDriverWait with polling interval and ignoring exception WebDriverWait wait = new WebDriverWait(driver,30); wait.pollingEvery(Duration.ofMillis(5000)); wait.ignoring(ElementNotInteractableException.class); // Using ready made wait conditions of ExpectedCOnditions class wait.until(ExpectedConditions.elementToBeClickable(driver.findElement(By.id("myBtn")))); System.out.println("Element is ready to be clicked."); // Refreshing the page driver.get("http://www.itgeared.com/demo/1502-javascript_countdown.html"); // Overriding apply() method to created our own wait condition for WebDriverWait boolean isClickable = wait.until(new Function() { public Boolean apply(WebDriver driver) { System.out.println("Interval time : "+new Date()); String text= driver.findElement(By.id("myBtn")).getText(); if(text.equals("Click Me!")) return true; return false; } }); if(isClickable) System.out.println("Element is ready to be clicked."); driver.quit(); } }
Output:-
Element is ready to be clicked.
Interval time : Thu Jun 20 06:51:08 IST 2019
Interval time : Thu Jun 20 06:51:13 IST 2019
Interval time : Thu Jun 20 06:51:18 IST 2019
Interval time : Thu Jun 20 06:51:23 IST 2019
Element is ready to be clicked.
You can see how we set custom polling interval in WebDriverWait.
Explicit Wait as WebDriverWait with ExpectedConditions and apply() method:-
package WaitExamples; import java.time.Duration; import java.util.Date; import java.util.NoSuchElementException; import java.util.function.Function; import org.openqa.selenium.By; import org.openqa.selenium.ElementNotInteractableException; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.FluentWait; import org.openqa.selenium.support.ui.Wait; import org.openqa.selenium.support.ui.WebDriverWait; import io.github.bonigarcia.wdm.WebDriverManager; public class ExplicitWaitAsFluentWaitExample { public static void main(String[] args) throws InterruptedException { WebDriverManager.chromedriver().setup(); WebDriver driver = new ChromeDriver(); driver.manage().window().maximize(); driver.get("http://www.itgeared.com/demo/1502-javascript_countdown.html"); // Configuring a FluentWait with polling interval and ignoring exception Waitwait = new FluentWait (driver) .withTimeout(Duration.ofMillis(30000)) .pollingEvery(Duration.ofMillis(5000)) .ignoring(NoSuchElementException.class); // Using ready made wait conditions of ExpectedCOnditions class wait.until(ExpectedConditions.elementToBeClickable(driver.findElement(By.id("myBtn")))); System.out.println("Element is ready to be clicked."); // Refreshing the page driver.get("http://www.itgeared.com/demo/1502-javascript_countdown.html"); // Overriding apply() method to created our own wait condition for WebDriverWait boolean isClickable = wait.until(new Function () { public Boolean apply(WebDriver driver) { System.out.println("Interval time : "+new Date()); String text= driver.findElement(By.id("myBtn")).getText(); if(text.equals("Click Me!")) return true; return false; } }); if(isClickable) System.out.println("Element is ready to be clicked."); driver.quit(); } }
#ThanksForReading
Nice article, though one question. Why was fluent wait class created when WebDriverWait has everything that can be configured? i mean what is the purpose of having fluent wait class in this hierarchy?
sir These are my questions
1 is default polling interval time is 500 or 250 ms?
2 What is the exact difference between Fluent wait and Explicit wait (as WebDriverWait)? interview purpose what we should say?
Please guide me.
I am setting polling interval and ignoring NoSuchElementException. I passed wrong locator so that it can encounter NoSuchElementException and can be ignored. Below code shows that no such element exception is getting ignored in case of ExpectedConditions also.
package seleniumtopics1;
import java.io.File;
import java.time.Duration;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;
public class MixingWaits2 {
public static void main(String[] args) {
// WebDriverManager.chromedriver().setup();
System.setProperty(“webdriver.chrome.driver”,
System.getProperty(“user.dir”) + File.separator + “browser_exe” + File.separator + “chromedriver.exe”);
WebDriver driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get(“https://www.google.com/”);
Wait wait = new FluentWait(driver).withTimeout(Duration.ofSeconds(15))
.pollingEvery(Duration.ofSeconds(1)).ignoring(NoSuchElementException.class);
System.out.println(“Wait starts:” + new Date());
try {
wait.until(ExpectedConditions.presenceOfElementLocated(By.id(“wrongElement”)));
// wait.until(ExpectedConditions.elementToBeClickable(driver.findElement(By.id(“wrong
// element”))));
} catch (Exception e) {
System.out.println(“Unable to locate element.” + e.getMessage());
}
System.out.println(“Wait ends:” + new Date());
driver.close();
driver.quit();
}
}
Output –
Starting ChromeDriver 2.36.540470 (e522d04694c7ebea4ba8821272dbef4f9b818c91) on port 38289
Only local connections are allowed.
May 04, 2019 1:59:34 PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: OSS
Wait starts:Sat May 04 13:59:37 IST 2019
Unable to locate element.Expected condition failed: waiting for presence of element located by: By.id: wrongElement (tried for 15 second(s) with 1000 milliseconds interval)
Wait ends:Sat May 04 13:59:59 IST 2019
You have mixed implicit and explicit wait both.
Yes Amod, I did that deliberately to check if nosuchelement exception is getting ignored or not. anyways after commenting the implicit wait line of code. then also webdriver is waiting till explicit wait timeout.
below is the output from console.
Starting ChromeDriver 2.36.540470 (e522d04694c7ebea4ba8821272dbef4f9b818c91) on port 30133
Only local connections are allowed.
May 04, 2019 6:20:27 PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: OSS
Wait starts:Sat May 04 18:20:31 IST 2019
Unable to locate element.Expected condition failed: waiting for presence of element located by: By.id: wrongElement (tried for 15 second(s) with 1000 milliseconds interval)
Wait ends:Sat May 04 18:20:47 IST 2019