Fixtures in Playwright [2026]

Learn about the importance of Playwright fixtures. Use BrowserStack Automate to run Playwright Tests on real devices & browsers.

Fixtures in Playwright
Home Guide Fixtures in Playwright [2026]

Fixtures in Playwright [2026]

I used to think Playwright test failures mostly came from flaky waits or unstable environments. But after digging into repeated CI failures, a different pattern stood out: the issues were rooted in how test setup and state were managed.

Playwright wasn’t the problem—test structure was. Once fixtures replaced duplicated setup, shared globals, and ad-hoc hooks, stability improved fast.

In this article, I’ll explain how Playwright fixtures actually work and how using them correctly makes test suites predictable, faster, and easier to scale.

What are Fixtures in Playwright?

Playwright Fixtures pertain to the concept of Test Fixtures.

A test fixture is a fixed state of a set of objects used as a base for running tests. It sets up the system for testing by yielding the initialization code, such as loading up a database with defined parameters from a site before running the test.

Why are Playwright Fixtures important?

Playwright fixtures are important because they control how tests are initialized, isolated, reused, and scaled, directly impacting reliability, execution speed, and maintainability as test suites grow.

  • Ensure every test starts from a clean and predictable state with guaranteed setup and teardown
  • Prevent state leakage when running tests in parallel across browsers and environments
  • Eliminate repeated setup logic by centralizing common test initialization
  • Make test dependencies explicit, improving readability and debugging
  • Reduce flaky test failures caused by shared state or improper cleanup
  • Optimize execution time by reusing expensive setup through worker-scoped fixtures
  • Provide consistent behavior across local runs and CI pipelines

Types of Playwright Fixtures

In Playwright, fixtures are categorized based on how they are scoped, created, and executed rather than by explicit “fixture types” as a framework concept.

Built-in Playwright Fixtures

These fixtures are provided out of the box by Playwright Test and cover core browser and test execution needs. They are automatically available in every test without extra configuration.

Key built-in fixtures include:

  • browser – A shared browser instance used across contexts.
  • context – An isolated browser context created per test.
  • page – A fresh page instance created from the context.
  • request – APIRequestContext for API testing.
  • browserName – Indicates the current browser under execution.
  • testInfo – Metadata about the running test such as retries, status, and output paths.

Built-in fixtures are designed for safe parallel execution and reset automatically between tests, making them reliable defaults for most scenarios.

Custom Fixtures

Custom fixtures are user-defined extensions created using test.extend() to encapsulate reusable setup and teardown logic.

Common use cases:

  • Authentication and logged-in sessions
  • Test data setup and cleanup
  • Initializing helpers or utilities
  • Managing feature flags or environment state

Custom fixtures allow teams to move complex setup logic out of test files, improving readability and maintainability while keeping tests declarative.

Test-Scoped Fixtures

Test-scoped fixtures are created and destroyed for every individual test.

Characteristics:

  • Maximum isolation between tests
  • Safe for mutable state
  • Slightly higher execution cost due to repeated setup

Typical examples:

  • Creating a new logged-in page per test
  • Seeding test data that must not be shared
  • Initializing mocks or spies

Test-scoped fixtures are the default scope in Playwright and are preferred when correctness and isolation matter more than execution speed.

Worker-Scoped Fixtures

Worker-scoped fixtures are created once per worker process and reused across multiple tests running in that worker.

Characteristics:

  • Faster execution for heavy setup
  • Shared state across tests in the same worker
  • Requires careful handling to avoid test coupling

Typical examples:

  • Database connections
  • Preloaded authentication tokens
  • Large test datasets
  • Expensive service initialization

Worker-scoped fixtures are especially useful in large test suites running in parallel where repeated setup becomes a bottleneck.

Auto Fixtures

Auto fixtures are fixtures that execute automatically without being explicitly referenced in a test.

Key behavior:

  • Enabled using auto: true
  • Runs for every test within scope
  • Useful for global setup or enforcement logic

Common use cases:

  • Global cleanup routines
  • Environment validation
  • Attaching logs or traces
  • Enforcing test preconditions

Auto fixtures should be used sparingly, as they can introduce hidden dependencies that make tests harder to reason about.

Extended Built-in Fixtures

These fixtures are created by extending existing Playwright fixtures such as page or context to customize their behavior.

Examples include:

  • A page fixture that always starts in an authenticated state
  • A context fixture with predefined permissions
  • A page fixture with network mocking enabled

This approach is preferred over duplicating setup logic in multiple tests and ensures consistent behavior across the test suite.

Shared Fixtures (Centralized Fixtures)

Shared fixtures are custom fixtures defined in a separate fixtures file and imported across multiple spec files or projects.

Benefits:

  • Consistent setup across large repositories
  • Easier maintenance and refactoring
  • Cleaner test files with minimal boilerplate

Shared fixtures are essential when scaling Playwright across teams, applications, or multiple environments.

Parameterized Fixtures

Parameterized fixtures accept configuration or runtime data to alter their behavior.

Common use cases:

  • Role-based authentication (admin, user, guest)
  • Region- or locale-specific setup
  • Feature-flag-driven test execution

