Chaos Testing for QA Engineers: Break Your System Before Users Do
Your system works when everything is perfect. But production is never perfect. Chaos testing deliberately breaks things to verify your system recovers gracefully.
🎠Want to master this with real projects? Join the Playwright Automation Mastery course at The Testing Academy.
Contents
Chaos Engineering for QA Engineers
Traditional QA: “Does the system work?” Chaos testing: “Does the system work when things go wrong?”
Chaos Experiments QA Can Run
| Experiment | What Breaks | Expected Behavior |
|---|---|---|
| Kill a service | Service dependency | Graceful degradation, error message |
| Network latency (3s) | Response time | Loading indicator, no timeout crash |
| Database connection drop | Data layer | Retry logic, queue messages |
| Disk full | Storage | Alert fires, writes rejected cleanly |
| DNS failure | External services | Cached response or fallback |
| CPU spike (100%) | Compute | Auto-scaling triggers, no crash |
🚀 Level Up Your Playwright
From locators to CI pipelines — build a production-grade Playwright + TypeScript framework step by step.
Chaos Testing with Playwright
test('app handles API timeout gracefully', async ({ page }) => {
// Simulate 10-second delay on payment API
await page.route('**/api/payment/**', async route => {
await new Promise(r => setTimeout(r, 10000));
route.abort('timedout');
});
await page.goto('/checkout');
await page.getByRole('button', { name: 'Pay' }).click();
// Should show timeout message, not crash
await expect(page.getByText('Payment service unavailable')).toBeVisible();
await expect(page.getByRole('button', { name: 'Retry' })).toBeVisible();
});
test('app handles 503 from dependency', async ({ page }) => {
await page.route('**/api/inventory/**', route => {
route.fulfill({ status: 503, body: 'Service Unavailable' });
});
await page.goto('/products');
// Should show fallback, not blank page
await expect(page.getByText('Inventory temporarily unavailable')).toBeVisible();
});
Steady State Hypothesis
// Before chaos: verify normal behavior
test.beforeEach(async ({ page }) => {
await page.goto('/');
await expect(page.getByText('Dashboard')).toBeVisible();
// System is in known good state
});
// During chaos: inject failure
// After chaos: verify recovery
test('system recovers after service restart', async ({ page }) => {
// Kill dependency (via API or Docker)
await fetch('http://localhost:9090/chaos/kill-service/inventory');
// Verify degraded behavior
await page.goto('/products');
await expect(page.getByText('Inventory unavailable')).toBeVisible();
// Restart service
await fetch('http://localhost:9090/chaos/restart-service/inventory');
// Verify recovery
await page.reload();
await expect(page.getByText('products found')).toBeVisible();
});
Tools
- Chaos Monkey (Netflix): Randomly kills production instances
- Litmus (CNCF): Kubernetes chaos experiments
- Gremlin: Enterprise chaos platform
- Toxiproxy (Shopify): Simulate network conditions
- Playwright page.route(): Application-level chaos (timeout, 503, slow responses)
🎓 Master Playwright End to End
Join hundreds of SDETs building real automation frameworks. Lifetime access, hands-on projects, and a job-ready portfolio.
