What is @playwright/test?
The @playwright/test npm package is a framework for end-to-end testing that allows developers to automate browser interactions for testing web applications. It supports multiple browsers, provides a rich set of APIs for navigation, interaction, and assertions, and offers features like test parallelization, fixtures, and snapshot testing.
What are @playwright/test's main functionalities?
Browser Automation
Automate browser actions such as navigating to a URL, interacting with page elements, and validating page properties.
const { test, expect } = require('@playwright/test');
test('basic test', async ({ page }) => {
await page.goto('https://example.com');
const title = await page.title();
expect(title).toBe('Example Domain');
});
Cross-Browser Testing
Run tests across multiple browsers like Chromium, Firefox, and WebKit.
const { test } = require('@playwright/test');
test.describe.configure({ browsers: ['chromium', 'firefox', 'webkit'] });
test('cross-browser test', async ({ page }) => {
await page.goto('https://example.com');
// Perform cross-browser checks
});
Mobile Emulation
Emulate mobile devices to test responsive designs and touch interactions.
const { devices, test } = require('@playwright/test');
const iPhone11 = devices['iPhone 11 Pro'];
test('mobile emulation test', async ({ browser }) => {
const context = await browser.newContext({
...iPhone11,
});
const page = await context.newPage();
await page.goto('https://example.com');
// Perform actions in the emulated mobile environment
});
Visual Regression Testing
Capture screenshots and compare them against known good snapshots to detect visual regressions.
const { test, expect } = require('@playwright/test');
test('visual test', async ({ page }) => {
await page.goto('https://example.com');
expect(await page.screenshot()).toMatchSnapshot('homepage.png');
});
Test Fixtures
Create reusable test setup and teardown logic with fixtures.
const { test } = require('@playwright/test');
test('use fixture', async ({ myFixture }) => {
// Use the fixture in the test
});
test.extend({
myFixture: async ({}, use) => {
// Set up the fixture
await use('some value');
// Clean up the fixture
},
});
Other packages similar to @playwright/test
cypress
Cypress is a popular end-to-end testing framework similar to Playwright. It offers a rich interactive test runner and has a focus on ease of use. Unlike Playwright, Cypress only supports testing in a Chromium-based browser, which can be a limitation for cross-browser testing.
selenium-webdriver
Selenium WebDriver is one of the oldest and most widely used browser automation tools. It supports multiple programming languages and browsers. Compared to Playwright, Selenium tests tend to be slower and can be more flaky due to reliance on the WebDriver protocol.
puppeteer
Puppeteer is a Node library developed by the Chrome DevTools team. It provides a high-level API to control Chrome or Chromium over the DevTools Protocol. Playwright is considered a successor to Puppeteer and extends its capabilities by supporting more browsers and additional features.
nightwatch
Nightwatch.js is an automated testing framework for web applications and websites, using the W3C WebDriver API. It is easy to use and set up. Compared to Playwright, Nightwatch may have less advanced features and browser support but is still a solid choice for many testing scenarios.
testcafe
TestCafe is a node.js tool for automating end-to-end web testing. It is known for its ease of setup and use, and it does not require WebDriver. Unlike Playwright, TestCafe runs tests written in JavaScript or TypeScript directly in the browser which can be both an advantage and a limitation depending on the context.
🎭 playwright-test
🚧 This project is under development. See Test runner integrations to use Jest or Mocha with Playwright.
Build an end-to-end test suite with Playwright.
Get started
npm i -D @playwright/test
Place tests in files ending with .spec.js
or .spec.ts
.
const { it, expect } = require('@playwright/test');
it('is a basic test with the page', async ({page}) => {
await page.goto('https://playwright.dev/');
const home = await page.waitForSelector('home-navigation');
expect(await home.evaluate(home => home.innerText)).toBe('🎭 Playwright');
});
Run all tests across Chromium, Firefox and WebKit
npx test-runner
Run tests on a single browser
npx test-runner --browser-name=chromium
Run all tests in headful mode
npx test-runner --headful
Take screenshots on failure
npx test-runner --screenshot-on-failure
See all options
npx test-runner --help
Parallelized execution
The test runner launches a number of worker processes to parallelize test execution. By default, this number is equal to number of CPU cores divided by 2. Each worker process runs a browser and some tests.
To run in serial, use the --jobs
flag.
npx test-runner --jobs 1
Setup environment with fixtures
Fixtures initialize your test functions. Fixtures can be used to set up the test environment with services and state that are required by the test.
For end-to-end testing, this test runner sets up a page in a browser. This behavior
can be customized.
Default fixtures
- Each worker process launches a browser (this is the
browser
fixture).
- Each worker runs tests.
- Each test is provided a browser context (
context
fixture) and a page (page
fixture). Browser contexts are isolated execution environments that share a browser instance.
- The
context
fixture uses the defaultContextOptions
fixture to define context options.
Examples
it('should load the website', async ({ page }) => {
await page.goto('https://playwright.dev');
expect(await page.title()).toContain('Playwright');
});
it('should load two pages', async ({ context }) => {
const pageOne = await context.newPage();
const pageTwo = await context.newPage();
})
Override default fixtures
Default options can be overriden to specific testing requirements. For example, defaultContextOptions
can be modified to launch browser contexts with mobile emulation.
const { fixtures } = require('@playwright/test');
const { devices } = require('playwright');
fixtures.overrideTestFixture('defaultContextOptions', async ({}, test) => {
await test({ ...devices['iPhone 11'] })
});
Define custom fixtures
It is possible to define custom fixtures to setup the test environment. If the fixture is to be shared across tests, define a worker-level fixture. If not, use test-level fixtures.
For example, we can extend the default page
fixture to navigate to a URL before running the tests. This will be a test-level fixture. This can be further extended to wrap the page into a page object model.
fixtures.defineTestFixture('homePage', async({page}, test) => {
await page.goto('https://playwright.dev/');
await test(page);
});
it('should be on the homepage', async ({homePage}) => {
expect(await homePage.title()).toContain('Playwright');
});
TODO: How to add TypeScript support with declareTestFixtures
Parameterize your tests
A common pattern with end-to-end tests is to run test suites against multiple
parameters.
Default parameters
browserName
: Can be chromium
, firefox
or webkit
. Tests are parameterized
across the 3 browsers.
Custom parameters
You can define custom parameters
import { fixtures } from '@playwright/test';
fixtures.defineParameter('appUrl', 'URL of the app to test against', 'http://localhost');
fixtures.generateParameterizedTests('appUrl', ['https://production.app',
'https://staging.app']);
it('should add item to cart', async ({ appUrl }) => {
})
TODO: How to add TypeScript support with declareParameters
To run tests with a custom value for the parameter, convert the name of the parameter
into kebab-case (appUrl
becomes app-url
)
npx test-runner --app-url=https://newlocation.app
Annotate your tests
Annotate your tests with modifiers: flaky
, fixme
, fail
, skip
, and slow
.
Annotations can be applied conditionally with parameters.
test.skip(params.browserName === 'firefox', 'Not supported for Firefox')
One or more annotations can be combined.
it('should add item to cart', (test, params) => {
test.flaky('Uses Math.random internally')
test.skip(params.browserName == 'firefox')
}, async ({ page }) => {
})
Spec syntax
To run a single test use fit
or it.only
.
const { it, fit } = require('@playwright/test');
it.only('should be focused', ...);
fit('should be focused', ...);
To skip a test use xit
or it.skip
.
const { it, fit } = require('@playwright/test');
it.skip('should be skipped', ...);
xit('should be skipped', ...);
Tests can be wrapped inside describe
blocks to structure tests.
Assertions
For assertions, the test runner uses the popular expect package. See
expect API reference.