Modern QA2026Network Condition Variability
Log inJoin
1 / 2 · Book 9 · The Device Fragmentation Reality · drill: interview Q&A⊞ allnext →Get the book →

1.5Network Condition Variability

Network conditions are the most underestimated fragmentation dimension. A feature that works perfectly on WiFi may be unusable on a congested 3G connection, and your test suite running on a fast CI server will never catch this.

Condition Typical Latency Typical Bandwidth Where It Occurs
WiFi (good) 5-20ms 50-500 Mbps Home, office
WiFi (congested) 50-200ms 1-10 Mbps Coffee shops, airports, conferences
5G 10-30ms 100-500 Mbps Urban areas with 5G coverage
4G/LTE 30-50ms 10-50 Mbps Suburban areas, most coverage areas
3G 100-500ms 0.5-5 Mbps Rural areas, developing markets
2G/Edge 300-1000ms 0.05-0.2 Mbps Remote areas, tunnels, emergency fallback
Offline Infinite 0 Elevators, subways, airplane mode, dead zones

The Impact of Network Conditions on User Experience

Consider a typical e-commerce checkout flow:

  • On good WiFi: Page loads in 800ms. User taps "Place Order." Confirmation appears in 1.2 seconds. Smooth experience.
  • On 3G: Page loads in 8 seconds. User taps "Place Order." Nothing seems to happen for 3 seconds. User taps again. Two orders are placed. User is angry.
  • On 2G: Page does not finish loading. Images are missing. The "Place Order" button is below the fold because a large hero image pushed it down. User gives up.
  • Offline: User loses connection mid-checkout. What happens to their cart? Is it saved? Can they resume when connectivity returns?

Each of these scenarios requires different handling in your application and different test coverage in your test suite.

Testing Network Conditions Programmatically

Playwright provides Chrome DevTools Protocol (CDP) access to simulate network conditions:

// Playwright: emulate network conditions
import { test, expect } from '@playwright/test';

const networkProfiles = {
    '4g': { download: 4_000_000, upload: 3_000_000, latency: 40 },
    '3g': { download: 750_000, upload: 250_000, latency: 100 },
    'slow3g': { download: 500_000, upload: 250_000, latency: 300 },
    'offline': { download: 0, upload: 0, latency: 0 },
};

for (const [name, profile] of Object.entries(networkProfiles)) {
    test(`app loads within budget on ${name}`, async ({ page, context }) => {
        const cdp = await context.newCDPSession(page);
        await cdp.send('Network.emulateNetworkConditions', {
            offline: profile.download === 0,
            downloadThroughput: profile.download / 8,
            uploadThroughput: profile.upload / 8,
            latency: profile.latency,
        });

        const start = Date.now();
        await page.goto('/');
        const loadTime = Date.now() - start;

        // Set budget per network condition
        const budgets: Record<string, number> = {
            '4g': 3000,
            '3g': 8000,
            'slow3g': 15000,
        };

        if (budgets[name]) {
            expect(loadTime).toBeLessThan(budgets[name]);
        }
    });
}

Network Throttling on Real Devices

For real device testing on cloud device farms, you can use platform-specific network conditioning:

# BrowserStack: Set network conditions
def set_network_profile(driver, profile):
    """Set network conditions on BrowserStack."""
    driver.execute_script(
        'browserstack_executor: {"action": "setNetworkProfile", '
        f'"arguments": {{"profile": "{profile}"}}}}'
    )

# Available profiles: 2g-gprs, 2g-edge, 3g-umts, 3g-hspa,
# 3.5g-hspa-plus, 4g-lte, 4g-lte-advanced, no-network, reset

# Example usage in a test
def test_checkout_on_3g(driver):
    set_network_profile(driver, "3g-umts")
    # Navigate to checkout
    driver.find_element(AppiumBy.ACCESSIBILITY_ID, "checkout-btn").click()
    # Verify loading indicator appears (user knows something is happening)
    loading = driver.find_element(AppiumBy.ACCESSIBILITY_ID, "loading-indicator")
    assert loading.is_displayed()
    # Wait for checkout page to load (extended timeout for slow network)
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    WebDriverWait(driver, 30).until(
        EC.presence_of_element_located(
            (AppiumBy.ACCESSIBILITY_ID, "checkout-form")
        )
    )
    # Reset network
    set_network_profile(driver, "reset")