π₯ Playwright Load Test Nightmare: Silent State Pollution?
Imagine thousands of concurrent e-commerce journeys, where a single test failure poisons your CI/CD. Hereβs how to guarantee state isolation and cleanup.
π Problem Statement
Large-scale Playwright E2E load tests for stateful processes (login, cart, checkout) on distributed CI/CD face critical issues.
β Failed tests leave dirty backend state (logged-in users, partial carts) and browser state (cookies).
β’ This pollutes subsequent tests, causing flaky, inexplicable failures.
β’ Goal: Achieve absolute isolation and guaranteed cleanup efficiently, without full browser relaunch per test.
π‘ Solution & Code Walkthrough
Leverage Playwright's BrowserContext for isolation and robust test hooks for setup/teardown.
β
Absolute Isolation:
β’ BrowserContext: Provides an Incognito-like session, isolating cookies, local storage, etc. Crucial for concurrency.
β’ Create a new BrowserContext for each test.beforeEach.
β
Guaranteed Cleanup:
β’ test.beforeEach & test.afterEach: Essential hooks for state management.
β’ Browser State: context.close() in afterEach tears down the isolated session.
β’ Backend State: Make API calls (e.g., DELETE /api/user/{id}) via Playwright's request context in afterEach for data cleanup. This is paramount.
import { test, expect, BrowserContext, request } from '@playwright/test';
test.describe('Concurrent Playwright Isolation', () => {
let context: BrowserContext;
let userId: string; // Example: tracks user for backend cleanup
test.beforeEach(async ({ browser }) => {
context = await browser.newContext(); // New, pristine session
const page = await context.newPage();
// Setup: e.g., register new user, store userId, login
// userId = (await request.post('/api/register')).data.id;
await page.goto('https://ecommerce.com/login');
await expect(page.locator('#dashboard')).toBeVisible();
});
test.afterEach(async () => {
await context.close(); // Close isolated browser context
// Cleanup: e.g., delete user from backend
// await request.delete(`/api/user/${userId}`);
});
test('should complete full e-commerce journey', async () => {
const page = await context.newPage(); // Use isolated context
await page.goto('https://ecommerce.com/products');
// ... intricate add-to-cart, checkout steps ...
await expect(page.locator('.order-confirmation')).toBeVisible();
});
});
β
Efficiency: Creating new BrowserContext instances is far more efficient than launching a full browser (browser.launch()) per test, as browser fixture provides one instance per worker.
π Key Takeaways
β’ BrowserContext is your isolation powerhouse.
β’ test.beforeEach/afterEach are critical for pristine setup/cleanup.
β’ Backend API calls in afterEach are vital for comprehensive state reset.
β’ Prioritize BrowserContext over full browser launches for speed.
β Quick Summary Q&A
Q: Why not just browser.launch() per test?
A: Too slow. browser.newContext() reuses an existing browser instance, offering speed and isolation.
Q: How do I clean backend data effectively?
A: Use Playwright's request context to make targeted API calls (e.g., DELETE, POST /clear-state) in test.afterEach.
TAGS: playwright, typescript, e2e testing, load testing, test automation, CI/CD, software testing, test architecture
ββββββββββββββββββββββββββββββββββββββββ
Level up your test automation skills!
Download our app for exclusive tutorials and daily interview challenges:
ββββββββββββββββββββββββββββββββββββββββ
π² π
πππ ππππππ πππ β πππ+ ππππ π&ππ¬
Practice real-world interview scenarios offline on the free QA Automation & SDET Prep app:
π€ ππ¨π¨π π₯π ππ₯ππ² (ππ§ππ«π¨π’π):
https://play.google.com/store/apps/details?id=com.app.seleniuminterviewquestions&referrer=utm_source%3Ddevto%26utm_medium%3Darticle%26utm_campaign%3Dselenium_20260905
π ππ©π© πππ¨π«π (π’ππ):
https://apps.apple.com/app/id6786760948?pt=128640464&ct=devto_selenium_20260905&mt=8
ββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββ
Top comments (0)