Fixtures follow a specific lifecycle involving a setup phase, an await use() call, and a teardown phase. The execution order is governed by these rules:
- Dependency Order: If fixture A depends on fixture B, B is always set up before A and torn down after A.
- Lazy Execution: Non-automatic fixtures are executed lazily, meaning they are only set up when a test or hook explicitly requests them.
- Scoping:
- Test-scoped fixtures are torn down after each individual test.
- Worker-scoped fixtures are torn down only when the worker process executing the tests is shut down.
- Automatic Fixtures: Automatic fixtures (
auto: true) are set up before tests and hooks. Automatic worker fixtures are set up before anything else, while automatic test fixtures are set up before tests and beforeEach hooks.
import { test as base } from '@playwright/test';
const test = base.extend<{
testFixture: string,
autoTestFixture: string
}, {
workerFixture: string,
autoWorkerFixture: string
}>({
// Worker-scoped fixture
workerFixture: [async ({ browser }) => {
// setup
await use('workerFixture');
// teardown
}, { scope: 'worker' }],
// Automatic worker-scoped fixture
autoWorkerFixture: [async ({ browser }) => {
await use('autoWorkerFixture');
}, { scope: 'worker', auto: true }],
// Test-scoped fixture
testFixture: [async ({ page, workerFixture }) => {
await use('testFixture');
}, { scope: 'test' }],
// Automatic test-scoped fixture
autoTestFixture: [async () => {
await use('autoTestFixture');
}, { scope: 'test', auto: true }],
});