Sometimes, you need to wait for something special on a webpage before continuing your test. Custom wait conditions let you tell the test exactly what to wait for.
Custom wait conditions in Selenium Python
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC class CustomCondition: def __init__(self, locator): self.locator = locator def __call__(self, driver): element = driver.find_element(*self.locator) if element.text == 'Ready': return element else: return False
The custom condition is a class with a __call__ method that Selenium calls repeatedly.
Return the element or True when the condition is met; return False to keep waiting.
class TextIsReady: def __init__(self, locator): self.locator = locator def __call__(self, driver): element = driver.find_element(*self.locator) return element.text == 'Ready'
class AttributeChanged: def __init__(self, locator, attribute, expected_value): self.locator = locator self.attribute = attribute self.expected_value = expected_value def __call__(self, driver): element = driver.find_element(*self.locator) return element.get_attribute(self.attribute) == self.expected_value
This test opens a page, waits up to 10 seconds for the element with ID 'status' to have text 'Ready', then prints the text.
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait class TextIsReady: def __init__(self, locator): self.locator = locator def __call__(self, driver): element = driver.find_element(*self.locator) if element.text == 'Ready': return element else: return False # Setup driver (example with Chrome) driver = webdriver.Chrome() driver.get('https://example.com/wait_test') locator = (By.ID, 'status') wait = WebDriverWait(driver, 10) # Use custom wait condition ready_element = wait.until(TextIsReady(locator)) print(f"Element text is: {ready_element.text}") driver.quit()
Custom wait conditions help when built-in waits are not enough.
Always return False or None to keep waiting, and a truthy value to stop waiting.
Use descriptive class names to keep your tests clear.
Custom wait conditions let you wait for exactly what you need.
Create a class with a __call__ method that returns True or the element when ready.
Use WebDriverWait with your custom condition to pause your test smartly.
Practice
Solution
Step 1: Understand built-in waits limitations
Built-in waits cover common cases but sometimes you need to wait for a unique condition.Step 2: Purpose of custom wait
Custom waits let you define exactly what to wait for, improving test reliability.Final Answer:
To wait for a specific condition that is not covered by built-in waits -> Option DQuick Check:
Custom wait = wait for unique condition [OK]
- Thinking custom waits speed up tests
- Believing custom waits replace WebDriverWait
- Assuming custom waits retry tests automatically
Solution
Step 1: Identify the special method for custom waits
Custom wait classes must implement the __call__ method to be callable by WebDriverWait.Step 2: Check method signature and return
Method __call__ takes driver and returns element or True when condition met.Final Answer:
class MyWait:\n def __call__(self, driver):\n return driver.find_element_by_id('myid') -> Option AQuick Check:
Custom wait uses __call__ method [OK]
- Using method named wait instead of __call__
- Defining function instead of class
- Using wrong method signature
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
class WaitForSubmit:
def __call__(self, driver):
try:
elem = driver.find_element(By.ID, 'submit')
return elem
except:
return False
wait = WebDriverWait(driver, 5)
submit_button = wait.until(WaitForSubmit())
print(submit_button.tag_name)Solution
Step 1: Understand the custom wait behavior
The custom wait tries to find element with id 'submit'. If not found, returns False to keep waiting.Step 2: Analyze wait.until with timeout 5 seconds
The element appears after 3 seconds, so wait.until returns the element before timeout.Final Answer:
Prints the tag name of the 'submit' element after waiting -> Option CQuick Check:
Element appears before timeout, so tag_name prints [OK]
- Assuming immediate TimeoutException
- Expecting print of False instead of element
- Confusing exceptions raised
class WaitForText:
def __call__(self, driver):
element = driver.find_element(By.ID, 'message')
if element.text == 'Done':
return True
else:
return None
wait = WebDriverWait(driver, 10)
wait.until(WaitForText())Solution
Step 1: Check imports
The code uses By.ID but does not import By, causing NameError at runtime.Step 2: Analyze return values
Returning True or None is allowed; wait.until treats True as success and None as failure to continue waiting.Final Answer:
Missing import for By causes NameError -> Option BQuick Check:
By must be imported to avoid NameError [OK]
- Thinking None stops waiting (it continues)
- Assuming returning True causes error
- Confusing find_element with find_elements
Solution
Step 1: Check condition logic
We need both visible and enabled, so use 'and' operator to check both.Step 2: Return element when condition met
Return the button element so wait.until returns it for further actions.Final Answer:
class WaitForStart:\n def __call__(self, driver):\n btn = driver.find_element(By.ID, 'start')\n if btn.is_displayed() and btn.is_enabled():\n return btn\n return False -> Option AQuick Check:
Return element when visible and enabled [OK]
- Using 'or' instead of 'and' for conditions
- Returning True instead of element
- Returning None instead of False
Ready to prove it?
Pass the test and this pattern moves unknown
