Blog detail

Selenium Devs Need to Use Fluent Waits: Explained Why with Examples

Date: 13-03-2023

Selenium is a popular open-source automation testing tool that is widely used for web application testing. One of the critical challenges that Selenium testers face is to synchronize their test scripts with the web application’s dynamic behavior. 

This is because web applications can have various dynamic components like AJAX, JavaScript, and jQuery, which can delay or modify the web elements’ visibility, making them difficult to locate and interact with.

To overcome this challenge, Selenium provides a feature called “Fluent Waits.” In this blog, we will discuss what fluent waits are, how they work, and how to use them effectively in your Selenium test scripts.

Waits in Selenium

Different types of Selenium waits and steps involved to use implicit, explicit and Fluent Waits. The important thing to note here is that all types of waits in selenium are dynamic. This means if the element is identified before the time out rest of the remaining seconds will be ignored.

Why do we need Waits in Selenium?

Whenever we are working with any web applications the elements or the objects on the web pages may not all load at the same time. Most web applications are developed using AJAX and JavaScript.

when a page is loaded by the browser the elements which we want to interact with may load at different time intervals.

Not only does it make this difficult to identify the elements but also if the element is not located it will throw an element not visible exception.

With the help of waits, we can enable the script to wait for some time before throwing the exception.

Fluent Wait

FluentWait instance defines the maximum amount of time to wait for a condition, as well as the frequency with which to check the condition.

What Are Fluent Waits?

Fluent waits are a type of explicit wait in Selenium that allows you to wait for a certain condition to occur before performing the next action. 

The primary difference between fluent waits and regular explicit waits is that fluent waits can define the maximum amount of time to wait for the condition to occur and the frequency of checking for the condition.

In simpler terms, fluent waits allow you to set up a wait condition and check for it at regular intervals until the condition is met or the maximum wait time is reached.

Key Points About Fluent Waits:

  • It will wait till the specified time before throwing an exception. In such scenarios, the fluent wait is the ideal wait to use as this will try to find the element at different frequencies until it finds it or the final timer runs out.
  • This Wait is quite similar to explicit Wait. It is similar in terms of management and functioning. In this Wait, you can perform wait for action for an element only when you are unaware of the time it might take to be clickable or visible.
  • Referring to Fluent waits as smart waits. They are called smart primarily because they don’t wait for the max time out, specified in the .withTimeout(5000, TimeUnit.MILLISECONDS). Instead, it waits for the time till the condition specified in the .until(YourCondition) method becomes true.

How do Fluent Waits work?

The FluentWait class in Selenium provides several methods to configure the wait condition. These methods include.

withTimeout(): 

This method sets the maximum amount of time to wait for the condition to occur. If the condition is not met within this time frame, the wait is terminated, and an exception is thrown.

pollingEvery(): 

This method sets the frequency of checking for the condition. If the condition is not met, the script will wait for the specified time before checking again.

ignoring(): 

This method allows you to ignore certain exceptions during the wait. For example, you can ignore the NoSuchElementException when locating a web element.

Once the wait condition is set up, you can call the until() method, passing in a lambda expression that defines the condition to wait for. The until() method will check for the condition at the specified frequency until it is met or the maximum wait time is reached.

Why Use Fluent Wait

Because of the performance of the test script, to avoid time out and unnecessary test script failure.

If the element to be present does not appear after a static time and keeps changing, then you will never know an estimated time needed for the sleep function. In case it takes more time than the defined time, the script shall throw an error. This is why, if you are dealing with dynamic elements using Selenium waits then it is wise to not use Thread. sleep().

A Practical Fluent Wait Situation

I want to grab some specific UI elements that are load run or when we select the first element then only the other one will be loaded and don’t want to use wait Thread. Sleep (1000); hard coded.

Syntax How to Use Fluent Wait:

  Wait wait = new FluentWait(WebDriver reference)  .withTimeout(timeout, SECONDS) .pollingEvery(timeout, SECONDS) .ignoring(Exception.class); WebElement foo=wait.until(new Function<WebDriver, WebElement>() { public WebElement  applyy(WebDriver driver) { return driver.findElement(By.id(“foo”)); } }); 
