Your First Playwright Test
By Syncfusion®, Inc. · Last updated
The parts of a test (import, test(), the page fixture, page.goto()), writing a test that acts and checks, running tests from the command line in one file or one browser, headless and headed mode, reading results (passed, failed, flaky, skipped), the HTML report, and recording tests with Codegen.
Your First Playwright Test
- Now you will write a test yourself, line by line.
- Every Playwright test has the same small shape. Once you know it, you can read any test.
- Then you will run tests in different ways, read the results and record a test with Codegen.
Simple lesson: a test opens a page, does what a user does, and checks the result.
A Real-World Example
- Priya adds a "mark as done" feature to her to-do app.
- She wants a test for it: add a task, tick it, and check that the counter says 0 items left.
- Here is her test. Press ▶ Run tests, then open the Steps tab to see each action.
- What happened: the test typed a task, ticked its checkbox and checked the counter.
- The Steps tab lists each action with its time.
What You Will Learn
- The parts of a test.
- How to write a test that acts and checks.
- How to run all tests, one file, or one browser.
- Headless and headed mode.
- How to read the results and the HTML report.
- How to record a test with Codegen.
Anatomy of a Test
- Every test file has the same building blocks. The animation points at each one.
Animation: the parts of a test are highlighted one by one: the import line, test with its title, the page fixture, page.goto, an action, and an assertion
import test, expect from '@playwright/test'; test('has a title', async ( page ) => await page.goto('https://…'); await page.getByRole('link').click(); await expect(page).toHaveTitle(/Shop/); );
1. Import test and expect 2. test(title, body) 3. The page fixture 4. Open a page 5. Act like a user 6. Check the result
Six parts: import, test, page, goto, an action, and an assertion.
Importing test and expect
import { test, expect } from '@playwright/test';is the first line of almost every test file.testdeclares a test.expectchecks a result.
The test() Function
test('title', async ({ page }) => { ... })declares one test.- The title is a short sentence about what the test proves. It appears in every report.
- The body is an
asyncfunction. Playwright calls it when the test runs. - async = a function that can wait. Inside it,
awaitwaits for each step to finish.
The page Fixture (First Look)
{ page }asks Playwright for a page: a fresh browser tab, made just for this test.- Fixture = something Playwright prepares for your test and cleans up after it.
- You never start or close the browser yourself. Fixtures explains how this works.
Navigating with page.goto()
await page.goto(url)opens a web address and waits for the page to load.- Always
awaitit. Withoutawait, the test moves on before the page is there.
Test File Naming
- Playwright runs files whose names end in
.spec.tsor.test.ts(or.js). - Name the file after the feature it tests:
login.spec.ts,cart.spec.ts. - A file called
login.tsis not a test file. Playwright skips it.
await = "wait until this step is done". Every Playwright action and every web-first assertion returns a promise. Put await in front of each one.
Simple lesson: import, test(), { page }, page.goto(), then actions and checks.
Writing a Test
Writing a Simple Test
- The smallest useful test opens a page and checks one thing.
- This one opens the Practice Shop and checks the page title.
/Practice Shop/is a regular expression. It means "the title contains Practice Shop".- A plain string,
'Home | Practice Shop', would need the whole title to match.
Interacting with the Page and Adding an Assertion
- A real test does something, then checks the result.
- Below, the test searches the product list, then checks how many products are left.
- Assertion = a check that must be true. If it is false, the test fails.
- Good tests follow three steps: arrange (open the page), act (click, type), assert (check).
Simple lesson: open the page, act like a user, then assert what the user should see.
Running Tests
npx playwright test
npx playwright testruns every test file, in every browser listed in the config.- In the labs, the command line sits under the editor. You can edit it like a real terminal.
- Two files, two tests, three browsers: six results.
- Now change the command and run it again:
| Command | What it runs |
|---|---|
npx playwright test | Every test, in every project |
npx playwright test cart | Only files whose name contains cart |
npx playwright test tests/cart.spec.ts | One file |
npx playwright test --project=chromium | Every test, in Chromium only |
npx playwright test cart --project=firefox | One file, in Firefox only |
- Each browser in the config is a project. Playwright Configuration explains projects.
Headless vs Headed Mode
- Headless = the browser runs with no window. This is the default. It is fast and works on servers.
- Headed = you see the browser window. Add
--headedto watch your test run. - In the lab, the Browser tab always shows the page, so you can watch every run.
Reading Terminal Output
- Each line of the output is one test in one browser:
✓ 1 [chromium] › tests/cart.spec.ts:3:1 › adding a product updates the cart count (612ms)
✓= the result.1= the order.[chromium]= the project. Then the file, the line and column, the title and the time.
Passed, Failed, Flaky and Skipped
- Run this file. It has one test of each kind. The command adds
--retries=1, so a failed test gets one more try.
| Result | Mark | Meaning |
|---|---|---|
| Passed | ✓ | Every step worked and every check was true |
| Failed | ✘ | A step or a check failed, on every try |
| Flaky | ✘ then ✓ | It failed first, then passed on a retry. Something is unreliable |
| Skipped | - | The test did not run, because you told Playwright to skip it |
A flaky test is a warning, not a success. Find out why it failed the first time. Playwright Configuration shows how retries work.
Simple lesson: npx playwright test runs everything. Add a file name or --project to run less.
Viewing Results
Opening the HTML Report
- A new project uses the HTML reporter. After each run, it writes
playwright-report/index.html. npx playwright show-reportopens it in your browser.- When a test fails, the report opens by itself.
Sketch of an HTML report: filter tabs All, Passed, Failed, Flaky, Skipped, then a list of tests with their browser and time
Search tests
All 6 Passed 4 Failed 1 Flaky 1 Skipped 0
✘ checkout shows the totalchromium · cart.spec.ts:125.2s
± sync completesfirefox · sync.spec.ts:31.6s
✓ home page has the shop namewebkit · home.spec.ts:30.9s
Click a test to see its steps, its error and its trace.
A sketch of the HTML report. Filter by result, then open a test to see what happened.
- The lab shows the same facts in the Terminal and Steps tabs. Reporting covers the HTML report in depth.
Simple lesson: npx playwright show-report opens a clickable report of the last run.
Recording Tests with Codegen
- Codegen = a tool that writes test code while you click around a page.
- In a real project,
npx playwright codegen https://example.comopens two windows: a browser and the Inspector, which shows the code. - Try the practice version below. Add two tasks, tick one, then click Assert text and click the counter.
Codegen
Recording Actions and Assertions
- Every click, fill and key press becomes one line of code.
- The assertion buttons add checks: Assert visibility, Assert text and Assert value.
- Codegen picks good locators for you: roles, labels and test ids first.
Copying Generated Locators
- The Inspector also has a Pick locator button. Click any element, and it shows the best locator for it.
- Locators has a practice picker.
Codegen Options
| Option | Example | What it does |
|---|---|---|
--device | npx playwright codegen --device="iPhone 13" <url> | Records on an emulated phone |
--viewport-size | npx playwright codegen --viewport-size="800,600" <url> | Sets the window size |
--target | npx playwright codegen --target=python <url> | Writes code in another language |
--output | npx playwright codegen -o tests/new.spec.ts <url> | Saves the code to a file |
Cleaning Up Generated Tests
- Recorded code is a draft. Before you keep it:
- Give the test a real title. Codegen calls every test
'test'. - Delete extra clicks you made by accident.
- Add assertions. A test with no
expect()proves almost nothing. - Move repeated steps into a helper. Page Object Model shows how.
Limits of Generated Code
- Codegen records what you did, not why. It cannot know what result matters.
- It may pick a weak locator, such as one based on text that changes.
- Use it to start fast. Then edit the test like any code you write.
Codegen is great for learning. Record a flow, then read the code. You will learn locators quickly.
Simple lesson: Codegen writes a first draft. You add a title, assertions and clean-up.
Try It in Your Project
- These steps take the lesson from the lab to your own app.
- Record one flow of your app with
npx playwright codegen <your-url>. - Clean the recording: rename the test, replace weak locators, add a real assertion at the end.
- Run it headed once, then headless, and open the HTML report.
Simple lesson: use one idea from this lesson on your own app this week.
TL;DR
- A test has an import,
test(), thepagefixture,page.goto(), actions and assertions. - Put
awaitbefore every action and web-first assertion. - Test files end in
.spec.tsor.test.ts. npx playwright testruns everything. Add a file name or--projectto run less.- Results are passed, failed, flaky or skipped.
npx playwright show-reportopens the HTML report.npx playwright codegenrecords a draft test.
Common mistakes
| Mistake | What happens | Fix |
|---|---|---|
Forgetting await before page.goto() | The next step runs before the page loads | Put await before every Playwright call |
Naming the file login.ts | Playwright finds no tests in it | Name it login.spec.ts |
A test with no expect() | It passes even when the feature is broken | Add at least one assertion |
Keeping Codegen's test('test', ...) | Reports are full of tests called "test" | Give each test a clear title |
| Ignoring flaky tests | Real bugs hide behind retries | Fix the cause of the first failure |
Check Yourself
Exercises
What to Remember
- A test is: import,
test(),{ page },goto, act, assert. awaitevery Playwright call.- Run less with a file name or
--project. - Flaky means "unreliable", even if it passed in the end.
- Codegen gives you a draft. You add the meaning.
Next: Locators