0
0
Selenium Pythontesting~15 mins

Custom expected conditions in Selenium Python - Deep Dive

Choose your learning style9 modes available
Overview - Custom expected conditions
What is it?
Custom expected conditions are user-defined rules that tell Selenium when to wait for something specific on a web page before continuing. They extend Selenium's built-in waiting features by allowing testers to create their own checks for elements or page states. This helps tests run smoothly by pausing only as long as needed for custom scenarios.
Why it matters
Without custom expected conditions, testers must rely only on fixed waits or generic checks, which can cause tests to fail or waste time waiting too long. Custom conditions solve this by making waits smarter and tailored to the app's unique behavior. This leads to more reliable and faster automated tests, saving time and reducing frustration.
Where it fits
Before learning custom expected conditions, you should understand Selenium basics, especially WebDriver and built-in waits like implicit and explicit waits. After mastering custom conditions, you can explore advanced synchronization techniques and build robust test frameworks that handle complex web app behaviors.
Mental Model
Core Idea
Custom expected conditions let you define exactly what Selenium should wait for, making test waits precise and efficient.
Think of it like...
It's like telling a friend to wait until your favorite song plays on the radio before leaving, instead of just waiting a fixed time or guessing.
┌───────────────────────────────┐
│ Selenium Test Execution Flow   │
├───────────────────────────────┤
│ 1. Trigger action              │
│ 2. Wait using ExpectedCondition│
│    ┌───────────────────────┐  │
│    │ Built-in or Custom     │  │
│    └───────────────────────┘  │
│ 3. Proceed when condition met │
└───────────────────────────────┘
Build-Up - 7 Steps
1
FoundationUnderstanding Selenium waits basics
🤔
Concept: Learn what waits are and why Selenium needs them.
Selenium interacts with web pages that load elements at different speeds. Without waits, Selenium might try to click or read elements before they appear, causing errors. Implicit waits tell Selenium to wait a fixed time for elements to appear. Explicit waits wait for specific conditions before continuing.
Result
Tests become more stable by avoiding errors from missing elements.
Understanding waits is key because web pages are dynamic, and tests must adapt to timing differences.
2
FoundationUsing built-in expected conditions
🤔
Concept: Explore Selenium's ready-made conditions for common waits.
Selenium provides conditions like element_to_be_clickable, presence_of_element_located, and visibility_of_element_located. These help wait for elements to be ready for actions. You use them with WebDriverWait to pause test execution until the condition is true or a timeout occurs.
Result
Tests wait smartly for common element states, reducing flaky failures.
Knowing built-in conditions helps you see when custom ones are needed for special cases.
3
IntermediateWhy create custom expected conditions
🤔Before reading on: do you think built-in conditions cover all test wait needs? Commit to yes or no.
Concept: Recognize the limits of built-in waits and the need for custom logic.
Built-in conditions cover many cases but not all. Sometimes you need to wait for complex states like a specific text change, multiple elements appearing, or custom JavaScript results. Custom expected conditions let you write your own checks to handle these unique scenarios.
Result
You can handle complex page behaviors that built-in waits can't detect.
Knowing when built-in waits fall short empowers you to extend Selenium effectively.
4
IntermediateWriting a simple custom expected condition
🤔Before reading on: do you think a custom expected condition must be a class or can it be a function? Commit to your answer.
Concept: Learn how to write a custom condition as a callable class or function.
A custom expected condition is a callable that takes a WebDriver and returns a truthy value when the condition is met or False/None otherwise. For example, a class with __call__ method or a function can be used. Selenium's WebDriverWait calls it repeatedly until it returns a truthy value or times out.
Result
You can create your own wait logic that integrates seamlessly with WebDriverWait.
Understanding the callable interface unlocks flexible custom wait conditions.
5
IntermediateExample: wait for element text to change
🤔Before reading on: do you think you can wait for an element's text to become a specific value using built-in conditions? Commit to yes or no.
Concept: Implement a custom condition that waits for an element's text to match expected text.
Define a class TextToBeChanged with __init__ to accept locator and expected text. In __call__, find the element and check if its text equals expected text. Return True if matched, else False. Use WebDriverWait(driver, timeout).until(TextToBeChanged(locator, text)) to wait.
Result
Test waits exactly until the element's text updates, avoiding premature actions.
Custom conditions let you wait for dynamic content changes that built-in waits don't cover.
6
AdvancedCombining multiple conditions in custom waits
🤔Before reading on: do you think you can combine several conditions into one custom expected condition? Commit to yes or no.
Concept: Create custom conditions that check multiple things at once for complex waits.
Sometimes you want to wait for multiple elements or states together. Write a custom condition that checks all required conditions inside __call__. For example, wait until two elements are visible and a button is enabled. Return True only when all are met.
Result
Tests can wait for complex page states efficiently without chaining multiple waits.
Combining checks reduces test complexity and improves synchronization precision.
7
ExpertHandling exceptions inside custom expected conditions
🤔Before reading on: should your custom expected condition raise exceptions or handle them internally? Commit to your answer.
Concept: Learn to manage exceptions inside custom conditions to avoid test failures during waits.
WebDriverWait retries calling your condition until timeout. If your condition raises exceptions like NoSuchElementException, it can cause premature failure. Instead, catch expected exceptions inside __call__ and return False to keep waiting. This makes waits robust against transient page states.
Result
Custom waits become stable and do not fail due to temporary element absence or page changes.
Proper exception handling inside custom conditions prevents flaky tests and improves reliability.
Under the Hood
WebDriverWait repeatedly calls the expected condition callable, passing the WebDriver instance. The callable checks the page state and returns a truthy value when the condition is met or False/None otherwise. If the condition returns truthy before timeout, wait ends successfully; otherwise, it times out and raises TimeoutException.
Why designed this way?
This design separates waiting logic from condition logic, making waits reusable and flexible. Using callables allows any user-defined logic to integrate seamlessly. It avoids blocking the main thread and supports polling with intervals, balancing responsiveness and resource use.
┌───────────────┐
│ WebDriverWait │
├───────────────┤
│ Loop:         │
│ ┌───────────┐ │
│ │ Call cond │─┼─> Returns True? ──┐
│ └───────────┘ │                   │
│ If True: End │                   │
│ Else: Sleep  │                   │
│ Repeat until │                   │
│ timeout      │                   │
└───────────────┘                   │
                                  │
                           ┌──────┴─────┐
                           │ Timeout    │
                           │ Exception  │
                           └────────────┘
