YouTip LogoYouTip

Playwright First Test

Playwright Testing |

\n\n

This 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\n

After 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\n

After running, you will see output similar to the following:

\n\n
Running 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\n

From 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\n

Clear the contents of tests/example.spec.ts, and write a test from scratch.

\n\n

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\n

Run this test:

\n\n
npx playwright test tests/first-test.spec.ts\n
\n\n

Expected output:

\n\n
Running 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\n

test() is the core function of Playwright Test, used to define a test case.

\n\n

Basic Syntax

\n\n

Example

\n\n
import{ 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\n

Parameter Description

\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
ParameterTypeDescription
First parameter (test name)stringDescriptive name of the test, displayed in test reports and logs
Second parameter (test function)async (fixtures) => {}Asynchronous function containing the actual test logic
\n\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.

\n\n

page is a Page object representing a browser tab.

\n\n

Each test has its own independent page instance:

\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
FixtureTypeDescription
pagePage objectIndependent browser tab for navigation, interaction, and assertions
contextBrowserContext objectBrowser context, managing cookies, storage, etc.
browserBrowser objectBrowser instance, rarely used directly
requestAPIRequestContext objectUsed for sending HTTP requests (without a browser)
\n\n

The most commonly used fixture is page; most operations are performed through it.

\n\n
\n\n

page.goto() Navigation

\n\n

page.goto(url) is one of the most fundamental operations in Playwright, used to navigate to a specified URL.

\n\n

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\n

The waitUntil option has three possible values:

\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
ValueMeaningUse Case
'load'Wait for the load event to fireDefault value, suitable for most pages
'domcontentloaded'Wait for the DOMContentLoaded eventWhen only the basic DOM structure needs to be loaded
'networkidle'Wait until the network is idle (no new requests within 500ms)When all asynchronous data must be fully loaded
\n\n
\n

In most cases, the default 'load' is sufficient. Playwright’s automatic waiting mechanism handles subsequent element availability, so 'networkidle' is usually unnecessary.

\n
\n\n
\n\n

expect() Assertions

\n\n

expect() is Playwright’s assertion method, used to verify whether test results match expectations.

\n\n

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\n

A 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\n

This means you do not need to write waitFor or sleep to wait for the page to be ready.

\n\n
\n\n

Test async/await Pattern

\n\n

All Playwright operations are asynchronous, so test functions must be declared as async.

\n\n

All browser operations (goto, click, fill, etc.) and assertions (expect) must use the await keyword.

\n\n

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

If you forget to add await, the test may assert at the wrong time, causing instability or unexpected passes. Always use await when calling Playwright APIs.

\n
\n\n
\n\n

Understanding Test Output

\n\n

Let’s look at a test with a deliberate assertion failure to understand test output:

\n\n

Example

\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\n

After running, the output will be roughly as follows:

\n\n
Running 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\n

Meanwhile, an HTML report will automatically open, showing detailed failure information and error screenshots.

← Playwright Test StructureFlask View Function Options Ap β†’