Beginner
Chapter 6 · 11 min read
Waits — Implicit, Explicit & Fluent
Handle dynamic page loading with implicit waits, explicit WebDriverWait with ExpectedConditions, and fluent waits with custom polling.
Handling Dynamic Content with Waits
Modern web apps load content dynamically — elements appear after AJAX calls, animations, or JavaScript execution. Without proper waits, tests fail with "element not found" errors even though the element exists — it just hasn't loaded yet.
Types of Waits
- Implicit Wait — Global timeout for all findElement calls. Simple but imprecise.
- Explicit Wait (WebDriverWait) — Wait for a specific condition on a specific element. The recommended approach.
- Fluent Wait — Explicit wait with custom polling interval and exception ignoring.
- Thread.sleep / time.sleep — Hard wait. Never use in production tests!
ExpectedConditions
Selenium provides built-in conditions: visibilityOfElementLocated, elementToBeClickable, presenceOfElementLocated, titleContains, alertIsPresent, and many more.
WaitsTest.java
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.*;
import org.testng.Assert;
import org.testng.annotations.*;
import java.time.Duration;
import java.util.function.Function;
public class WaitsTest {
WebDriver driver;
@BeforeMethod
public void setup() {
driver = new ChromeDriver();
}
@Test
public void testImplicitWait() {
// Global wait — applies to all findElement calls
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
driver.get("https://www.selenium.dev/selenium/web/web-form.html");
// Will wait up to 10s for element to appear
WebElement input = driver.findElement(By.name("my-text"));
Assert.assertTrue(input.isDisplayed());
}
@Test
public void testExplicitWait() {
driver.get("https://www.selenium.dev/selenium/web/web-form.html");
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
// Wait for element to be visible
WebElement input = wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.name("my-text")));
Assert.assertTrue(input.isDisplayed());
// Wait for element to be clickable
WebElement button = wait.until(
ExpectedConditions.elementToBeClickable(
By.cssSelector("button[type='submit']")));
Assert.assertTrue(button.isEnabled());
// Wait for title
boolean titleMatch = wait.until(
ExpectedConditions.titleContains("Web form"));
Assert.assertTrue(titleMatch);
}
@Test
public void testExplicitWait_MultiplConditions() {
driver.get("https://www.selenium.dev/selenium/web/web-form.html");
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
// Wait for presence (in DOM, may not be visible)
wait.until(ExpectedConditions.presenceOfElementLocated(
By.name("my-text")));
// Wait for URL to contain
wait.until(ExpectedConditions.urlContains("web-form"));
// Wait for number of elements
wait.until(ExpectedConditions.numberOfElementsToBeMoreThan(
By.tagName("input"), 3));
}
@Test
public void testFluentWait() {
driver.get("https://www.selenium.dev/selenium/web/web-form.html");
Wait<WebDriver> fluentWait = new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(15))
.pollingEvery(Duration.ofMillis(500))
.ignoring(NoSuchElementException.class)
.ignoring(StaleElementReferenceException.class);
WebElement element = fluentWait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver d) {
return d.findElement(By.name("my-text"));
}
});
Assert.assertTrue(element.isDisplayed());
}
@Test
public void testCustomWaitCondition() {
driver.get("https://www.selenium.dev/selenium/web/web-form.html");
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
// Custom condition: wait until element has a specific attribute value
wait.until(d -> {
WebElement el = d.findElement(By.name("my-text"));
String type = el.getAttribute("type");
return "text".equals(type);
});
}
@AfterMethod
public void teardown() { if (driver != null) driver.quit(); }
}
test_waits.py
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import (
NoSuchElementException, StaleElementReferenceException)
import pytest
@pytest.fixture
def driver():
d = webdriver.Chrome()
yield d
d.quit()
def test_implicit_wait(driver):
"""Global wait for all find_element calls"""
driver.implicitly_wait(10)
driver.get("https://www.selenium.dev/selenium/web/web-form.html")
input_el = driver.find_element(By.NAME, "my-text")
assert input_el.is_displayed()
def test_explicit_wait(driver):
"""Wait for specific conditions"""
driver.get("https://www.selenium.dev/selenium/web/web-form.html")
wait = WebDriverWait(driver, 10)
# Wait for visibility
input_el = wait.until(
EC.visibility_of_element_located((By.NAME, "my-text")))
assert input_el.is_displayed()
# Wait for clickable
button = wait.until(
EC.element_to_be_clickable(
(By.CSS_SELECTOR, "button[type='submit']")))
assert button.is_enabled()
# Wait for title
assert wait.until(EC.title_contains("Web form"))
def test_explicit_wait_multiple(driver):
"""Multiple wait conditions"""
driver.get("https://www.selenium.dev/selenium/web/web-form.html")
wait = WebDriverWait(driver, 10)
# Presence in DOM
wait.until(EC.presence_of_element_located((By.NAME, "my-text")))
# URL condition
wait.until(EC.url_contains("web-form"))
# Number of elements
inputs = wait.until(
EC.presence_of_all_elements_located((By.TAG_NAME, "input")))
assert len(inputs) > 3
def test_fluent_wait(driver):
"""Custom polling and exception ignoring"""
driver.get("https://www.selenium.dev/selenium/web/web-form.html")
wait = WebDriverWait(
driver, timeout=15, poll_frequency=0.5,
ignored_exceptions=[
NoSuchElementException,
StaleElementReferenceException
])
element = wait.until(
EC.visibility_of_element_located((By.NAME, "my-text")))
assert element.is_displayed()
def test_custom_wait_condition(driver):
"""Wait with custom lambda condition"""
driver.get("https://www.selenium.dev/selenium/web/web-form.html")
wait = WebDriverWait(driver, 10)
# Custom: wait until element has specific attribute
wait.until(lambda d:
d.find_element(By.NAME, "my-text").get_attribute("type") == "text")
Selenium
Beginner
Waits — Implicit, Explicit & Fluent
Written by PV
© 2026 All Rights Reserved