Modern QA2026Pattern 1: Poll and Wait — tiles
Log inJoin
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}"
    )