Wait Strategies
Wait Strategies Understand implicit, explicit, fluent, and expected condition waits in Selenium and Appium to write reliable, non-flaky test automation
Testing Quest #31 Intermediate

Wait Strategies

Understand implicit, explicit, fluent, and expected condition waits in Selenium and Appium to write reliable, non-flaky test automation

testingseleniumappiumwaitsautomation
Download as:

Why Waits Matter

Web and mobile applications load content dynamically โ€” elements appear after API calls, animations, or JavaScript execution. If your test tries to interact with an element before it exists, it fails. Wait strategies tell your test how and how long to wait for conditions to be met before proceeding.

The goal is to wait just long enough โ€” not too short (flaky tests) and not too long (slow tests). Never use a fixed sleep to solve timing issues.

Prerequisites

Implicit Wait

An implicit wait sets a global timeout for all find_element calls in the session. If the element is not immediately present, WebDriver polls the DOM repeatedly until the timeout expires:

driver.implicitly_wait(10)

# Every find_element call now waits up to 10 seconds
element = driver.find_element(By.ID, "my-element")

WebDriver polls the DOM for a certain duration when trying to find any element. This applies to every element lookup for the entire session.

Why implicit waits are not recommended:

  • You cannot control the wait per element โ€” the same timeout applies everywhere
  • You cannot wait for specific conditions (e.g., clickable, visible)
  • If an element is genuinely missing, every lookup silently waits the full timeout before failing, making test runs slow

Explicit Wait

An explicit wait pauses execution until a specific condition is met, with a timeout. Unlike implicit waits, this applies only to the single check where you use it:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# Wait up to 3 seconds for a specific element
element = WebDriverWait(driver, timeout=3).until(
    lambda d: d.find_element(By.TAG_NAME, "p")
)

The lambda (or any callable) is evaluated repeatedly. As long as it returns a falsy value, the wait keeps trying. Once it returns a truthy value, execution continues.

You can use any custom function โ€” not just built-in conditions:

# Wait until a custom condition is met
def page_has_loaded(driver):
    return driver.execute_script("return document.readyState") == "complete"

WebDriverWait(driver, timeout=10).until(page_has_loaded)

Expected Conditions

Expected conditions are built-in convenience functions for common wait scenarios. They are used with explicit waits:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

# Wait for an element to be clickable
wait = WebDriverWait(driver, timeout=10)
button = wait.until(EC.element_to_be_clickable((By.ID, "submit-btn")))
button.click()

Common expected conditions:

ConditionUse when
presence_of_element_locatedElement exists in the DOM (may not be visible)
visibility_of_element_locatedElement is visible on the page
element_to_be_clickableElement is visible and enabled
element_to_be_selectedCheckbox or radio button is selected
text_to_be_present_in_elementElement contains specific text
invisibility_of_element_locatedElement has disappeared (e.g., a loading spinner)
alert_is_presentA browser alert dialog has appeared

Fluent Wait

A fluent wait is an explicit wait with fine-grained control over polling behavior and exception handling:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import (
    ElementNotVisibleException,
    ElementNotSelectableException,
)

wait = WebDriverWait(
    driver,
    timeout=10,
    poll_frequency=1,
    ignored_exceptions=[
        ElementNotVisibleException,
        ElementNotSelectableException,
    ],
)
element = wait.until(EC.element_to_be_clickable((By.XPATH, "//div")))
ParameterWhat it controls
timeoutMaximum time to wait before raising a TimeoutException
poll_frequencyHow often (in seconds) to re-check the condition
ignored_exceptionsExceptions to suppress while polling (instead of failing immediately)

A fluent wait is the same as an explicit wait โ€” it just exposes additional configuration. Use it when you need to control poll intervals or ignore specific transient exceptions.

Never Use time.sleep()

A hard sleep pauses execution for a fixed duration with no exit criteria. It cannot finish early even if the condition is already met:

import time

# Bad โ€” always waits 5 seconds, even if the element appears instantly
time.sleep(5)
element = driver.find_element(By.ID, "my-element")

# Good โ€” waits up to 5 seconds, returns as soon as the element appears
element = WebDriverWait(driver, timeout=5).until(
    EC.presence_of_element_located((By.ID, "my-element"))
)

If you find yourself reaching for time.sleep(), refactor the test to use an explicit wait with the right condition instead.

Do Not Mix Implicit and Explicit Waits

From the official Selenium documentation:

Warning: Do not mix implicit and explicit waits. Doing so can cause unpredictable wait times. For example, setting an implicit wait of 10 seconds and an explicit wait of 15 seconds could cause a timeout to occur after 20 seconds.

The two wait mechanisms interact in unexpected ways because they operate at different layers. Stick to explicit waits only for predictable behavior.

Summary

Wait TypeScopeRecommended
ImplicitGlobal โ€” all find_element callsNo
ExplicitSingle conditionYes
Expected ConditionsSingle condition (built-in helpers)Yes
FluentSingle condition (custom polling)Yes
time.sleep()Fixed duration, no exit criteriaNever

Best practice: Use explicit waits with expected conditions. Use fluent waits when you need custom polling. Avoid implicit waits and hard sleeps.

Resources

๐Ÿ”—
Selenium Waits Documentation selenium.dev

Official Selenium guide to implicit, explicit, and fluent waits

๐Ÿ”—
Appium Execute Methods appium.io

Appium-specific commands and wait strategies for mobile testing