Explicit waits (WebDriverWait) in Selenium Python - Build an Automation Script
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 TimeoutException # Initialize the Chrome WebDriver with webdriver.Chrome() as driver: driver.get('https://example.com/login') try: # Wait up to 10 seconds until the login button is clickable wait = WebDriverWait(driver, 10) login_button = wait.until(EC.element_to_be_clickable((By.ID, 'loginBtn'))) # Click the login button login_button.click() # Wait until URL changes to dashboard wait.until(EC.url_to_be('https://example.com/dashboard')) # Assert the current URL is the dashboard URL assert driver.current_url == 'https://example.com/dashboard', f"Expected URL to be 'https://example.com/dashboard' but got {driver.current_url}" print('Test Passed: Login button clickable and dashboard loaded') except TimeoutException: print('Test Failed: Element not clickable or URL did not change in time')
This script uses Selenium WebDriver with Python to automate the manual test case.
First, it opens the browser and navigates to the login page URL.
Then, it uses WebDriverWait with expected_conditions.element_to_be_clickable to wait up to 10 seconds for the login button to become clickable. This is better than using fixed waits because it waits only as long as needed.
After the button is clickable, it clicks the button.
Next, it waits until the URL changes to the dashboard URL using expected_conditions.url_to_be.
Finally, it asserts that the current URL is the expected dashboard URL to confirm navigation succeeded.
Exceptions like TimeoutException are caught to handle cases where the button never becomes clickable or the URL does not change in time, printing a failure message.
This approach follows best practices by using explicit waits, proper locators, and assertions.
Now add data-driven testing with 3 different login URLs and verify the login button on each page becomes clickable.
Practice
WebDriverWait in Selenium tests?Solution
Step 1: Understand the role of explicit waits
Explicit waits pause the test until a specific condition is true or a timeout happens, making tests more reliable.Step 2: Compare with other wait types
Unlike fixed waits, explicit waits respond to page conditions, not just time delays.Final Answer:
To wait explicitly until a certain condition is met or timeout occurs -> Option DQuick Check:
Explicit wait = wait for condition [OK]
- Confusing explicit wait with fixed sleep
- Thinking it speeds up tests
- Assuming it retries tests automatically
Solution
Step 1: Recall WebDriverWait constructor parameters
The constructor takes the driver first, then the timeout as an integer or float in seconds.Step 2: Check each option's correctness
wait = WebDriverWait(driver, 10) matches the correct order and type. wait = WebDriverWait(10, driver) reverses parameters. wait = WebDriverWait(driver, timeout=10s) uses invalid syntax with '10s'. wait = WebDriverWait(driver, "10") passes timeout as string, which is incorrect.Final Answer:
wait = WebDriverWait(driver, 10) -> Option AQuick Check:
WebDriverWait(driver, seconds) [OK]
- Swapping driver and timeout parameters
- Using string instead of number for timeout
- Adding units like 's' in timeout
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 5)
element = wait.until(EC.element_to_be_clickable((By.ID, 'submit')))
print('Element found:', element is not None)Solution
Step 1: Understand wait.until behavior
The wait will pause up to 5 seconds for the element to be clickable. Since the element appears after 3 seconds, it will be found within timeout.Step 2: Check the print statement output
The element variable will hold the found element, so 'element is not None' is True, printing 'Element found: True'.Final Answer:
Element found: True -> Option BQuick Check:
Element appears before timeout = True [OK]
- Assuming wait.until returns False if element appears
- Expecting TimeoutException when element appears in time
- Confusing syntax errors with runtime behavior
wait = WebDriverWait(driver, 10) wait.until(EC.presence_of_element_located(By.ID, 'username'))
Solution
Step 1: Check expected condition usage
The method presence_of_element_located expects a single argument: a tuple like (By.ID, 'username').Step 2: Identify the mistake in argument format
The code passes By.ID and 'username' as separate arguments, missing the tuple, causing a TypeError.Final Answer:
Missing tuple around locator in presence_of_element_located -> Option AQuick Check:
Locator must be tuple (By.ID, 'value') [OK]
- Passing locator arguments separately instead of tuple
- Using string timeout instead of number
- Thinking polling parameter is mandatory
Solution
Step 1: Understand waiting for multiple conditions
WebDriverWait can accept a custom function that returns True when either condition is met, allowing waiting for multiple conditions simultaneously.Step 2: Evaluate options for efficiency and correctness
Use WebDriverWait with a custom expected condition combining both checks using a lambda function uses a lambda combining both conditions, so wait ends as soon as one is true. Use two separate WebDriverWait calls one after another for each condition waits sequentially, possibly longer. Use implicit wait instead of explicit wait for both elements uses implicit wait, which is not suitable for condition checks. Use time.sleep() to wait a fixed time before checking both elements uses fixed sleep, which is unreliable.Final Answer:
Use WebDriverWait with a custom expected condition combining both checks using a lambda function -> Option CQuick Check:
Custom combined condition = fastest wait [OK]
- Waiting sequentially causing longer delays
- Using implicit wait for condition checks
- Using fixed sleep instead of waits
Ready to prove it?
Pass the test and this pattern moves unknown
