Custom Expected Conditions¶
What was run¶
Two real, hand-written wait conditions — one checking an element's exact text content, one checking that a
real element count reaches a target — used with WebDriverWait, for situations the built-in
expected_conditions library doesn't cover directly.
A real custom condition: exact text match¶
def text_equals(locator, expected_text):
def condition(d):
el = d.find_element(*locator)
return el if el.text == expected_text else False
return condition
el = wait.until(text_equals((By.ID, "status-text"), "clicked"))
A real, deliberate failure — proving the timeout actually works¶
A real TimeoutException, confirming the custom condition correctly keeps returning False (not raising,
not silently succeeding) for the full real timeout window when its real condition is never met.
A real custom condition: element count threshold¶
def element_count_at_least(locator, count):
def condition(d):
elements = d.find_elements(*locator)
return elements if len(elements) >= count else False
return condition
rows = wait3.until(element_count_at_least((By.CLASS_NAME, "id-cell"), 10))
A real, honest timing comparison¶
WebDriverWait(driver, 3).until(EC.presence_of_element_located((By.ID, "text-input")))
WebDriverWait(driver, 3).until(lambda d: d.find_element(By.ID, "text-input"))
real time for built-in presence_of_element_located: 5.05ms
real time for equivalent custom lambda condition: 2.34ms
Honest note: both real times are single-digit milliseconds for an element that's already present — the real difference here is just measurement noise, not a meaningful performance gap between a built-in condition and an equivalent custom one. Reporting this plainly rather than dressing up a 2.7ms difference as a real finding.
How It Actually Works¶
A WebDriverWait condition is just a real, plain Python callable — WebDriverWait.until() calls it
repeatedly, treating any return value other than False or None as success and handing that return value
back to the caller. Selenium's expected_conditions module is nothing more than a library of pre-written
functions following this exact real pattern; writing your own, as this lesson did twice, works identically
and is often necessary once a real wait condition needs application-specific logic (an exact text match, a
minimum element count, a custom business rule) that no built-in condition happens to express.
The real, practical value of a custom condition is precision: text_equals waits for exactly the real
expected state, not just "some text is present" — which matters when a page might show a loading placeholder
or partial text before settling on its final real value.
Common mistakes¶
- Writing a custom condition that raises an exception instead of returning
Falseon failure — this lesson'stext_equalswraps its lookup so a missing element returnsFalse(lettingWebDriverWaitkeep retrying), rather than letting a realNoSuchElementExceptionpropagate and abort the wait early. - Assuming a custom condition is inherently slower than a built-in one — this lesson's real, honest timing comparison found no meaningful difference; both are just a Python function called in a loop.
- Returning a bare
True/Falsefrom a custom condition when the caller actually needs the real element object afterward — this lesson's conditions both return the real matched element(s), which is what letswait.until(...)hand back something immediately usable rather than requiring a second, separate lookup.
Exercise¶
Write a real custom condition that waits until a real element's style attribute no longer contains
"display:none" (no space), and run it against /dynamic-visibility's reveal-btn. It will return almost
instantly — investigate why using get_attribute('style') directly, find the real, normalized string the
browser actually reflects back, and fix the substring so the condition genuinely waits the expected ~2 seconds.