🎠Why Do I Choose Playwright for End-to-End Testing?
Some of the features of Playwright I like over other e2e testing frameworks.
Introduction
Playwright enables reliable end-to-end testing for modern web apps. Playwright Test was created specifically to accommodate the needs of end-to-end testing. Playwright supports all modern rendering engines including Chromium, WebKit, and Firefox. Test on Windows, Linux, and macOS, locally or on CI, headless or headed, with native mobile emulation for Google Chrome for Android and Mobile Safari.
Key advantages:
- Cross-browser support: Test on Chromium, Firefox, WebKit, Chrome, Edge, and mobile devices.
- First-class TypeScript support: Strong typing and autocompletion.
- Parallel execution: Fast test runs with isolated browser contexts.
- Powerful automation APIs: Interact with pages, network, and browser features.
- Rich debugging tools: UI mode, trace viewer, and codegen.
See Best Practices for more tips.
Out-of-the-box Test Assertions
Playwright includes test assertions via the expect
function. To make an assertion, call expect(value)
and choose a matcher that reflects your expectation. There are many generic matchers like toEqual
, toContain
, and toBeTruthy
for asserting various conditions.
Soft Assertions
By default, a failed assertion will terminate test execution. Playwright also supports soft assertions: failed soft assertions do not terminate test execution, but mark the test as failed.
// Make a few checks that will not stop the test when failed...
await expect.soft(page.getByTestId('status')).toHaveText('Success')
await expect.soft(page.getByTestId('eta')).toHaveText('1 day')
// ... and continue the test to check more things.
await page.getByRole('link', { name: 'next page' }).click()
await expect
.soft(page.getByRole('heading', { name: 'Make another order' }))
.toBeVisible()
At any point during test execution, you can check for soft assertion failures:
// Make a few checks that will not stop the test when failed...
await expect.soft(page.getByTestId('status')).toHaveText('Success')
await expect.soft(page.getByTestId('eta')).toHaveText('1 day')
// Avoid running further if there were soft assertion failures.
expect(test.info().errors).toHaveLength(0)
Note: Soft assertions only work with the Playwright test runner.
Support for Multiple Browsers and Devices
Playwright can run tests on Chromium, WebKit, and Firefox, as well as branded browsers like Google Chrome and Microsoft Edge. It can also emulate tablets and mobile devices, including device orientation, geolocation, and color scheme.
You can run your tests in multiple browsers and configurations by setting up projects in the config. You can also add different options for each project.
import { defineConfig, devices } from '@playwright/test'
export default defineConfig({
projects: [
// Desktop browsers
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
{ name: 'webkit', use: { ...devices['Desktop Safari'] } },
// Mobile emulation
{ name: 'Mobile Chrome', use: { ...devices['Pixel 5'] } },
{ name: 'Mobile Safari', use: { ...devices['iPhone 12'] } },
// Branded browsers
{
name: 'Google Chrome',
use: { ...devices['Desktop Chrome'], channel: 'chrome' },
},
{
name: 'Microsoft Edge',
use: { ...devices['Desktop Edge'], channel: 'msedge' },
},
],
})
Certain Enterprise Browser Policies may impact Playwright's ability to launch and control Google Chrome and Microsoft Edge. Running in an environment with browser policies is outside of the Playwright project's scope.
Generating Tests
Use the codegen
command to run the test generator, followed by the URL of the website you want to generate tests for. The URL is optional; you can always run the command without it and add the URL directly in the browser window.
npx playwright codegen demo.playwright.dev/todomvc
Interact with the browser, and Playwright will generate code for your actions. Codegen prioritizes role, text, and test id locators, and will refine locators to uniquely identify elements, reducing test flakiness.
You can also generate tests using emulation for specific viewports, devices, or color schemes, as well as emulate geolocation, language, or timezone. The generator can also preserve authenticated state. See the Test Generator guide for more.
With the test generator, you can record:
assert visibility
to check if an element is visibleassert text
to check if an element contains specific textassert value
to check if an element has a specific value
Debug Tests in UI Mode
Debug your tests with UI Mode for a better developer experience. You can walk through each step and visually see what was happening before, during, and after each step. UI mode also includes features like the locator picker and watch mode.
npx playwright test --ui
Use the Pick Locator button to select an element and see the locator Playwright would use. Edit locators in the locator playground and see them highlighted live. Use Copy Locator to copy and paste into your test.
To debug one test file:
npx playwright test example.spec.ts --debug
To debug a specific test from a line number:
npx playwright test example.spec.ts:10 --debug
Test Reports
The HTML Reporter shows a full report of your tests, allowing you to filter by browsers, passed, failed, skipped, and flaky tests. By default, the HTML report opens automatically if some tests fail, or you can open it manually:
npx playwright show-report
You can also use other reporters (list, dot, JSON, JUnit, Allure, etc.) for integration with CI/CD pipelines.
Trace Viewer
Playwright Trace Viewer is a GUI tool to explore recorded Playwright traces of your tests. You can go back and forward through each action and visually see what was happening.
In the HTML report, click the trace icon next to the test name to open the trace for that test.
Or, in the detailed view, scroll to the
Traces
tab and open the trace by clicking the screenshot.
View traces by clicking through each action or hovering on the timeline. Inspect the log, source, network, errors, and console during each step. The trace viewer creates a DOM snapshot so you can interact with it and open DevTools to inspect HTML, CSS, etc.
See the Trace Viewer guide for more.
Support for Multiple Languages
Playwright is available in multiple languages (JavaScript/TypeScript, Python, Java, .NET, Go) that share the same underlying implementation. All core browser automation features are supported in all languages, though testing ecosystem integration may differ. See supported languages.
Mock APIs and Network Interception
Playwright provides APIs to mock and modify network traffic, both HTTP and HTTPS. You can also mock using HAR files. For example, intercept all calls to */**/api/v1/fruits
and return a custom response:
test("mocks a fruit and doesn't call api", async ({ page }) => {
// Mock the api call before navigating
await page.route('*/**/api/v1/fruits', async (route) => {
const json = [{ name: 'Strawberry', id: 21 }]
await route.fulfill({ json })
})
// Go to the page
await page.goto('https://demo.playwright.dev/api-mocking')
// Assert that the Strawberry fruit is visible
await expect(page.getByText('Strawberry')).toBeVisible()
})
For microservices or large websites, you can proxy partial JS and CSS file requests to your local dev server, making it easier to develop test cases when you need to change source code or add test ids.
export default defineConfig({
// ...
webServer: {
command: 'npm run start',
url: 'http://127.0.0.1:3000',
reuseExistingServer: !process.env.CI,
},
})
See webServer for more.
Out-of-the-box Snapshot Testing
Playwright provides methods for comparing page and element screenshots with expected values stored in files.
import { test, expect } from '@playwright/test'
test('example test', async ({ page }) => {
await page.goto('https://playwright.dev')
// Basic usage.
await expect(page).toHaveScreenshot()
})
// Pass options to customize the snapshot comparison and have a generated name.
await expect(page).toHaveScreenshot('landing-page.png', { maxDiffPixels: 100 })
// Configure image matching threshold.
expect(await page.screenshot()).toMatchSnapshot('landing-page.png', {
threshold: 0.3,
})
// Non-image snapshots.
expect(await page.textContent('.hero__title')).toMatchSnapshot('hero.txt')
Learn more about visual comparisons.
Note: Matching snapshots only works with the Playwright test runner.
Since there can be significant differences among snapshots on different OS or headed/headless mode, it's better to run snapshot test cases on Linux headless mode using the Docker image to keep the same environment as CI.
Integration with Docker
Script to run Docker image:
docker run -it --rm --ipc=host -v $(pwd):/work/ -w /work/ mcr.microsoft.com/playwright:v1.42.1-jammy /bin/bash
See usage for more.
Why Playwright Over Other Frameworks?
- True cross-browser and cross-platform support (including WebKit/Safari).
- Powerful and reliable locators (role, text, test id, etc.) reduce test flakiness.
- Rich debugging and reporting tools (UI mode, trace viewer, HTML reports).
- First-class support for modern web features (SPA, SSR, network mocking, mobile emulation).
- Fast parallel execution and isolated browser contexts.
- Active development and strong community support.