Tip #3

The "10% Rule" (Random Failure Injection)

How to catch Uncaught Promise Rejection by introducing randomness.

The Problem: The Clean Laboratory

The Laboratory

EnvironmentSterile
Success Rate100.0%
"Tests always pass!" (False confidence)

Real World

EnvironmentChaotic
Failure Rate~1 - 5%
  • Packet Loss / Timeouts
  • White Screen of Death

Your test environment is too clean. 100% of API calls succeed. If your frontend code assumes response.ok === true every time, a single failed image load or analytics ping could crash your entire React app.

The Solution: The Chaos Interceptor

Don't just mock specific routes

Mocking /api/user to return 500 is good, but it's deterministic. It doesn't find the bugs you aren't looking for.

RECOMMENDED

Do use a Random Interceptor

Act like a "Bad Wi-Fi Router." Intercept every single request and roll a dice. If it rolls a 1 (10% chance), the request fails.

Why 10%?

Because at 50% the app becomes unusable. At 1%, bugs are too rare to reproduce. 10% is the sweet spot: annoying enough to break bad code, but functional enough to click through the flow.

The Code (Python + Playwright)

We tell Playwright to intercept every network request and potentially abort it based on a probability factor.

tests/chaos_interceptor.py
import random
from playwright.sync_api import Page, Route, expect

def test_random_network_failure(page: Page):
    # ๐Ÿงจ CHAOS CONFIGURATION
    # 10% chance of any request failing
    FAILURE_RATE = 0.10 

    def chaos_router(route: Route):
        # We exclude the main document (so the page actually loads)
        if route.request.resource_type == "document":
            route.continue_()
            return

        # Roll the dice
        if random.random() < FAILURE_RATE:
            print(f"๐Ÿ’ฅ Killing request: {route.request.url}")
            # Simulates a connection drop (ERR_FAILED)
            route.abort("failed")
        else:
            route.continue_()

    # 1. Activate the interceptor for ALL traffic
    page.route("**/*", chaos_router)

    # 2. Run your standard user flow
    page.goto("/dashboard")
    page.click("#submit-order")

    # 3. Resilience Assertion
    # The app might show error toasts, but it should NOT crash.
    # We check that the main UI is still visible.
    expect(page.locator("#app-root")).to_be_visible()
    expect(page.locator(".crash-boundary")).not_to_be_visible()

Start Testing in "Bad Wi-Fi Mode"

Debuggo has a built-in Randomness Slider. Drag it to 10% and watch your app struggle (and then improve).

Enable Chaos Mode

System-wide proxy

Why this matters: This is the ultimate "Anti-Flakiness" training. If your tests can pass while 10% of the network is exploding, your application is bulletproof. This often uncovers critical bugs where a non-essential failure (like a failed icon load) prevents the user from checking out.