Myth Busters - 4 Common Misconceptions
Quick: do you think custom expected conditions must always be classes? Commit to yes or no.
Common Belief:Custom expected conditions must be classes with __call__ methods.
Tap to reveal reality
Reality:They can be any callable, including functions, as long as they accept a WebDriver and return a truthy value when ready.
Why it matters:Believing only classes work limits flexibility and can make code unnecessarily complex.
Quick: do you think exceptions inside custom conditions cause WebDriverWait to fail immediately? Commit to yes or no.
Common Belief:If a custom condition raises an exception, WebDriverWait stops and fails the test.
Tap to reveal reality
Reality:WebDriverWait ignores certain exceptions like NoSuchElementException if they are handled properly inside the condition. Unhandled exceptions do cause failure.
Why it matters:Not handling exceptions inside conditions leads to flaky tests and premature failures.
Quick: do you think custom expected conditions always make tests slower? Commit to yes or no.
Common Belief:Adding custom waits always slows down test execution.
Tap to reveal reality
Reality:Custom conditions can make tests faster by waiting exactly for needed states, avoiding fixed or excessive waits.
Why it matters:Misunderstanding this can cause testers to avoid custom waits and write brittle tests.
Quick: do you think built-in expected conditions cover every possible wait scenario? Commit to yes or no.
Common Belief:Built-in expected conditions are enough for all waiting needs.
Tap to reveal reality
Reality:They cover common cases but not complex or app-specific states, which require custom conditions.
Why it matters:Ignoring custom conditions limits test coverage and robustness.
Expert Zone
1
Custom expected conditions can return any truthy value, not just True, allowing you to pass useful data to the wait result.
2
You can chain or compose custom conditions to build reusable, modular wait logic for complex scenarios.
3
Properly handling exceptions inside custom conditions is critical to avoid flaky tests caused by transient page states.
When NOT to use
Avoid custom expected conditions when a built-in condition suffices, as custom code adds maintenance overhead. For very complex waits, consider using explicit JavaScript execution or event listeners instead.
Production Patterns
In real projects, custom expected conditions are used to wait for dynamic content updates, multi-element states, or backend-driven UI changes. They are often wrapped in utility libraries to keep test code clean and reusable.
Connections
Callback functions
Custom expected conditions are a form of callback used by WebDriverWait to check readiness.
Understanding callbacks helps grasp how Selenium repeatedly invokes conditions until success.
Polling mechanisms
WebDriverWait uses polling to repeatedly check conditions at intervals.
Knowing polling concepts clarifies why waits balance responsiveness and resource use.
Event-driven programming
Custom expected conditions mimic waiting for events by checking states repeatedly.
Recognizing this connection helps design efficient waits that respond to UI changes.
Common Pitfalls
#1Not handling exceptions inside custom conditions causes premature test failure.
Wrong approach:class WaitForElementText: def __init__(self, locator, text): self.locator = locator self.text = text def __call__(self, driver): element = driver.find_element(*self.locator) # May raise NoSuchElementException return element.text == self.text
Correct approach:class WaitForElementText: def __init__(self, locator, text): self.locator = locator self.text = text def __call__(self, driver): try: element = driver.find_element(*self.locator) return element.text == self.text except Exception: return False
Root cause:Misunderstanding that exceptions during waits should be caught to allow retrying.
#2Using fixed sleep instead of custom expected conditions leads to slow and flaky tests.
Wrong approach:driver.find_element(By.ID, 'start').click() time.sleep(5) # Wait fixed 5 seconds assert 'Done' in driver.page_source
Correct approach:driver.find_element(By.ID, 'start').click() WebDriverWait(driver, 10).until(lambda d: 'Done' in d.page_source)
Root cause:Not leveraging Selenium's waiting features and relying on guesswork.
#3Writing custom conditions that return None instead of False when not ready causes WebDriverWait to stop waiting.
Wrong approach:def condition(driver): element = driver.find_element(By.ID, 'msg') if element.text == 'Ready': return True else: return None # Incorrect, should return False
Correct approach:def condition(driver): element = driver.find_element(By.ID, 'msg') if element.text == 'Ready': return True else: return False
Root cause:Misunderstanding that WebDriverWait treats None as success and stops waiting.
Key Takeaways
Custom expected conditions let you define exactly what Selenium should wait for, making tests more reliable and efficient.
They are callables that WebDriverWait repeatedly calls until a condition is met or timeout occurs.
Proper exception handling inside custom conditions is essential to avoid flaky tests caused by transient page states.
Custom conditions extend Selenium's built-in waits to handle complex or app-specific scenarios.
Using custom expected conditions wisely improves test speed, stability, and maintainability.