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")