Parameterized fixtures reduce duplication by allowing a single fixture to support multiple test variations without branching logic inside tests.

Fixture Lifecycle

The Playwright fixture lifecycle follows a strict and predictable execution model that determines when fixtures are initialized, resolved, injected, and torn down. Understanding these steps is critical for debugging setup failures and designing reliable fixture hierarchies.

  • Playwright parses the test file and identifies all fixtures required by the test based on the test function parameters.
  • The fixture dependency graph is resolved, ensuring that fixtures required by other fixtures are initialized first.
  • Worker-scoped fixtures begin setup once per worker process before any test in that worker starts.
  • Test-scoped fixtures begin setup immediately before the individual test runs.
  • For each fixture, setup logic executes until the await use(value) call is reached.
  • The resolved fixture value is injected into the test or dependent fixture.
  • Once all required fixtures are resolved, the test body starts execution.
  • If a fixture throws an error during setup, the test is marked as a setup failure and the test body is skipped.
  • After the test completes, teardown begins for test-scoped fixtures.
  • Teardown logic executes after the use() call finishes, even if the test fails or times out.
  • Teardown runs in reverse order of fixture initialization to ensure dependent resources are cleaned safely.
  • Once all tests in a worker complete, worker-scoped fixture teardown executes.
  • Final cleanup runs before the worker process exits, releasing shared resources.

This lifecycle guarantees deterministic setup, explicit dependency resolution, and reliable cleanup, making fixture-related failures easier to isolate and diagnose in both local and CI executions.

When to use Playwright Fixtures?

Playwright Fixtures are especially useful when:

  • Repeating test setups across multiple test cases.
  • Needing to establish consistent conditions (e.g., logins, API states) for various tests.
  • Simplifying teardown processes after test execution.

Steps to Implement Fixtures in Playwright

Creating a Playwright fixture is straightforward and significantly aids in reusing functions.

Below are the detailed steps for implementing them.

Creation of Custom fixture in a test file

To create a new fixture file loginFixture.ts for a custom fixture, first import the Playwright test as baseTest.

import { test as baseTest } from '@playwright/test';

// Define custom fixture

const test = baseTest.extend<{loggedInPage: any;}>({

 loggedInPage: async ({ page }, use) => {

   // Go to the login page

   await page.goto('https://www.bstackdemo.com/signin'); // Replace with login URL

   // Fill in login details

   await page.locator('id=username').click(); // click on the username field

   await page.locator('#react-select-2-option-0-0').click(); // click the first option

   await page.locator('id=password').click(); // click on the password field

   await page.locator('#react-select-3-option-0-0').click(); // click the first option

   await page.click('button[type="submit"]');

   // Make the logged-in page available for tests

   await use(page);

 }

});

export { test };

A variable test will be defined at this stage by extending the base test. Inside the extend method, the loggedInPage fixture will be used as the key, with an anonymous function as the value, where use will serve as the second parameter.

