Waiting is a crucial part of writing reliable and robust Selenium tests. Whether you’re dealing with dynamic content, asynchronous loading, or complex UI interactions, understanding and mastering different wait strategies is key to ensure that consistent result out of the tests.
In this blog, we’ll dive deep into various waiting techniques like Implicit, Explicit, Fluent wait techniques in Selenium 4. This blog will serve as a one-stop solution for all your waiting needs in Selenium Webdriver 4. Additionally, you can learn about how to wait for API response in Selenium WebDriver.
Understanding the Basics: Implicit, Explicit, and Fluent Wait
Waits | Definition | When to use? |
---|---|---|
Implicit Wait | Sets a default wait time for the entire WebDriver instance, affecting all element searches. It’s a quick and easy way to handle elements that may not be immediately available but isn’t the most efficient for complex scenarios. | This should be used irrespective of the nature of the page. As this adds an implicit wait for every interaction with the page so in ideal world Wait Timeout of few seconds must be added a implicit wait condition. |
Explicit Wait | Allows you to wait for specific conditions to be met before proceeding. It’s more precise than implicit wait, but still limited in flexibility. | This should be used when you would like to wait for a condition to be true. For example, waiting for button to be visible on the page before clicking on it. |
Fluent Wait | A more advanced form of WebDriverWait , FluentWait offers the ability to define custom polling intervals, specify exceptions to ignore, and create complex conditions. It’s the most powerful and flexible wait option in Selenium. | This is an advanced version of explicit wait, offering greater precision. It can be used in any dynamic page where you would like to have an intelligent wait for condition to be true. Unlike Explicit wait, this wait comes with a polling strategy which makes it more precise and intelligent. |
Use Explicit Wait for common conditions like waiting for elements to be clickable, visible, or present.
Use Fluent Wait when you need more advanced control over the wait behavior, such as custom polling intervals, handling exceptions, or combining multiple conditions.
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(30));
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("submitButton")));
Fluent Wait Examples in Selenium WebDriver 4
Selenium official website talks about waiting strategy as one of the most crucial aspect of browser automation. It is important to learn about different fluent wait implementations in Selenium WebDriver 4.
Here are various examples of Fluent Wait in WebDriver to utilise them effectively.
Fluent Wait Example handling NoSuchElementException
Code Explanation
This code snippet is designed to wait for an element (loginBtn
) to become both visible and clickable. It uses FluentWait
to handle cases where the element might not be immediately available due to dynamic content loading or delayed rendering. By ignoring NoSuchElementException
, the code avoids premature test failures, ensuring the element is interacted with only when it’s fully ready.
When to Use This?
Use this wait condition, when you expect exception NoSuchElementException
on the page if you try to interact with the element before its rendering.
Wait<WebDriver> wait =
new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(10))
.pollingEvery(Duration.ofMillis(500))
.ignoring(NoSuchElementException.class);
wait.until(
d -> {
WebElement dynamicElement = driver.findElement(By.id("loginBtn"));
if (dynamicElement.isDisplayed() && dynamicElement.isEnabled()) {
dynamicElement.click();
return true;
}
return false;
});
Fluent Wait Example handling
NoSuchElementException & StaleElementReferenceException
Code Explanation
This code snippet is designed to wait for an element (loginBtn
) to become both visible and clickable. It uses FluentWait
to handle cases where the element might not be immediately available due to dynamic content loading or delayed rendering. This code snippet handles both NoSuchElementException
and StaleElementReferenceException
exceptions.
When to Use This?
Use this wait condition, when you expect any of NoSuchElementException
or StaleElementReferenceException
on the page if you try to interact with the element before its rendering.
Wait<WebDriver> wait =
new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(10))
.pollingEvery(Duration.ofMillis(500))
.ignoring(NoSuchElementException.class)
.ignoring(StaleElementReferenceException.class);
wait.until(
d -> {
WebElement dynamicElement = driver.findElement(By.id("loginBtn"));
if (dynamicElement.isDisplayed() && dynamicElement.isEnabled()) {
dynamicElement.click();
return true;
}
return false;
});
Fluent Wait in Selenium 4 for Text Change of an Element
Code Explanation
This code snippet is designed to wait for an element (statusMessage
) to have text as Complete
. It uses FluentWait
to handle cases where the element might not be immediately available due to dynamic content loading or delayed rendering or contains a different text. This code snippet handles both NoSuchElementException
and StaleElementReferenceException
exceptions.
When to Use This?
Use this wait condition, when you expect any of NoSuchElementException
or StaleElementReferenceException
on the page in addition with a specific text value for the element. This would be useful when a saved an entity and waiting for text confirmation to turn Complete
from Pending
.
Wait<WebDriver> wait =
new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(10))
.pollingEvery(Duration.ofMillis(300))
.ignoring(NoSuchElementException.class)
.ignoring(StaleElementReferenceException.class);
wait.until(
d -> {
WebElement statusMessage = driver.findElement(By.id("statusMessage"));
String text = statusMessage.getText();
// Wait until the text changes to "Complete"
if (text.equals("Complete")) {
return true;
}
// Print the current status and continue waiting
System.out.println("Current status: " + text);
return false;
});
Fluent Wait Example for Dropdown having a value
When to Use This?
This FluentWait example is particularly useful when dealing with dropdowns whose options are loaded dynamically or when the options might not be immediately available. By waiting for the specific value to appear before interacting with the dropdown, you ensure that your test is both reliable and resistant to timing issues.
Wait<WebDriver> wait =
new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(10))
.pollingEvery(Duration.ofMillis(500))
.ignoring(NoSuchElementException.class);
wait.until(
d -> {
WebElement dropdown = driver.findElement(By.id("myDropdown"));
Select select = new Select(dropdown);
List<WebElement> options = select.getOptions();
for (WebElement option : options) {
if (option.getText().equals("Desired Value")) {
select.selectByVisibleText("Desired Value");
return true;
}
}
return false;
});
Fluent Wait Example for Alert to Disappear
When to Use This?
This FluentWait example is particularly useful when you would like to proceed after alert disappears from page.
Wait<WebDriver> wait =
new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(10))
.pollingEvery(Duration.ofMillis(500))
.ignoring(NoAlertPresentException.class);
wait.until(
d -> {
try {
d.switchTo().alert().accept();
return false; // Alert is still present
} catch (NoAlertPresentException e) {
return true; // Alert has disappeared
}
});
Fluent Wait Example when multiple conditions are chained
When to Use This?
You need to interact with a UI element that only becomes clickable after:
- A button within the modal becomes clickable.
- A modal dialog appears.
- A loading spinner inside the modal disappears.
Wait<WebDriver> wait =
new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(20))
.pollingEvery(Duration.ofMillis(500))
.ignoring(NoSuchElementException.class);
wait.until(driver -> {
WebElement modal = driver.findElement(By.id("modalWindow"));
if (!modal.isDisplayed()) return false;
WebElement spinner = modal.findElement(By.id("loadingSpinner"));
if (spinner.isDisplayed()) return false;
WebElement button = modal.findElement(By.id("confirmButton"));
if (!button.isEnabled()) return false;
button.click();
return true;
});
How different wait strategies affect test execution time?
The test execution time is directly impacted by the chosen wait strategy. For example, if a codebase with over 100 test scenarios has a 10-second sleep timeout for each scenario, the total execution time will be delayed by 1,000 seconds — that’s roughly 16 minutes.
The impact of improper wait times is more complicated than just adding up the timeouts. If a sleep timeout is part of a core method, like loadingHomePage
, and the home page is loaded multiple times across 100 tests, the delay can become exponential.
If a test suite takes an extra hour to provide feedback, it wastes about 13% of your working hours. This is why having an appropriate wait condition is crucial for a faster and more efficient feedback process.
Common Pitfalls
One common pitfall is guessing the wait times rather than experimenting with different values.
People often use a fixed constant value with explicit wait conditions instead of using fluent waits. Using fixed timeouts can make the waiting longer than necessary.
Additionally, waiting for UI elements is not the only way to ensure that a page is ready for interaction. Tools like Cypress and Playwright offer solutions such as waiting for API responses, which can provide a more efficient way to ensure readiness. If you are using Selenium WebDriver, you can also use network response wait condition.
Comparisons with Other Tools
Cypress provides automatic waiting for elements to appear and actions to complete, reducing the need for manual waits. Playwright, similarly, supports built-in waits for network responses and element states, simplifying synchronisation. It is high time for Selenium Developers to consider to have a robust waiting mechanism in the tool, either as a plugin or as a library methods.
Thank you for reading this post, don't forget to subscribe!