Skip to main content

Writing Tests

Playwright assertions are created specifically for the dynamic web. Checks are automatically retried until the necessary conditions are met. Playwright comes with auto-wait built in meaning it waits for elements to be actionable prior to performing actions. Playwright provides a test function to declare tests and the expect function to write assertions.

You will learn

The Example Test

Take a look at the example test included when installing Playwright to see how to write a test using locators and web first assertions.

import { test, expect } from '@playwright/test';

test('homepage has Playwright in title and get started link linking to the intro page', async ({ page }) => {
await page.goto('');

// Expect a title "to contain" a substring.
await expect(page).toHaveTitle(/Playwright/);

// create a locator
const getStarted = page.getByRole('link', { name: 'Get started' });

// Expect an attribute "to be strictly equal" to the value.
await expect(getStarted).toHaveAttribute('href', '/docs/intro');

// Click the get started link.

// Expects the URL to contain intro.
await expect(page).toHaveURL(/.*intro/);

Add // @ts-check at the start of each test file when using JavaScript in VS Code to get automatic type checking.


Playwright Test uses the expect library for test assertions which provides matchers like toEqual, toContain, toMatch, toBe and many more. Playwright also extends this library with convenience async matchers that will wait until the expected condition is met.

await expect(page).toHaveTitle(/Playwright/);


Locators are the central piece of Playwright's auto-waiting and retry-ability. Locators represent a way to find element(s) on the page at any moment and are used to perform actions on elements such as .click .fill etc.

const getStarted = page.getByRole('link', { name: 'Get started' });

await expect(getStarted).toHaveAttribute('href', '/docs/installation');

Test Isolation

Playwright Test is based on the concept of test fixtures such as the built in page fixture, which is passed into your test. Pages are isolated between tests due to the Browser Context, which is equivalent to a brand new browser profile, where every test gets a fresh environment, even when multiple tests run in a single Browser.

test('basic test', async ({ page }) => {

Using Test Hooks

You can use various test hooks such as test.describe to declare a group of tests and test.beforeEach and test.afterEach which are executed before/after each test. Other hooks include the test.beforeAll and test.afterAll which are executed once per worker before/after all tests.

import { test, expect } from "@playwright/test";

test.describe("navigation", () => {
test.beforeEach(async ({ page }) => {
// Go to the starting url before each test.
await page.goto("");

test("main navigation", async ({ page }) => {
// Assertions use the expect API.
await expect(page).toHaveURL("");

What's Next