69 / 89 · 04 API & Contract Testing with AI · Asynchronous Testing Patterns← prev⊞ allnext →☰ Read as one page
11.2Pattern 1: Poll and Wait
The simplest async pattern. Check for the expected state within a timeout.
def wait_for_condition(check_fn, timeout=10, interval=0.5, message="Condition not met"):
"""Poll a condition function until it returns True or timeout."""
deadline = time.time() + timeout
last_result = None
while time.time() < deadline:
last_result = check_fn()
if last_result:
return last_result
time.sleep(interval)
pytest.fail(f"{message} (timeout={timeout}s, last_result={last_result})")
# Usage
def test_order_processed(kafka_producer, db):
kafka_producer.send("order.created", {"order_id": "ord-1"})
order = wait_for_condition(
lambda: db.get_order("ord-1"),
timeout=10,
message="Order was not processed"
)
assert order.status == "pending"
When to use: Simple event-to-state verification. One event, one expected state change.
Pitfalls:
- Setting timeout too low causes flaky tests
- Setting interval too high misses the window (state changes then changes again)
- No information about why the condition was not met
Enhanced Version with Diagnostics
def wait_for_condition(check_fn, timeout=10, interval=0.5, message="", diagnostics_fn=None):
"""Poll with diagnostics on failure."""
deadline = time.time() + timeout
attempts = 0
while time.time() < deadline:
attempts += 1
result = check_fn()
if result:
return result
time.sleep(interval)
# Gather diagnostics on failure
diag = ""
if diagnostics_fn:
diag = f"\nDiagnostics: {diagnostics_fn()}"
pytest.fail(
f"{message}\n"
f"Timeout: {timeout}s, Attempts: {attempts}, "
f"Interval: {interval}s{diag}"
)