DEV Community

Styrow.dev
Styrow.dev

Posted on Originally published at styrow.dev

How do you efficiently manage and restore distinct authentication states when running Playwright tests in parallel?

🔥 Playwright Parallel Testing Headache: How do you efficiently manage and restore distinct authentication states when running Playwright tests in parallel? Sharing auth across parallel test workers causes flaky failures and slow execution.

📌 Problem Statement
Running Playwright tests in parallel is crucial for speed. ❌ A major pitfall is parallel tests interfering with each other's authentication states. This leads to unpredictable failures due to shared cookies, local storage, or session data. Re-logging for every test is slow and inefficient.

💡 Solution & Code Walkthrough
The robust solution leverages Playwright's browserContext with storageState. This strategy ensures each parallel test worker has its own isolated, pre-authenticated session.

• Authenticate once for each user/role.
• Capture the authenticated session's storageState (cookies, local/session storage).
• Re-use this storageState to create new browserContext instances for tests.

Step 1: Create an auth.setup.ts script
This runs once to log in a user and save their session state.

// playwright/auth.setup.ts
import { test as setup } from '@playwright/test';
import * as path from 'path';

const authFile = path.join(__dirname, '.auth/user.json');

setup('authenticate standard user', async ({ page }) => {
  await page.goto('https://example.com/login');
  await page.fill('#username', 'testuser');
  await page.fill('#password', 'password123');
  await page.click('button[type="submit"]');
  await page.waitForURL('https://example.com/dashboard');
  await page.context().storageState({ path: authFile });
});
Enter fullscreen mode Exit fullscreen mode

Step 2: Configure playwright.config.ts to use storageState
This tells Playwright to load the saved state for all tests.

// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';
import * as path from 'path';

export default defineConfig({
  projects: [
    { name: 'setup', testMatch: /.*\.setup\.ts/ },
    {
      name: 'authenticated',
      dependencies: ['setup'],
      use: {
        storageState: path.join(__dirname, 'playwright/.auth/user.json'),
      },
    },
  ],
});
Enter fullscreen mode Exit fullscreen mode

Step 3: Write your tests (they now run pre-authenticated!)

// tests/dashboard.spec.ts
import { test, expect } from '@playwright/test';

test.describe('Dashboard access', () => {
  test('should display user profile', async ({ page }) => {
    await page.goto('https://example.com/dashboard');
    await expect(page.locator('#user-profile-name')).toHaveText('Test User');
  });
});
Enter fullscreen mode Exit fullscreen mode

🔑 Key Takeaways
✅ Isolation: Each test runs in its own distinct, pre-authenticated browserContext.
✅ Efficiency: No need to re-login in every test or worker, significantly speeding up parallel runs.
✅ Robustness: Eliminates cross-test authentication pollution, reducing flakiness.
• The setup project ensures authentication runs once before dependent tests.

❓ Quick Summary Q&A
• Q: Why use storageState for parallel Playwright tests?
• A: To manage distinct authentication states, prevent interference, and speed up execution by avoiding repeated logins.
• Q: What does storageState save?
• A: Cookies, local storage, and session storage from an authenticated session.

TAGS: playwright, testing, automation, typescript, authentication, parallel testing, e2e, ci/cd

────────────────────────────────────────
────────────────────────────────────────

📲 𝐅𝐑𝐄𝐄 𝐌𝐎𝐁𝐈𝐋𝐄 𝐀𝐏𝐏 — 𝟔𝟎𝟎+ 𝐒𝐃𝐄𝐓 𝐐&𝐀𝐬
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_20261115

🍎 𝐀𝐩𝐩 𝐒𝐭𝐨𝐫𝐞 (𝐢𝐎𝐒):
https://apps.apple.com/app/id6786760948?pt=128640464&ct=devto_selenium_20261115&mt=8

────────────────────────────────────────
────────────────────────────────────────

Top comments (0)