Playwright Fixtures

A fixture in Playwright is a reusable setup and teardown mechanism that prepares the test environment before a test runs and cleans it up after the test finishes.

In simple terms, fixtures help avoid repeating setup code in every test.

Playwright provides several built-in fixtures such as page, browser, and context, and it also allows you to create custom fixtures.

Built-In Playwright Fixtures

Here are some commonly used built-in Playwright fixtures:

Fixtures

Usage

browser

Brower Instance (Chromium, Firefox, Webkit)

Context

Brower Context (A isolated browser session)

page

A single browser page (browser tab)

request

For sending request for API Testing


Using the Built-In page Fixture

Example Without Fixtures

import { chromium, expect } from '@playwright/test';
(async () => {
  const browser = await chromium.launch();
  const context = await browser.newContext();
  const page = await context.newPage();
  await page.goto('https://qafeast.com');
  await expect(page).toHaveTitle(/QA Feast/i);
  await browser.close();
})();


In this test, we manually:

     - Launch the browser
     - Create a context
     - Create a page
     - Close the browser

Same Test Using Playwright Fixtures

import { test, expect } from '@playwright/test';
test('basic page test', async ({ page }) => {
  await page.goto('https://qafeast.com');
  await expect(page).toHaveTitle(/QA Feast/i);
});


Here, Playwright:

     - Launches the browser
     - Creates the context and page
     - Cleans up automatically after the test

Why Fixtures Are Important

Without fixtures:

     - Repeated browser setup in every test
     - Hard-to-maintain test files
     - No centralized control over setup

With fixtures:

     - Clean and readable tests
     - Centralized setup logic
     - Automatic cleanup
     - Better scalability

Custom Fixtures in Playwright

When you need to set up logic to run before a test starts, you can create custom fixtures.

Common Use Cases

     - Login once and reuse the session
     - Shared test data
     - Page Object initialization
     - Environment setup

Creating Custom Fixtures

Step 1: Extend the test Class

import { test as base } from '@playwright/test';
export const test = base.extend({
  loggedInPage: async ({ page }, use) => {
    await page.goto('https://example.com/login');
    await page.fill('#username', 'testuser');
    await page.fill('#password', 'password123');
    await page.click('#login');
    await use(page); // run the test
    // optional teardown
  }
});


use() tells Playwright that the setup is complete and the test can now run.

Step 2: Use the Custom Fixture in a Test

import { test, expect } from './fixtures';
test('dashboard visible after login', async ({ loggedInPage }) => {
  await expect(loggedInPage.locator('#dashboard')).toBeVisible();
});


Playwright Fixture Lifecycle

Every fixture follows this order:

     1. Setup code runs
     2. use() passes control to the test
     3. Test executes
     4. Teardown code runs automatically

Fixture Scope

Fixtures can run:

     - Per test (default)
     - Once per worker

Worker-Scoped Fixture Example

export const test = base.extend({
  dbConnection: [async ({}, use) => {
    console.log('Connect DB');
    await use();
    console.log('Disconnect DB');
  }, { scope: 'worker' }]
});


Use worker scope for:

     - Database connections
     - Test servers
     - Expensive setup operations

Using Fixtures with Page Object Model (POM)

Fixtures work seamlessly with POM.

export const test = base.extend({
  homePage: async ({ page }, use) => {
    const homePage = new HomePage(page);
    await use(homePage);
  }
});


Test Code Becomes:

test('home page test', async ({ homePage }) => {
  await homePage.open();
  await homePage.verifyHeader();
});

 

 

Related Tutorials