test() function signature - basic declaration
The test() function declares a test with the signature: test(title, body) or test(title, details, body). The title is a string, details is optional and contains tag, annotation, and lock properties, and body is a function taking Fixtures and optional TestInfo.
Test details object structure
The details parameter in test(title, details, body) accepts an object with properties: tag (string or array of strings), annotation (object or array of objects with type string and optional description string), and lock (string or array of strings).
Test.afterEach hook signature
Test.afterEach() declares a hook executed after each test. Signature: test.afterEach(hookFunction) or test.afterEach(title, hookFunction). The hookFunction takes one or two arguments: an object with fixtures and optional TestInfo.
Test.beforeEach hook signature
Test.beforeEach() declares a hook executed before each test. Signature: test.beforeEach(hookFunction) or test.beforeEach(title, hookFunction). The hookFunction takes one or two arguments: an object with fixtures and optional TestInfo.
Test.describe group signature
Test.describe() declares a group of tests. Signatures: test.describe(title, callback), test.describe(callback), or test.describe(title, details, callback). The callback is a function run immediately. The optional details parameter matches the structure used in test().
Test.describe.configure execution modes
Test.describe.configure() configures execution mode with mode option accepting 'default', 'parallel', or 'serial'. Also accepts retries (int) and timeout (int in milliseconds) options. Mode: 'default' runs tests sequentially with independent retries; 'parallel' runs tests concurrently; 'serial' runs tests sequentially and skips remaining tests if one fails.
Test.describe.fixme() marks tests as fixme
Test.describe.fixme() declares a group of tests marked as 'fixme' that will not be executed. Signatures: test.describe.fixme(title, callback), test.describe.fixme(callback), or test.describe.fixme(title, details, callback).
Test.describe.only() focuses a group
Test.describe.only() declares a focused group of tests. If there are focused tests or suites, only they will run. Signatures: test.describe.only(title, callback), test.describe.only(callback), or test.describe.only(title, details, callback).
Test.describe.parallel.only() focuses parallel group (discouraged)
Test.describe.parallel.only() declares a focused group of tests to run in parallel. Marked as discouraged; Test.describe.configure() is preferred. Signatures: test.describe.parallel.only(title, callback), test.describe.parallel.only(callback), or test.describe.parallel.only(title, details, callback).
Test.describe.serial() runs tests sequentially (discouraged)
Test.describe.serial() declares a group of tests to run serially. If one fails, subsequent tests are skipped. Marked as discouraged. Signatures: test.describe.serial(title, callback), test.describe.serial(title), or test.describe.serial(title, details, callback).
Test.describe.serial.only() focuses serial group (discouraged)
Test.describe.serial.only() declares a focused group of tests to run serially. Marked as discouraged. Signatures: test.describe.serial.only(title, callback), test.describe.serial.only(title), or test.describe.serial.only(title, details, callback).
Test.describe.skip() skips a group
Test.describe.skip() declares a skipped group of tests that will never run. Signatures: test.describe.skip(title, callback), test.describe.skip(title), or test.describe.skip(title, details, callback).
Test.expect property
Test.expect is an object that provides the expect function for creating test assertions. It can be used as test.expect(page).toHaveTitle('Title').
Test.extend() method returns Test
Test.extend() extends the test object by defining fixtures and/or options. It accepts a fixtures parameter as an object containing fixture and option definitions, and returns a Test object.
Test.abort() method signature
Test.abort() aborts the currently running test by throwing an error. Signature: test.abort(message?). The message parameter is optional string describing the abort reason.
Test.fail() declares failing test
Test.fail() marks a test as 'should fail' - Playwright ensures it fails. Declarations: test.fail(title, body), test.fail(title, details, body). Runtime: test.fail(condition, description), test.fail(callback, description), or test.fail(). The condition is boolean, callback returns boolean based on fixtures.
Test.fail.only() focuses a failing test
Test.fail.only() focuses on a specific test expected to fail. Signatures: test.fail.only(title, body) or test.fail.only(title, details, body).
Test.fixme() marks test for fixing
Test.fixme() marks a test as 'fixme' - Playwright will not run past the call. Declarations: test.fixme(title, body), test.fixme(title, details, body). Runtime: test.fixme(condition, description), test.fixme(callback, description), or test.fixme().
Test.info() returns TestInfo
Test.info() returns information about the currently running test. It returns TestInfo and can only be called during test execution. Example usage: test.info().attach('screenshot', { body: await page.screenshot(), contentType: 'image/png' }).
Test.only() focuses a test
Test.only() declares a focused test. If there are focused tests or suites, only they run. Signatures: test.only(title, body) or test.only(title, details, body).
Test.setTimeout() method signature
Test.setTimeout() changes the timeout for the test. Signature: test.setTimeout(timeout). The timeout parameter is an int in milliseconds. Zero means no timeout.
Test.skip() skips a test at runtime
Test.skip() skips a test - Playwright will not run past the call. Declarations: test.skip(title, body), test.skip(title, details, body). Runtime: test.skip(condition, description), test.skip(callback, description), or test.skip().
Test.slow() marks test as slow
Test.slow() marks a test as 'slow', giving it triple the default timeout. Signatures: test.slow(), test.slow(condition, description), or test.slow(callback, description). Cannot be used in beforeAll or afterAll hooks.
Test.step() declares test step
Test.step() declares a test step shown in the report. Signature: await test.step(title, body, options?). Returns the value returned by the step callback. Parameters: title (string), body (function receiving TestStepInfo returning Promise<any>). Options: box (boolean, defaults false), location (Location), timeout (float in milliseconds, defaults 0).
Test.step.skip() skips a test step
Test.step.skip() marks a test step as skipped and does not execute it. Signature: await test.step.skip(title, body, options?). Parameters: title (string), body (function returning Promise<any>). Options: box (boolean), location (Location), timeout (float in milliseconds).
Test.use() specifies options or fixtures
Test.use() specifies options or fixtures for a test file or describe group. Signature: test.use(options). The options parameter is a TestOptions object. Can also provide a function that overrides a fixture. Cannot be called within beforeEach or beforeAll.
Test tags must start with @ symbol
Test tags are declared in the tag property of test details and each tag must start with the @ symbol. Tags can be provided as a string or array of strings. Tags are displayed in test reports and available via TestCase.tags property.
Test annotations structure
Test annotations are provided in the annotation property of test details as an object or array of objects with type (string, required) and description (string, optional). Annotations are displayed in test reports and available via TestCase.annotations property, and can be added at runtime via TestInfo.annotations.
Test locks prevent concurrent execution
Tests that share a lock name never run concurrently, even when declared in different files or projects. Locks are provided as string or array of strings in the lock property of test details. Useful when tests access shared resources that do not support concurrent access.
Worker process restart on test failures affects afterAll hooks
The worker process is restarted on test failures, and afterAll hooks run again in the new worker. Multiple afterAll hooks run in order of registration. Playwright continues running all applicable hooks even if some fail.
Multiple beforeEach hooks run in registration order
When multiple beforeEach hooks are added, they run in the order of their registration. Playwright continues running all applicable hooks even if some fail.
Parallel tests execute in separate processes
Tests declared in test.describe.parallel() execute in separate processes and cannot share state or global variables. Each parallel test executes all relevant hooks.
Test.step box option for error reporting
When box option is true in Test.step(), errors thrown from step internals point to the step call site instead of the exact action that failed. Defaults to false.
Test.step returns step callback return value
Test.step() returns the value returned by the step callback, allowing steps to return data for use in tests.
Test.describe.configure applies to entire scope
Configuration via Test.describe.configure() applies to the entire scope regardless of whether it runs before or after test declarations.
Test example with basic structure
import { test, expect } from '@playwright/test';
test('basic test', async ({ page }) => {
await page.goto('https://playwright.dev/');
const name = await page.innerText('.navbar__title');
expect(name).toBe('Playwright');
});
Test tags example
import { test, expect } from '@playwright/test';
test('basic test', {
tag: '@smoke',
}, async ({ page }) => {
await page.goto('https://playwright.dev/');
});
test('another test @smoke', async ({ page }) => {
await page.goto('https://playwright.dev/');
});
Test annotations example
import { test, expect } from '@playwright/test';
test('basic test', {
annotation: {
type: 'issue',
description: 'https://github.com/microsoft/playwright/issues/23180',
},
}, async ({ page }) => {
await page.goto('https://playwright.dev/');
});
Test locks example
import { test, expect } from '@playwright/test';
test('update user settings', {
lock: 'user-settings',
}, async ({ page }) => {
// This test never runs concurrently with other tests
// that declare the 'user-settings' lock.
});
Test.afterAll example
test.afterAll(async () => {
console.log('Done with tests');
});
test.afterAll('Teardown', async () => {
console.log('Done with tests');
});
Test.afterEach example
import { test, expect } from '@playwright/test';
test.afterEach(async ({ page }) => {
console.log(`Finished ${test.info().title} with status ${test.info().status}`);
if (test.info().status !== test.info().expectedStatus)
console.log(`Did not run as expected, ended up at ${page.url()}`);
});
test('my test', async ({ page }) => {
// ...
});
Test.beforeAll example
import { test, expect } from '@playwright/test';
test.beforeAll(async () => {
console.log('Before tests');
});
test.afterAll(async () => {
console.log('After tests');
});
test('my test', async ({ page }) => {
// ...
});
Test.beforeEach example
import { test, expect } from '@playwright/test';
test.beforeEach(async ({ page }) => {
console.log(`Running ${test.info().title}`);
await page.goto('https://my.start.url/');
});
test('my test', async ({ page }) => {
expect(page.url()).toBe('https://my.start.url/');
});
Test.describe example
test.describe('two tests', () => {
test('one', async ({ page }) => {
// ...
});
test('two', async ({ page }) => {
// ...
});
});
Test.describe anonymous group example
test.describe(() => {
test.use({ colorScheme: 'dark' });
test('one', async ({ page }) => {
// ...
});
test('two', async ({ page }) => {
// ...
});
});
Test.describe with tags example
import { test, expect } from '@playwright/test';
test.describe('two tagged tests', {
tag: '@smoke',
}, () => {
test('one', async ({ page }) => {
// ...
});
test('two', async ({ page }) => {
// ...
});
});
Test.describe.configure parallel mode example
test.describe.configure({ mode: 'parallel' });
test('runs in parallel 1', async ({ page }) => {});
test('runs in parallel 2', async ({ page }) => {});
Test.describe.configure default mode example
test.describe.configure({ mode: 'default' });
test('runs first', async ({ page }) => {});
test('runs second', async ({ page }) => {});
Test.describe.configure serial mode example
test.describe.configure({ mode: 'serial' });
test('runs first', async ({ page }) => {});
test('runs second', async ({ page }) => {});
Test.describe.configure retries and timeout example
test.describe.configure({ retries: 2, timeout: 20_000 });
test('runs first', async ({ page }) => {});
test('runs second', async ({ page }) => {});
Test.describe.configure nested describes example
test.describe.configure({ mode: 'parallel' });
test.describe('A, runs in parallel with B', () => {
test.describe.configure({ mode: 'default' });
test('in order A1', async ({ page }) => {});
test('in order A2', async ({ page }) => {});
});
test.describe('B, runs in parallel with A', () => {
test.describe.configure({ mode: 'default' });
test('in order B1', async ({ page }) => {});
test('in order B2', async ({ page }) => {});
});
Test.describe.fixme example
test.describe.fixme('broken tests that should be fixed', () => {
test('example', async ({ page }) => {
// This test will not run
});
});
test.describe.fixme(() => {
// ...
});
Test.describe.only example
test.describe.only('focused group', () => {
test('in the focused group', async ({ page }) => {
// This test will run
});
});
test('not in the focused group', async ({ page }) => {
// This test will not run
});
Test.describe.parallel.only example
test.describe.parallel.only('group', () => {
test('runs in parallel 1', async ({ page }) => {});
test('runs in parallel 2', async ({ page }) => {});
});
Test.describe.serial.only example
test.describe.serial.only('group', () => {
test('runs first', async ({ page }) => {
});
test('runs second', async ({ page }) => {
});
});
Test.describe.skip example
test.describe.skip('skipped group', () => {
test('example', async ({ page }) => {
// This test will not run
});
});
test.describe.skip(() => {
// ...
});
Test.expect usage example
test('example', async ({ page }) => {
await test.expect(page).toHaveTitle('Title');
});
Test.extend fixture and option example
import { test as base } from '@playwright/test';
import { TodoPage } from './todo-page';
export type Options = { defaultItem: string };
export const test = base.extend<Options & { todoPage: TodoPage }>({
defaultItem: ['Do stuff', { option: true }],
todoPage: async ({ page, defaultItem }, use) => {
const todoPage = new TodoPage(page);
await todoPage.goto();
await todoPage.addToDo(defaultItem);
await use(todoPage);
await todoPage.removeAll();
},
});
import { test } from './my-test';
test('test 1', async ({ todoPage }) => {
await todoPage.addToDo('my todo');
});
Test.abort example
import { test, expect } from '@playwright/test';
test('does not publish to shared page', async ({ page }) => {
await page.route('**/publish', route => {
test.abort('Tests must not publish to the shared page. Use the `clone` option.');
return route.abort();
});
});
Test.fail declared example
import { test, expect } from '@playwright/test';
test.fail('not yet ready', async ({ page }) => {
// ...
});