Modern QA2026Common Async Pitfalls — tiles
Log inJoin
48 / 80 · 12 Programming for QA · Async/Await Patterns← prev⊞ allnext →☰ Read as one page

6.5Common Async Pitfalls

1. Forgotten Await

Already covered above — the most dangerous bug because the test passes silently.

Detection: Use TypeScript strict mode and ESLint rules like @typescript-eslint/no-floating-promises.

2. Race Conditions in Tests

// BUG: click may happen before navigation completes
await page.goto('/products');
page.click('[data-testid="first-product"]');  // missing await!
await expect(page).toHaveURL(/\/products\/\d+/);  // may fail intermittently

// FIX: await the click
await page.goto('/products');
await page.click('[data-testid="first-product"]');
await expect(page).toHaveURL(/\/products\/\d+/);

3. Shared State Between Concurrent Tests

# BUG: parallel tests modify the same user
async def test_update_name():
    await api.patch("/users/1", json={"name": "Alice"})
    user = await api.get("/users/1")
    assert user["name"] == "Alice"  # May fail if test_update_email runs concurrently

async def test_update_email():
    await api.patch("/users/1", json={"email": "new@test.com"})
    user = await api.get("/users/1")
    assert user["email"] == "new@test.com"

# FIX: each test creates its own user
async def test_update_name():
    user = await api.post("/users", json={"name": "Original"})
    await api.patch(f"/users/{user['id']}", json={"name": "Alice"})
    updated = await api.get(f"/users/{user['id']}")
    assert updated["name"] == "Alice"

4. Unhandled Promise Rejections

// BUG: if the fetch fails, the error is swallowed
fetch('/api/cleanup').then(r => r.json());  // no await, no catch

// FIX: always await or catch
try {
    await fetch('/api/cleanup');
} catch (e) {
    console.warn('Cleanup failed:', e);
}

5. Event Loop Blocking

# BUG: synchronous sleep blocks the event loop
async def test_with_delay():
    import time
    time.sleep(5)  # Blocks the entire event loop for 5 seconds!

# FIX: use async sleep
async def test_with_delay():
    await asyncio.sleep(5)  # Non-blocking