Bird
Raised Fist0
Selenium Pythontesting~7 mins

Custom wait conditions in Selenium Python

Choose your learning style10 modes available
Introduction

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.

Waiting for a specific text to appear inside an element.
Waiting for a button to become clickable after some animation.
Waiting for a custom attribute to change value on an element.
Waiting for multiple elements to be visible at the same time.
Waiting for a loading spinner to disappear before proceeding.
Syntax
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.

Examples
This waits until the element's text is exactly 'Ready'.
Selenium Python
class TextIsReady:
    def __init__(self, locator):
        self.locator = locator

    def __call__(self, driver):
        element = driver.find_element(*self.locator)
        return element.text == 'Ready'
This waits until a specific attribute of an element matches the expected value.
Selenium Python
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
Sample Program

This test opens a page, waits up to 10 seconds for the element with ID 'status' to have text 'Ready', then prints the text.

Selenium Python
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()
OutputSuccess
Important Notes

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.

Summary

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

(1/5)
1. What is the main purpose of creating a custom wait condition in Selenium with Python?
easy
A. To automatically retry failed tests
B. To speed up the test execution by skipping waits
C. To replace the WebDriverWait class completely
D. To wait for a specific condition that is not covered by built-in waits

Solution

  1. Step 1: Understand built-in waits limitations

    Built-in waits cover common cases but sometimes you need to wait for a unique condition.
  2. Step 2: Purpose of custom wait

    Custom waits let you define exactly what to wait for, improving test reliability.
  3. Final Answer:

    To wait for a specific condition that is not covered by built-in waits -> Option D
  4. Quick Check:

    Custom wait = wait for unique condition [OK]
Hint: Custom waits handle unique conditions not in built-in waits [OK]
Common Mistakes:
  • Thinking custom waits speed up tests
  • Believing custom waits replace WebDriverWait
  • Assuming custom waits retry tests automatically
2. Which of the following is the correct way to define a custom wait condition class in Selenium Python?
easy
A. class MyWait: def __call__(self, driver): return driver.find_element_by_id('myid')
B. class MyWait: def wait(self): return True
C. def MyWait(driver): return driver.find_element('id', 'myid')
D. class MyWait: def wait_for(self, driver): return False

Solution

  1. Step 1: Identify the special method for custom waits

    Custom wait classes must implement the __call__ method to be callable by WebDriverWait.
  2. Step 2: Check method signature and return

    Method __call__ takes driver and returns element or True when condition met.
  3. Final Answer:

    class MyWait:\n def __call__(self, driver):\n return driver.find_element_by_id('myid') -> Option A
  4. Quick Check:

    Custom wait uses __call__ method [OK]
Hint: Custom wait class must have __call__(self, driver) method [OK]
Common Mistakes:
  • Using method named wait instead of __call__
  • Defining function instead of class
  • Using wrong method signature
3. Given the code below, what will be the output if the element with id 'submit' appears after 3 seconds?
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)
medium
A. Prints False
B. Raises TimeoutException immediately
C. Prints the tag name of the 'submit' element after waiting
D. Raises NoSuchElementException

Solution

  1. 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.
  2. Step 2: Analyze wait.until with timeout 5 seconds

    The element appears after 3 seconds, so wait.until returns the element before timeout.
  3. Final Answer:

    Prints the tag name of the 'submit' element after waiting -> Option C
  4. Quick Check:

    Element appears before timeout, so tag_name prints [OK]
Hint: Custom wait returns element or False; wait.until waits until element found [OK]
Common Mistakes:
  • Assuming immediate TimeoutException
  • Expecting print of False instead of element
  • Confusing exceptions raised
4. Identify the error in the following custom wait condition code:
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())
medium
A. Returning None instead of False causes wait.until to stop waiting
B. Missing import for By causes NameError
C. Returning True instead of element causes error
D. Using find_element instead of find_elements causes exception

Solution

  1. Step 1: Check imports

    The code uses By.ID but does not import By, causing NameError at runtime.
  2. Step 2: Analyze return values

    Returning True or None is allowed; wait.until treats True as success and None as failure to continue waiting.
  3. Final Answer:

    Missing import for By causes NameError -> Option B
  4. Quick Check:

    By must be imported to avoid NameError [OK]
Hint: Always import By before using it in locators [OK]
Common Mistakes:
  • Thinking None stops waiting (it continues)
  • Assuming returning True causes error
  • Confusing find_element with find_elements
5. You want to wait until a button with id 'start' is both visible and enabled before clicking it. Which custom wait condition class correctly implements this?
hard
A. class WaitForStart: def __call__(self, driver): btn = driver.find_element(By.ID, 'start') if btn.is_displayed() and btn.is_enabled(): return btn return False
B. class WaitForStart: def __call__(self, driver): btn = driver.find_element(By.ID, 'start') if btn.is_displayed() or btn.is_enabled(): return True return False
C. class WaitForStart: def __call__(self, driver): btn = driver.find_element(By.ID, 'start') if btn.is_displayed() and btn.is_enabled(): return True return False
D. class WaitForStart: def __call__(self, driver): btn = driver.find_element(By.ID, 'start') if btn.is_enabled(): return btn return None

Solution

  1. Step 1: Check condition logic

    We need both visible and enabled, so use 'and' operator to check both.
  2. Step 2: Return element when condition met

    Return the button element so wait.until returns it for further actions.
  3. 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 A
  4. Quick Check:

    Return element when visible and enabled [OK]
Hint: Return element only if visible AND enabled, else False [OK]
Common Mistakes:
  • Using 'or' instead of 'and' for conditions
  • Returning True instead of element
  • Returning None instead of False
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard