Back to Home

Mastering Playwright Fixtures: Built-in vs Custom

Faruk Hasan
September 7, 2025
6 min read

In this tutorial, we’ll dive into one of Playwright’s most powerful concepts: fixtures. We’ll explore both the built-in fixtures (like browser, context, page) and see how to create a custom fixture for signup. Fixtures allow you to avoid boilerplate, keep tests clean, and ensure a consistent test setup and teardown.

What is a Fixture?

A fixture is a ready-made object that Playwright sets up before your test runs and cleans up after the test finishes. Think of it as “hidden setup code” that saves you from launching browsers or creating contexts manually.

Playwright automatically provides:

Example: Built-in Fixture

import { test, expect } from "@playwright/test"; test("visit Google", async ({ page }) => { await page.goto("https://www.google.com"); await expect(page).toHaveTitle(/Google/); });

Notice how we didn’t explicitly create browser or context. Playwright’s built-in fixtures handle that automatically:

When to Use Custom Fixtures

Built-ins are great, but sometimes you need extra setup for every test: signing up, logging in, preloading data, or navigating to a specific page. Instead of repeating that in every test, you can define a custom fixture.

Step 1: Create a Fixture File

import { test as base, expect, Page } from "@playwright/test"; type MyFixtures = { signedUpPage: Page; }; const test = base.extend({ signedUpPage: async ({ page }, use) => { await page.goto("https://faruk-hasan.com/automation/signup.html"); await page.locator("#username").fill("myUser"); await page.locator("#email").fill("test@example.com"); await page.locator("#password").fill("Password123!"); await page.locator("#confirmPassword").fill("Password123!"); await page.getByRole("button", { name: "Sign Up" }).click(); await use(page); // hands signed-up page to tests }, }); export { test, expect };

Key points:

Step 2: Write a Test Using the Custom Fixture

import { test, expect } from "./fixtures"; test("login page loads correctly", async ({ signedUpPage }) => { await signedUpPage.waitForTimeout(5000); // just to observe await expect(signedUpPage).toHaveTitle("Login - Automation Practice"); });

Here, signedUpPage is already prepared by the fixture — no need to repeat signup steps. The test simply checks that the login page loads correctly after signup.

Why This Matters

GitHub Repository

You can explore the full project and run it yourself:

View on GitHub: custom_fixture_playwright
git clone https://github.com/faruklmu17/custom_fixture_playwright.git

Watch the Full Walkthrough

Everything above is explained step-by-step in my video tutorial: Watch on YouTube

Have questions or want a follow-up on advanced fixtures? Reach out—I love helping QAs and devs level up with Playwright.