const test = baseTest.extend<{loggedInPage: any;}>({

 loggedInPage: async ({ page }, use) => {

// }

The next block features a simple test that navigates to https://www.bstackdemo.com/signin, selects the username and password, and logs into the application.

// Go to the login page

   await page.goto('https://www.bstackdemo.com/signin'); // Replace with your login URL

   // Fill in login details

   await page.locator('id=username').click(); // click on the username field

   await page.locator('#react-select-2-option-0-0').click(); // click the first option

   await page.locator('id=password').click(); // click on the password field

   await page.locator('#react-select-3-option-0-0').click(); // click the first option

   await page.click('button[type="submit"]');

   // Wait for navigation to complete after login

   await page.waitForNavigation();

This line will make the page available for all the tests.

await use(page);

Using Fixtures in the spec file

A new spec file named login.spec.ts will be created, with a reference to loggedInPage. Since this page is already logged in, it enables testing of other application functionalities without the need to repeat the login process.

import { test } from '../fixtures/loginFixture';

test('should navigate to the dashboard after login', async ({ loggedInPage }) => {

 // Now we're logged in, so we can go to the dashboard

 await loggedInPage.goto('https://www.bstackdemo.com/');

});

Best Practices of Using Fixtures in Playwright

Here are some best practices when using Playwright fixtures.

1. Test on real devices

  • Playwright fixtures are useful in creating and defining reusable and consistent steps for a process flow, such as Login, authentication, and API mocking.
  • BrowserStack allows access to real device cloud platform with over 3500+ different device, browsers, and OS combinations and browsers, ensuring that Playwright Fixtures run in real user conditions rather than virtual environments.
  • This helps early identification of device-oriented bugs.

For example, login fixtures can be used to automate all devices and browsers in a single instance, ensuring that the login functionality operates efficiently.

Talk to an Expert

2. Cross-Browser and Cross-Platform Support

  • BrowserStack enables the execution of Playwright tests across various devices, browsers, and operating system combinations.
  • Adapting Playwright fixtures ensures that test steps remain flexible and reusable across different combinations.
  • This allows for the same test steps to be executed in multiple browsers, including Chrome, Firefox, Safari, and Edge, across various versions.

3. CI/CD Integration

  • BrowserStack integrates flawlessly with CI/CD tools such as GitHub Actions, Jenkins, and CircleCI. The tests can be run in a clean and isolated environment by configuring Playwright Fixtures.
  • Automating the Playwright tests on BrowserStack after every build will help ensure the application is validated and tested in real-world scenarios.

For example: Automating the tests with BrowserStack through parallel testing in GitHub Actions will make sure that on every deployment, the test cases are run across real device.

Try BrowserStack for Free

Playwright Fixture Scope

Fixture scope defines how long a fixture exists and how frequently it is created during a test run. It directly affects test isolation, execution speed, and reliability, especially when tests run in parallel.

Test-scoped fixtures: Test-scoped fixtures represent resources that are created specifically for a single test and discarded immediately after that test completes.

  • Created fresh for each individual test
  • Teardown runs immediately after the test finishes
  • Provide strong isolation and prevent shared state issues
  • Suitable for mutable resources such as pages, sessions, cookies, and test data
  • Higher execution cost when setup is expensive

Worker-scoped fixtures: Worker-scoped fixtures represent shared resources that live for the entire lifetime of a worker process and are reused across multiple tests.

  • Created once per worker process
  • Shared across all tests running in the same worker
  • Teardown runs after all worker tests complete
  • Ideal for expensive or read-only setup operations
  • Requires careful state management to avoid cross-test interference

Scope behavior in parallel execution: Scope behavior determines how fixtures are instantiated when tests run concurrently across multiple workers.

  • Test-scoped fixtures are isolated across all parallel tests
  • Worker-scoped fixtures are isolated per worker, not per test
  • Increasing worker count multiplies worker-scoped fixture instances
  • Incorrect scope selection often leads to flaky tests in CI environments

Choosing the right fixture scope: Choosing the correct fixture scope is a design decision that balances isolation, performance, and maintainability.

  • Use test scope when correctness and independence are critical
  • Use worker scope when setup cost is high and state can be safely shared
  • Avoid mixing scopes without clear ownership to prevent hidden dependencies

Fixtures vs Hooks

Fixtures and hooks both manage setup and teardown in Playwright, but they differ in how setup is declared, scoped, and executed. Fixtures are dependency-driven and explicit, while hooks are implicit and tied to file or block structure. This distinction becomes critical as test suites scale and run in parallel.

AspectPlaywright FixturesPlaywright Hooks
PurposeProvide explicit, reusable setup units injected into testsRun lifecycle callbacks before or after tests
DeclarationDeclared as test dependencies via function parametersDeclared using beforeEach, afterEach, beforeAll, afterAll
VisibilityTest dependencies are visible in the test signatureSetup logic is hidden inside hooks
Scope controlSupport test and worker scopesLimited to file or describe block scope
Parallel safetyDesigned for parallel execution by defaultCan accidentally share state across tests
ReusabilityEasily shared across files and projectsTightly coupled to test file structure
Execution behaviorRuns only when the fixture is requiredRuns for every test in its scope
Failure reportingSetup failures are clearly reported before test runsFailures often appear as test failures
Dependency supportFixtures can depend on other fixturesNo native dependency graph
Performance optimizationWorker-scoped fixtures reduce repeated setupNo equivalent mechanism for shared setup
ScalabilitySuitable for large, modular test suitesBecomes hard to maintain at scale

Fixtures are the preferred approach for reusable, scalable, and parallel-safe setup logic, while hooks are best limited to simple, file-specific initialization that does not need reuse or scope control.

How BrowserStack Automate Can Enhance Playwright Tests

BrowserStack Automate offers various functionalities for running the tests on multiple devices and parallelism.

Here are a few advantages of using BrowserStack Automate in Playwright tests:

  • Reduce the time taken for execution – Parallel execution allows to run multiple test cases in parallel. With BrowserStack Automate, many number of tests can be run in parallel across different devices and browsers.
  • Cross Browser and Cross device execution – BrowserStack Automate helps to run multiple tests simultaneously across various devices and OS combinations, thus giving the leverage of efficiency in testing the application.
  • Scalability – BrowserStack is scalable to many devices and can spin up as many browser combinations as possible with the any additional maintenance.
  • Cost efficient – BrowserStack Automate is cost-effective in the longer term in case of maintenance of the tests.
  • CI/CD Integration – Tests can be integrated in the CI/CD process through BrowserStack, which is optimal for continuous testing and integration.

Do flaky Playwright tests start with poor setup?

Stabilize fixture-driven Playwright tests on real browsers using BrowserStack Automate.
Playwright Banner

Useful Playwright Resources

Tool Comparisons:

Tags
Automation Frameworks Automation Testing Playwright Real Device Cloud
Do flaky Playwright tests start with poor setup?
Stabilize fixture-driven Playwright tests on real browsers using BrowserStack Automate.

Get answers on our Discord Community

Join our Discord community to connect with others! Get your questions answered and stay informed.

Join Discord Community
Discord