Playwright Testing |
\n\nThis chapter guides you through writing and running your first Playwright test, helping you understand the basic structure and execution flow of tests.
\n\n\n\n
Running the Example Test
\n\nAfter initializing the project, run the auto-generated example test first to confirm everything is working correctly:
\n\n# Run all tests\nnpx playwright test\n\n\nAfter running, you will see output similar to the following:
\n\nRunning 6 tests using 4 workers\nβ 1 βΊ tests/example.spec.ts:3:1 βΊ has title (2.1s)\nβ 2 βΊ tests/example.spec.ts:10:1 βΊ get started link (1.8s)\nβ 3 βΊ tests/example.spec.ts:3:1 βΊ has title (1.9s)\nβ 4 βΊ tests/example.spec.ts:10:1 βΊ get started link (1.7s)\nβ 5 βΊ tests/example.spec.ts:3:1 βΊ has title (2.3s)\nβ 6 βΊ tests/example.spec.ts:10:1 βΊ get started link (2.0s)\n\n6 passed (12s)\n\n\nFrom the output, you can see: 2 tests were run on each of the 3 browsers, and all 6 tests passed.
\n\n\n\n
Creating Your First Test File
\n\nClear the contents of tests/example.spec.ts, and write a test from scratch.
Example
\n\n// File path: tests/first-test.spec.ts\n\nimport{ test, expect } from '@playwright/test';\n\n// test(name, callback) defines a test\n\n// name: test name, displayed in test reports\n\n// callback's parameter { page } is a fixture provided by Playwright\n\n test('Visit TUTORIAL homepage and check title', async ({ page })=>{\n\n// Navigate to the specified URL\n\n await page.goto('');\n\n// Assertion: page title contains "TUTORIAL"\n\n await expect(page).toHaveTitle(/TUTORIAL/);\n\n});\n\n\nRun this test:
\n\nnpx playwright test tests/first-test.spec.ts\n\n\nExpected output:
\n\nRunning 1 test using 1 worker\nβ 1 βΊ tests/first-test.spec.ts:4:1 βΊ Visit TUTORIAL homepage and check title (2.5s)\n\n1 passed (2.5s)\n\n\n\n\n
Understanding the test() Function
\n\ntest() is the core function of Playwright Test, used to define a test case.
Basic Syntax
\n\nExample
\n\nimport{ test, expect } from '@playwright/test';\n\n// test(test name, test function)\n\n test('Descriptive test name', async ({ page })=>{\n\n// Operations in the test\n\n await page.goto('https://example.com');\n\n// Assertions in the test\n\n await expect(page).toHaveTitle(/Example/);\n\n});\n\n\nParameter Description
\n\n| Parameter | \nType | \nDescription | \n
|---|---|---|
| First parameter (test name) | \nstring | \n Descriptive name of the test, displayed in test reports and logs | \n
| Second parameter (test function) | \nasync (fixtures) => {} | \n Asynchronous function containing the actual test logic | \n
\n\n
What Is the page Fixture?
\n\n{ page } is destructuring assignment in the test function parameter, extracting page from the fixtures object provided by Playwright.
page is a Page object representing a browser tab.
Each test has its own independent page instance:
| Fixture | \nType | \nDescription | \n
|---|---|---|
page | \n Page object | \nIndependent browser tab for navigation, interaction, and assertions | \n
context | \n BrowserContext object | \nBrowser context, managing cookies, storage, etc. | \n
browser | \n Browser object | \nBrowser instance, rarely used directly | \n
request | \n APIRequestContext object | \nUsed for sending HTTP requests (without a browser) | \n
The most commonly used fixture is page; most operations are performed through it.
\n\n
page.goto() Navigation
\n\npage.goto(url) is one of the most fundamental operations in Playwright, used to navigate to a specified URL.
Example
\n\n// Basic usage\n\n await page.goto('');\n\n// Navigation with options\n\n await page.goto('',{\n\n// Wait until the 'load' event fires (default)\n\n waitUntil:'load',\n\n// Timeout in milliseconds\n\n timeout:30000,\n\n// Referrer header\n\n referer:'https://www.google.com/',\n\n});\n\n\nThe waitUntil option has three possible values:
| Value | \nMeaning | \nUse Case | \n
|---|---|---|
'load' | \n Wait for the load event to fire | \n Default value, suitable for most pages | \n
'domcontentloaded' | \n Wait for the DOMContentLoaded event | \n When only the basic DOM structure needs to be loaded | \n
'networkidle' | \n Wait until the network is idle (no new requests within 500ms) | \nWhen all asynchronous data must be fully loaded | \n
\n\n\nIn most cases, the default
\n'load'is sufficient. Playwrightβs automatic waiting mechanism handles subsequent element availability, so'networkidle'is usually unnecessary.
\n\n
expect() Assertions
\n\nexpect() is Playwrightβs assertion method, used to verify whether test results match expectations.
Example
\n\n// Page title assertion\n\n await expect(page).toHaveTitle(/TUTORIAL/);\n\n// Page URL assertion\n\n await expect(page).toHaveURL('');\n\n// Element visibility assertion\n\n await expect(page.getByText('TUTORIAL')).toBeVisible();\n\n\nA key feature of Playwright assertions is automatic retry: if the assertion condition is temporarily not met, Playwright will keep retrying until the condition is satisfied or the timeout is reached.
\n\nThis means you do not need to write waitFor or sleep to wait for the page to be ready.
\n\n
Test async/await Pattern
\n\nAll Playwright operations are asynchronous, so test functions must be declared as async.
All browser operations (goto, click, fill, etc.) and assertions (expect) must use the await keyword.
Example
\n\n// Correct usage\n\n test('Correct example', async ({ page })=>{\n\n await page.goto('');\n\n await expect(page).toHaveTitle(/TUTORIAL/);\n\n});\n\n// Incorrect usage (missing await)\n\n test('Incorrect example', async ({ page })=>{\n\n page.goto('');// Missing await!\n\n expect(page).toHaveTitle(/TUTORIAL/);// Missing await!\n\n});\n\n\n\n\n\nIf you forget to add
\nawait, the test may assert at the wrong time, causing instability or unexpected passes. Always useawaitwhen calling Playwright APIs.
\n\n
Understanding Test Output
\n\nLetβs look at a test with a deliberate assertion failure to understand test output:
\n\nExample
\n\n// File path: tests/fail-demo.spec.ts\n\nimport{ test, expect } from '@playwright/test';\n\ntest('A deliberately failing test', async ({ page })=>{\n\n await page.goto('');\n\n// Assertion with non-existent text, expected to fail\n\n await expect(page).toHaveTitle(/Non-existent text/);\n\n});\n\n\nAfter running, the output will be roughly as follows:
\n\nRunning 1 test using 1 worker\nβ 1 βΊ tests/fail-demo.spec.ts:4:1 βΊ An intentionally failing test (5.2s)\n\n1 failed\n\ntests/fail-demo.spec.ts:4:1 βΊ An intentionally failing test\n\n\nMeanwhile, an HTML report will automatically open, showing detailed failure information and error screenshots.
YouTip