A typical website is usually made up of a backend that calls dynamic data from a database. As this data is being called through an asynchronous process, it takes a while for it to be ready, hence increasing the time it takes for a website to load completely. Selenium is a great tool for automated testing of websites, it speeds up the testing process and produces results quickly. However, as a result of the slow asynchronous process explained earlier, there is a need to make Selenium wait.
Selenium wait ensures that elements of the applications load completely so that test actions can be performed on them. This usually involves pausing the execution of the code for a while until the data is fully loaded.
Types of Selenium Waits
There are three main implementations of Waits in Selenium:
- Through Implicit Wait
- Through Explicit Wait
- Through Fluent Wait
1. Implicit Wait
Implicit wait is pretty straightforward as it simply tells the WebDriver component of Selenium to wait for a particular amount of time, say 10 seconds. This is similar to a timeout method in Javascript. The time specified for waiting should typically be an estimate of how long it takes the page to load. Hence, Implicit wait cannot work effectively unless the tester knows how long it takes for the page to load.
Let’s say a website under test takes ten seconds to load a page until a particular element shows up. In that case, you can set implicit wait for 10 seconds. The test will pause, and once the time passes, WebDriver will continue to run the script as planned.
A simple implementation of Implicit wait can be performed with the following code:
WebDriver driver => new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get("https://www-stage.testup.io"); WebElement myDynamicElement = driver.findElement(By.id("myDynamicElement"));
It is important to note that the Implicit Wait function will only work as long as the current browser is open. That means that the time taken for loading components will reoccur upon page reload.
2. Explicit Wait
The explicit wait is a little bit more complex. It works in the form of an “if” conditional statement such that Selenium does not run unless certain conditions are met. A great use case for explicit wait is when you want a certain action like a popup to run, or you would like the user to navigate to a certain part of the page before running Selenium. Implicit wait cannot be used in this case because the time taken for the condition to be fulfilled may vary with the user, hence the need to use Explicit wait.
An example code of an implementation of Explicit wait can be found below:
from selenium.webdriver.common.by import By.ID from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC driver = webdriver.Firefox() driver.get("http://testup.io") #This is Testup's website URL try: elem = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, "Element_to_be_found")) #This is a dummy element ) finally: driver.quit()
3. Fluent Wait
The fluent wait is similar to explicit wait, however aside from defining a condition after which Selenium starts to run, you can also define the frequency with which you want to check for a specified condition. The best use case for this type of wait is for websites that have elements that take much longer to load than others. Fluent wait enables us to keep checking for the element at regular intervals and enable Selenium to run once the condition has been met.
An example code of an implementation of Fluent wait can be found below:
//Declare and initialise a fluent wait FluentWait wait = new FluentWait(driver); //Specify the timout of the wait wait.withTimeout(5000, TimeUnit.MILLISECONDS); //Specify polling time wait.pollingEvery(250, TimeUnit.MILLISECONDS); //Specify what exceptions to ignore wait.ignoring(NoSuchElementException.class) //This is how we specify the condition to wait on. wait.until(ExpectedConditions.alertIsPresent());
Fluent waits are also called smart waits. This is because they do not wait for the maximum time specified in .withTimeout(5000, TimeUnit.MILLISECONDS) before they run, rather they wait for the time till the condition specified in .until(YourCondition) method becomes true.