Our Test script : 
import java.util.concurrent.TimeUnit;  import org.openqa.selenium.By;  import org.openqa.selenium.NoSuchElementException;  import org.openqa.selenium.WebDriver;  import org.openqa.selenium.WebElement;  import org.openqa.selenium.chrome.ChromeDriver;  import org.openqa.selenium.support.ui.FluentWait;  import org.openqa.selenium.support.ui.Wait;  import com.google.common.base.Function;    public class FluentWaitExp { public static void main(String[] args) throws InterruptedException { System.setProperty(“webdriver.chrome.driver”, “E:\\Selenium\\chromedriver_win32\\chromedriver.exe”);    WebDriver driver = new ChromeDriver(); driver.get(“https://www.google.com/”); driver.manage().window().maximize(); driver.findElement(By.name(“q”)).sendKeys(“Selenium”);    Thread.sleep(2000); driver.findElement(By.name(“btnK”)).click(); @SuppressWarnings({ “deprecation” }) Wait<WebDriver> wait = new FluentWait<WebDriver>(driver).withTimeout(30, TimeUnit.SECONDS) .pollingEvery(2,TimeUnit.SECONDS).ignoring(NoSuchElementException.class);   WebElement element = (WebElement) wait.until(new Function<WebDriver, WebElement>() { @Override public WebElement apply(WebDriver arg0) { WebElement linkelement = driver.findElement(By.partialLinkText(“Selenium – Health Professional”));    if (linkelement.isEnabled()) { System.out.println(“Element is Found”); } return linkelement; } }); element.click(); } }

Syntax Example 1:

Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
  .withTimeout(30, TimeUnit.SECONDS)
  .pollingEvery(5, TimeUnit.SECONDS)
  .ignoring(NoSuchElementException.class);

This is how we can implement and use this syntax practically:

package demo;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;

import com.google.common.base.Function;

import io.github.bonigarcia.wdm.WebDriverManager;

public class FluentWaitDemo {

              public static void main(String[] args) {
                             try {
                                           test();
                                          
                             } catch (InterruptedException e) {                                        
                                           e.printStackTrace();

                             }
              }

              public static void test() throws InterruptedException {

                             WebDriverManager.chromedriver().setup();
                             WebDriver driver = new ChromeDriver();
                             driver.manage().window().maximize();
                            
                             driver.get(“https://www.google.com”);
                             driver.findElement(By.name(“q”)).sendKeys(“Selenium”);
                            driver.findElement(By.name(“btnK”)).sendKeys(Keys.RETURN);

                             //driver.findElement(By.linkText(“Selenium Tutorial – javatpoint”)).click();

                             // Waiting 30 seconds for an element to be present on the page, checking
                             // for its presence once every 5 seconds.
                             Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
                             .withTimeout(30, TimeUnit.SECONDS)
                             .pollingEvery(5, TimeUnit.SECONDS)
                             .ignoring(NoSuchElementException.class);

                             WebElement element  = wait.until(new Function<WebDriver, WebElement>() {
                                          
                                           public WebElement apply(WebDriver driver) {
                                                          WebElement linkElement =  driver.findElement(By.partialLinkText(“Selenium Tutorial – javatpoint”));

                                                          if (linkElement.isEnabled()) {
                                                                        System.out.println(“Element Found”);

                                                          }
                                                          return linkElement;
                                           }
                             });

                             element.click();
                             Thread.sleep(3000);

                             driver.close();
                             driver.quit();

              }
}

About This Example:

In this example, a google search scenario has been implemented where it locates a specific URL in search results. It won’t appear on the first page itself, so we have to manually navigate to the second page.

Here the timeout has been set as 30 seconds and the polling frequency as 5 seconds. This means first it will search for the element for 20 seconds. Then if not found driver will wait for 5 seconds and again search for the element for 20 seconds.

This will work in a loop until it finds the element. The loop will execute after every 5 seconds. So we have enough time to navigate to the page the URL exists. Then the web driver will identify the element and will act accordingly.

The fluent wait will be applicable in a scenario where let’s say we navigate to a site there are different kinds of ads popping out and we have to manually close them. So in a situation like this Fluent wait will be very useful.

Syntax Example 2:

Here is an example of how to use fluent waits in Selenium:

scss
Copy code
// create a new instance of FluentWait
FluentWait wait = new FluentWait(driver);

// set the maximum wait time to 30 seconds
wait.withTimeout(Duration.ofSeconds(30));

// set the polling frequency to 5 seconds
wait.pollingEvery(Duration.ofSeconds(5));

// ignore the NoSuchElementException during the wait
wait.ignoring(NoSuchElementException.class);

// define the wait condition using a lambda expression
WebElement element = wait.until(driver -> driver.findElement(By.id(“myElement”)));

// perform an action on the element
element.click();

In this example, we create a new instance of FluentWait and configure the wait condition to wait for an element with the ID “myElement” to be visible. We set the maximum wait time to 30 seconds and the polling frequency to 5 seconds. We also ignore the NoSuchElementException exception during the wait.

Conclusion

In conclusion, fluent waits are an essential feature of Selenium that allows you to synchronize your test scripts with the dynamic behavior of web applications.

By using fluent waits, you can wait for a specific condition to occur before performing the next action, ensuring that your test script runs smoothly and accurately.

When using fluent waits, it is essential to configure the wait condition correctly, setting the maximum wait time, and polling frequency, and ignoring any exceptions that may occur during the wait.

With these best practices in mind, you can leverage the power of fluent waits in your Selenium test scripts and improve the reliability and accuracy of your test automation.

Tags associated Fluent Waits,Selenium automation testing,Selenium Devs,Selenium Framework,Selenium Testing,Selenium testing services