This post was originally published on the Learn Playwright blog. Reference the original post to get the most updated version of this content.
🔖 | Today's Resources
- Getting Started guide - let's wrap it up!
- Auto-waiting - and why it improves test reliability.
- Web-First Assertions - and retries till expected condition is met
- Test Fixtures - and why it helps parallelization.
- Test Hooks - for just-in-time resource setup and teardown
- Introduction to Playwright Test runner - for video walkthrough of concepts
🎯 Day 2 Objectives: #30DaysOfPlaywright!!
Our Day 1 exploration of Playwright helped us setup and validate our local testing envrionment. Today we'll complete the tutorial by reviewing fundamental Playwright concepts namely:
- Writing assertions - to test if an expect-ed behavior holds true.
- Using test fixtures - to set desired page/browser context for test run.
- Using test hooks - to setup and tear down resources between tests.
We'll quickly go over what each does and why we need them - and revisit each topic for a deeper dive in a future post. Let's get started!
1. Playwright Fundamentals
In my kickoff post I recommended the Introduction to Playwright Test runner talk as a good introduction to Playwright fundamentals. Today we'll reference it in the context of various sections of the Getting Started guide.
Here's a handy list of segments with direct links to the relevant section of the talk, for convenience. I recommend you check out at least Ch 1-3 for today.
- What is Playwright Test?
- Why create another Test runner?
- Ch 1: Get Started - Demo - Playwright Test demo
- Ch 1: Get Started - Script - Unpack Test script
- Ch 2: Fundamentals - Test Isolation, Auto Waiting, Web First Assertions
- Ch 3: Configuration - Fixtures, Data-Driven Tests, Reporters, Devices
- Ch 4: Inspector and Codegen - Playwright authoring & debugging tools
- Ch 5: Playwright Tracing - Post-mortem Debugging (workflow & viewer)
- Recap - Start, configure, customize, debug, author & trace.
- Q&A - Languages support, comparison to other test frameworks.
2. Unpack the Test Script
Let's revisit the code fr the first test we created and ran on Day 1.
const { test, expect } = require('@playwright/test');
test('basic test', async ({ page }) => {
await page.goto('https://playwright.dev/');
const title = page.locator('.navbar__inner .navbar__title');
await expect(title).toHaveText('Playwright');
});
This simple test script illustrates some fundamental Playwright concepts that enable more reliable end-to-end testing:
- Auto-waiting - performs actionability checks on elements before making a requested action.
- Web-First Assertions - retries checks until a necessary condition is met, before proceeding.
- Test Isolation with fixtures - establish reliable environment for tests, enable parallelization.
- Test Hooks - for just-in-time setup and teardown of resources shared between tests.
Let's explore these briefly below.
3. Web Assertions.
Playwright uses the expect library for test assertions. Developers can test if the current state of the application matches an expected result - with helpful matchers to test various conditions for that state. For example:
expect(value).toEqual(0);
Modern web applications are dynamic with application state in constant flux. Testing assertions can be challenging if the matcher condition is not stable. Playwright makes this more reliable by extending the expect library with convenience async matchers that will now wait till the expected condition is met (and timeout otherwise).
await expect(page).toHaveTitle("Playwright");
Now let's try the Writing Assertions example (see below):
// assert.spec.js
const { test, expect } = require('@playwright/test');
test('my test', async ({ page }) => {
await page.goto('https://playwright.dev/');
// Expect a title "to contain" a substring.
await expect(page).toHaveTitle(/Playwright/);
// Expect an attribute "to be strictly equal" to the value.
await expect(page.locator('text=Get Started').first()).toHaveAttribute('href', '/docs/intro');
// Expect an element "to be visible".
await expect(page.locator('text=Learn more').first()).toBeVisible();
await page.click('text=Get Started');
// Expect some text to be visible on the page.
await expect(page.locator('text=Introduction').first()).toBeVisible();
});
Save it to a new file (assert.spec.js
) and run it as follows:
$ npx playwright test assert.spec.js
The { page }
argument provided to the test function is an example of a test fixture. We'll talk about what fixtures are in the next section.
For now, we can look at the page class documentation and see that it provides methods to interact with a single tab in a browser and handle various events emitted from it.
- The page.locator() method resolves to a view of elements in that page that match the associated selector.
- The page.goto() method navigates the browser to the provided URL.
- The page.click() methods 'clicks' the element matching that selector.
We'll explore available assertions in Playwright in depth in a future post.
4. Test Fixtures.
The { page }
argument passed into the test()
function above is an example of a test fixture. So, what is a fixture?
Inspired by pytest, test fixtures are a tool for establishing a reliable and consistent test environment that provides tests exactly what they need for the current run - and nothing more. Playwright Test analyzes all the fixtures a test needs, merges required values into a single object - and makes that available to the test
as a first parameter. The fixture is torn down after the test completes.
Why fixtures? Because they create a consistent environment (test repeatability) and provide effective isolation for testing with the following benefits:
- Efficiency - run multiple tests in parallel, faster, with less memory used.
- Targeting - retry just failed tests without re-running the entire suite.
- Grouping - group tests based on shared meaning, not just setup.
Playwright comes with a number of built-in fixtures that you can configure (see below). You can also add your own:
- fixtures.browser - shared browser instance (for worker)
- fixtures.browserName - currently running (chromium, firefox or webkit)
- fixtures.context - isolated browser context (per test)
- fixtures.page - isolated page (per test)
You can use Test Fixtures at the granularity of a test run, or use Worker Fixtures to apply them at the level of a worker process (across all tests it oversees).
The bottom line is fixtures enable consistent and isolated testing environments in Playwright Test in a flexible and customizable manner.
5. Test Hooks.
While fixtures allow you to setup the environment for a test run, test hooks provide placeholders for writing code needed to setup and teardown resources that may be shared across tests (in a group) or used on a per-test basis. Here's an example from the getting started guide:
// example.spec.js
const { test, expect } = require('@playwright/test');
test.describe('feature foo', () => {
test.beforeEach(async ({ page }) => {
// Go to the starting url before each test.
await page.goto('https://playwright.dev/');
});
test('my test', async ({ page }) => {
// Assertions use the expect API.
await expect(page).toHaveURL('https://playwright.dev/');
});
});
Here, the test.describe
method is used to declare a group of tests. The test hooks we need to familiarize ourselves with are:
- test.beforeEach - runs before starting each test in group.
- test.afterEach - runs after completing each test in group.
- test.beforeAll - runs once per group, before any tests are started.
- test.afterAll - runs once per group, after all tests complete.
Day 2: Review & Resources
- [X] Learned about the expect library for default assertions.
- [X] Learned about web assertions available in Playwright.
- [X] Learned about fixtures in pytest.
- [X] Learned about fixtures available in Playwright.
- [X] Explored the Playwright Test API support for test hooks.
- [X] Completed the Getting Started tutorial for Playwright.
This has been a lot to absorb - but never fear. In the upcoming days, we'll dive into these topics and APIs in more detail with simple examples. For now, you have a working Playwright environment and a grasp of key terms and concept for end-to-end testing using this framework! Onwards!
Day 3: Up Next
We now have a sense of how to create and run a simple test, and the core components that make up a test script. In the next few posts, let's explore some of the tools available for authoring and debugging Playwright test scripts - before we start diving into the Playwright API in more detail.
Here is a short list of tooling resources that may be worth scanning for a head start.
- Command line tools - open pages, generate code, screenshots, PDF etc.
- Playwright Inspector - GUI-based tool to author and debug scripts.
- Trace Viewer - GUI-based tool to analyze Playwright Test run traces.
- Test Generator - CLI tool to record page interactions as test scripts.
In addition, check out the Community Showcase for tools, frameworks and examples authored by the broader community.