</>

Technology

Playwright

Difficulty

Beginner

Interview Question

How do you use beforeEach, afterEach, beforeAll, and afterAll hooks in Playwright?

Answer

Playwright Test Hooks

Playwright provides four lifecycle hooks for setting up and tearing down test state.

beforeEach — Runs Before Every Test

TypeScript
import { test, expect } from '@playwright/test';

test.beforeEach(async ({ page }) => {
  // Runs before each test in this file
  await page.goto('/login');
  await page.getByLabel('Email').fill('user@test.com');
  await page.getByLabel('Password').fill('password');
  await page.getByRole('button', { name: 'Sign in' }).click();
  await expect(page).toHaveURL('/dashboard');
});

test('can see dashboard', async ({ page }) => {
  await expect(page.getByRole('heading')).toHaveText('Dashboard');
});

test('can view profile', async ({ page }) => {
  await page.getByRole('link', { name: 'Profile' }).click();
  await expect(page).toHaveURL('/profile');
});

afterEach — Runs After Every Test

TypeScript
test.afterEach(async ({ page }, testInfo) => {
  if (testInfo.status !== testInfo.expectedStatus) {
    // Take screenshot on failure
    const screenshot = await page.screenshot();
    await testInfo.attach('screenshot', { body: screenshot, contentType: 'image/png' });
  }
});

beforeAll — Runs Once Before All Tests in the Suite

TypeScript
import { test, expect, Browser } from '@playwright/test';

test.describe('Admin Suite', () => {
  let adminPage: any;

  test.beforeAll(async ({ browser }) => {
    // Create an admin session once for all tests
    const context = await browser.newContext();
    adminPage = await context.newPage();
    await adminPage.goto('/admin/login');
    await adminPage.getByLabel('Email').fill('admin@test.com');
    await adminPage.getByLabel('Password').fill('admin123');
    await adminPage.getByRole('button', { name: 'Sign in' }).click();
  });

  test.afterAll(async () => {
    await adminPage.close();
  });

  test('admin can create user', async () => {
    await adminPage.getByRole('link', { name: 'Users' }).click();
    // ...
  });
});

afterAll — Runs Once After All Tests

TypeScript
test.afterAll(async () => {
  // Cleanup: delete test data, close DB connections, etc.
  console.log('All tests done — cleaning up');
});

Hook Execution Order

CODE
beforeAll
  └── beforeEach → test 1 → afterEach
  └── beforeEach → test 2 → afterEach
  └── beforeEach → test 3 → afterEach
afterAll

Hooks Inside describe Blocks

TypeScript
test.describe('Shopping Cart', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/cart');
  });

  test('shows empty cart message', async ({ page }) => {
    await expect(page.getByText('Your cart is empty')).toBeVisible();
  });
});

Note: beforeAll in Playwright runs in the worker scope — avoid sharing mutable page state across tests, as tests may run in different workers. Use beforeEach for page-level setup.

Follow AutomateQA

Related Topics