DEV Community

Cover image for Playwright adoption guide: Overview, examples, and alternatives
Megan Lee for LogRocket

Posted on • Originally published at blog.logrocket.com

Playwright adoption guide: Overview, examples, and alternatives

Written by Antonello Zanini✏️

Playwright is a browser automation framework available in multiple programming languages. In the fast-paced world of web development, Playwright has become one of the leading technologies for writing end-to-end tests for modern web applications, thanks to its rich and intuitive API.

Join us in this adoption guide and get ready to learn everything you need to know about Playwright and why to use it in your browser automation projects!


Introduction to Playwright

Playwright is a cross-browser, cross-language, cross-platform browser automation framework developed by Microsoft. Originally created to meet the needs of end-to-end testing, it can cover many other user cases as well. It provides an intuitive, easy-to-learn, unified API for interacting with all modern rendering engines, including Chromium, WebKit, and Firefox.

Playwright works on Windows, Linux, and macOS; locally or on CI; on desktop or emulated mobile browsers; and in headless or headed mode. The framework supports several platforms and programming languages, such as JavaScript and TypeScript, Java, Python, and .NET.

Let’s now take a step back and review Playwright’s history before seeing what it offers, its main use cases, and how to get started with it.

History of Playwright

Playwright was introduced by Microsoft in January 2020. The development team included engineers who had previously worked on Google's Puppeteer project, the most popular JavaScript-based automated testing framework at the time.

The team's experience with that technology helped them build a more flexible and modern framework that could overcome Puppeteer's well-known limitations and shortcomings. For example, they immediately recognized the need for a tool that could support multiple browsers and not only Chromium-based browsers.

On 6 May 2020, the first stable version of Playwright was released. This included full support for Chromium, Firefox, and WebKit, establishing Playwright as a comprehensive cross-browser testing tool.

The Playwright Node.js test runner was released later as part of an effort to provide a more complete solution for running browser-based tests. Its development was driven by the need for a tool that could fully leverage the Playwright API and make end-to-end testing more robust and straightforward.

Since its initial release, Playwright has rapidly evolved. The team has worked hard to to make the framework more robust and extensive by keep adding new features. These include improved selectors, auto-wait mechanisms, network interception, device emulation, and integrations with popular CI/CD systems and testing frameworks.

With over 62k stars on GitHub and more than 5 million weekly downloads on npm, Playwright is now a leading browser automation technology. Its community boasts thousands of active users, with extensive documentation, tutorials, and community-driven content contributing to its widespread adoption.

Further reading:

How Playwright works: Playwright library vs. Playwright Test

To better understand how Playwright works, we need to dig into its two main components:

  • The Playwright library — The core component that provides the API for interacting with browsers. It supports the Chromium, Firefox, and WebKit browser engines, making it possible to interact with multiple browsers from a single script. Features offered by these APIs include browser context management, page navigation, DOM element selectors, user action simulation, and more
  • Playwright Test — A test runner built specifically to work with the Playwright Library. It offers a complete environment for writing, organizing, and running automated tests. Features offered by this component include BDD test definition, assertions, parallel execution, result report generation, extended configuration, and more

In other words, the Playwright library exposes the low-level API for interacting with browsers. Meanwhile, Playwright Test brings the framework and tools needed to efficiently manage and execute tests built using that API. Together, they form a powerful toolkit that enables developers to create robust and reliable web automation scripts and tests.

Further reading:

Use cases for Playwright

Playwright’s use cases depend on whether we’re referring to the Playwright library or Playwright Test.

These are some of the most common use cases for the Playwright library:

  • Web scraping — Scripts that can extract data from web pages by automating browser interactions and navigating through pages
  • Browser automation bot development — Bots that automate repetitive tasks in the browser by simulating the behavior of a human user

These are some of the main use cases of Playwright Test:

  • End-to-end testing — Simulate a specific user flow in a site or web application from start to finish to ensure that all components work together as intended on different browsers
  • Component testing — Isolate individual components of a web application to test their functionality in different scenarios. As of this writing, this is still experimental in Plawyright
  • API testing — Verify that the REST APIs exposed by a backend application produce the desired results by calling them directly or triggering them by automating user interaction with a frontend application in the browser
  • Visual regression testing — Testing a web application to ensure that new code changes do not negatively affect layouts or user interface

Playwright as a whole covers all the use cases presented above and many more.

Further reading:

Setting up a Playwright project

Playwright requires different setups depending on which of its two components you need to use. Since the framework is popular primarily for its testing capabilities, let's look at how to create a Playwright testing project in TypeScript using Node.js.

First, make sure you have Node.js installed on your machine. Then, run the command below in the project folder to start the Playwright setup wizard:

npm init playwright@latest
Enter fullscreen mode Exit fullscreen mode

During the process, you will have to choose:

  • Programming language to write your tests with (TypeScript or JavaScript)
  • Name of the folder containing the test scripts
  • Whether to add a GitHub Actions workflow to easily run tests on CI
  • Whether to install Playwright browsers

After answering these questions, the installation tool will start downloading, installing, and configuring the required dependencies. At the end of this process, your project folder will contain a Playwright test suite.

The configured test folder will contain an example.spec.ts test file you can run with this command:

npx playwright test
Enter fullscreen mode Exit fullscreen mode

The result will be the following HTML report: Result Of Setting Up A Test Suite In Playwright Displaying Html Report Awesome, you just set up a Playwright testing project!


Anatomy of a Playwright script

Browser automation and test scripts follow two different structures in Playwright. We’ll go over how they work in the Playwright library and with Playwright Test.

Playwright library scripts

A Playwright Library browser automation script generally performs the three steps below:

  1. Launch a chosen browser directly
  2. Visit a web page and perform some operations on it
  3. Close the browser and release its resources

For example, this is what a simple web scraping Playwright script looks like:

const { chromium } = require("playwright");

(async () => {
  // launch a new browser instance
  const browser = await chromium.launch();
  // create a new browser context
  const context = await browser.newContext();
  // create a new page in the browser context
  const page = await context.newPage();

  // locate the h1 element on the page 
  const firstH1 = await page.locator('h1'); 
  // extract the text in the h1 element 
  const h1Text = await firstH1.textContent();

  // print the scraped data in the console
  console.log(h1Text);

  // release the browser resources
  await context.close();
  await browser.close();
})();
Enter fullscreen mode Exit fullscreen mode

Behind the scenes, Playwright instructs Chromium to visit the specified page, search for the <h1> element, retrieve the text inside it, print it in the console, and close the browser.

Playwright Test scripts

In Playwright, a test is a sequence of commands enclosed in a test() block. These commands are the building blocks of the test logic and are usually methods on the page object provided by Playwright. Then, at the end of the test block, there is an except() assertion method to verify that a specific condition is true.

Playwright tests have a BDD syntax and follow the AAA pattern:

  • Arrange — Prepare the test environment, such as setting up a database with some specific data
  • Act — Perform actions on the page, such as filling out forms or clicking buttons
  • Assert — Check the state of the page against expectations

This is true for both unit and end-to-end tests.

In simple terms, a Playwright test performs actions on the application and verifies that it’s behaving as expected. Here is an example of a test:

import { test, expect } from "@playwright/test";

test("has title", async ({ page }) => {
  await page.goto("https://playwright.dev/");

  // expect a title "to contain" a substring.
  await expect(page).toHaveTitle(/Playwright/);
});

test("get started link", async ({ page }) => {
  await page.goto("https://playwright.dev/");

  // click the get started link.
  await page.getByRole("link", { name: "Get started" }).click();

  // expects page to have a heading with the name of Installation.
  await expect(page.getByRole("heading", { name: "Installation" })).toBeVisible();
});
Enter fullscreen mode Exit fullscreen mode

Here, the test file contains two tests. The first test wraps the following two commands:

  • Visit the URL "https://playwright.dev/"
  • Verify that the title contains the substring "Playwright"

The second test includes commands to:

  • Visit the URL "https://playwright.dev/"
  • Click the link with the name "Get started"
  • Verify that a heading with the name “Installation” is visible on the page

As you can notice, the commands are close to plain English and can be chained quite intuitively. This is what makes Playwright so popular — it ensures that tests are easy to write, read, and debug.

In Playwright, related tests can also be grouped together in a describe() block, like this:

import { describe, test, expect } from "@playwright/test";

describe("User Authentication Tests", () => { 
  test("should let a user log in", async ({ page }) => {
    // test logic for user login...
  });

  test("should let new users sign up", async ({ page }) => {
    // test logic for new signups...
  });

  test("should let users reset their passwords", async ({ page }) => {
    // test logic for password reset functionality...
  });
});
Enter fullscreen mode Exit fullscreen mode

describe() blocks are called test groups and live inside a spec file. All test groups in a spec file are called a test suite.

The devices and browsers to execute these tests on, as well as many other options, can be configured locally or globally in configuration files. In a TypeScript testing project, the global configuration file is playwright.config.ts.


Why choose Playwright?

Here are the main reasons why Playwright is such a popular option for browser automation, from its great ease of use to its extensive documentation and plethora of integrations:

  • Cross-browser support — Playwright can run on Chrome, Firefox, Edge, Safari, and many other browsers. The same automated test or script can be run on different browsers without having to make code changes. This ensures that tested web applications run consistently across all major browsers, which is critical to reaching a wider audience and maintaining a high-quality user experience
  • Multiple programming languages — The same Playwright API that thousands of developers love and are familiar with is available in JavaScript, TypeScript, Python, and .NET with some minor modifications to adapt the method names to the best naming practices of the different programming languages. There are also many other unofficial ports, such as Playwright Ruby or Playwright Go
  • Many integrations — Playwright is compatible with all major CI/CD systems, including GitHub Actions, Docker, Azure Pipelines, CircleCI, Jenkins, Bitbucket Pipelines, GitLab CI, and Google Cloud Build. It also supports Visual Studio Code via a dedicated extension
  • Easy setup and configuration — Playwright comes with an installation tool that simplifies project setup. The framework also features an integrated configurable test runner that supports parallel execution, custom reporting, CLI options, and more. This test runner simplifies the creation, configuration, and management of end-to-end testing
  • Supported frameworks — Playwright's API can interact with any application running in a browser, regardless of the framework it was built in. That includes static sites, dynamic web pages, SPAs, and more. When it comes to component testing, it supports React, Vue, Svelte, and Solid
  • Extensive community and support — Playwright has been on the crest of a wave for years now. The community is huge and there is a lot of information available on various sites and channels, including Discord, StackOverflow, YouTube, GitHub, and others
  • Top-notch documentation — Playwright's official documentation is detailed, always up-to-date, covers all supported programming languages, and includes best practices and hundreds of examples. It is hard to ask for more from the documentation of a framework

Further reading:

Main limitations of Playwright

Playwright is an excellent tool with many features supporting several use cases, but it also has some limitations. The most critical ones are:

  • Steep learning curve — Playwright's extensive feature set can be overwhelming for beginners. Mastering every aspect of this vast technology can take several months. The learning curve can be steep, especially for those unfamiliar with automated testing frameworks
  • Not officially extendable via plugins — Compared to Cypress and Selenium, Playwright cannot be extended via official or community-developed plugins. This is possible only through playwright-extra, a community-driven project tthat adds extensibility to Playwright via several plugins
  • Heavy library — The playwright npm package has an uncompressed size of 3 MB and depends on playwright-core, which has an unpacked size of 7 MB. That is a total of 10 MB. On top of that, browser executables required by Playwright take hundreds of MB
  • No support for spies — Playwright does not have built-in support for spies, which are commonly used in unit testing to monitor function calls and their arguments. If you need such functionality, you must rely on additional libraries or frameworks
  • Ongoing changes — Playwright is still under active development, with at least a couple of new releases per month, which means frequent updates and changes to the API. While this ensures access to the latest browser features and many improvements based on community feedback, it can also lead to potential instability and the need for updates in test scripts

Further reading:


Key Playwright features to know

Having seen the main strengths and weaknesses of Playwright, you’re ready to get into the specifics of what this popular automation tool can do.

Rich API

What makes Playwright such a powerful tool is its strongly typed API, which allows you to:

  • Select DOM elements — Identify page elements and retrieve them by ID, name, text, and many other strategies, or by using a CSS selector or XPath expression
  • Automate web interactions — Use built-in methods to simulate user interaction with web elements, including clicking, typing, dragging, and more. Playwright also supports complex interactions, such as handling file uploads and downloads
  • Run custom JavaScript script — Run native JavaScript code on the page to perform interactions and actions not directly supported by Playwright methods or utilities
  • Deal with modern web features — Take advantage of WebSockets, service workers, WebRTC, and other modern web and browser features. This makes it possible to thoroughly test the latest web technologies
  • Take screenshots and visually compare them — Take screenshots of the entire viewport or a single element and use options like maxDiffPixels to compare them for visual regression testing

These are just a few of the many features supported by the rich Playwright API. Check out the official documentation for more information.

Further reading:

Auto-waiting

Before performing any action on a web element, Playwright performs a series of actionability checks. These checks ensure that the action will behave as expected.

Specifically, Playwright automatically waits for all these checks to pass and only then executes the requested action. If the checks do not pass within the globally configured timeout value, the action fails with a TimeoutError.

For example, before performing a locator.click() action, Playwright will ensure that:

  • locator resolves to an exactly one element
  • Element is visible
  • Element is in a stable state (e.g. not in an animation)
  • Element can receive events
  • Element is enabled

If you don’t like this behavior, you can opt out of auto-waiting by specifying the force option to false:

element.click({ force: true })
Enter fullscreen mode Exit fullscreen mode

Network and browser mocking

Playwright can mock and modify HTTP and HTTPS network traffic to API endpoints. In particular, it can mock or intercept and modify XHRs and fetch requests your frontend application makes on the browser. This is possible thanks to the page.route() method:

test("mocks a fruit and doesn't call api", async ({ page }) => {
  // mock the api call before the page navigation logic
  await page.route("*/**/api/v1/fruits", async route => {
    // response of the intercepted API call
    const json = [{ name: "Strawberry", id: 21 }];
    // return the given response
    await route.fulfill({ json });
  });

  // navigate to the page making the request to intercept
  await page.goto("https://demo.playwright.dev/api-mocking");

  // assert that the Strawberry fruit is visible
  await expect(page.getByText("Strawberry")).toBeVisible();
});
Enter fullscreen mode Exit fullscreen mode

The above code intercepts all the frontend calls to the */**/api/v1/fruits endpoints and mocks a custom response for them.

Playwright also supports mocking requests via HTTP Archive (HAR) files. These files contain a record of all the network requests made by the page when it’s loaded by the browser, including information about the request and response headers, cookies, content, timings, and more. You can use Plawyright to record a HAR file, update it as required, and use it to mock network requests in your tests.

Further reading:

Screenshots and videos

Playwright supports recording options to take screenshots or record videos of your tests. By default, videos are disabled but can be enabled with the global video option. This accepts the following values:

  • "off" —Do not record video (default value)
  • "on" — Record a video for each test
  • "retain-on-failure" — Record videos for each test, but remove all videos from successful test runs
  • "on-first-retry" — Record video only when retrying a test for the first time

Similarly, Playwright can be configured to capture screenshots after each test run by using the screenshot option. The supported values for this option are:

  • "off" — Do not capture screenshots (default value)
  • "on" — Capture screenshots after each test
  • "only-on-failure" — Capture screenshots after each test failure

Trace Viewer

Trace Viewer is a powerful GUI tool to explore recorded Playwright traces after a test script has run. These traces provide comprehensive insights into your automated test runs, helping you debug and optimize your tests: Trace Viewer Tool Demo When you run a test with tracing enabled, Playwright collects detailed information about each operation performed. This includes network requests, screenshots, DOM snapshots, console logs, and more.

The traces are stored in an archive file that you can explore with the Trace Viewer in an interactive interface. Inside this tool, you can navigate through each action your test performed, view corresponding network activity, and examine how the page looked at any point in time.

The Trace Viewer is particularly useful for debugging a test failed in a CI/CD environment. It can help you gain a deeper understanding of test execution to quickly identify and address issues.

Device emulation

Playwright can test your web application on your current machine or emulate real devices, including mobile phones and tablets. Select a device from the list of supported ones or configure a custom device you would like to emulate by specifying values such as "userAgent", "screenSize", "viewport", and if it "hasTouch" enabled.

You can also emulate the "geolocation", "locale", and "timezone" for all tests or for a specific test, as well as set the "permissions" to show notifications or even change the "colorScheme".

Consider the following configuration file for your test suite:

// import the device list
import { defineConfig, devices } from "@playwright/test";

export default defineConfig({
  projects: [
    {
      name: "Mobile Safari",
      use: {
        // configure a special device
        ...devices["iPhone 13"],
      },
    },
  ],
});
Enter fullscreen mode Exit fullscreen mode

When running a test in headed mode, this is what you’ll see in the browser window: Device Emulation Test Run In Headed Mode Showing User Interface In Mobile Layout As configured, the window browser your application is tested in has the same viewport size as an iPhone 13.

Parallelism and sharding

By default, Playwright runs tests in parallel. In detail, it launches multiple test files in parallel using different worker processes. These are operating system processes that run independently and are orchestrated by the Playwright test runner. All workers have identical environments, start their own browsers, and cannot communicate with each other.

To be executed, a test file must be first assigned to a free worker. Thus, test files are executed in parallel, but tests of a single file are run in order and within the same worker process. You can disable parallelism by setting the number of workers to 1. Playwright also supports sharding the test suite so that you can run it on multiple machines simultaneously.

Automatic retries

Playwright supports test retries. This is a mechanism to automatically re-run a test when it fails, which is useful for detecting flaky behavior. By default, retries are disabled. When enabled, Playwright will retry failing tests multiple times until they pass or the maximum number of retries is reached.

You can configure retries in the Playwright configuration file as shown below:

import { defineConfig } from "@playwright/test";

export default defineConfig({
  // give failing tests 3 retry attempts
  retries: 3,
});
Enter fullscreen mode Exit fullscreen mode

After you configure the retry logic, Playwright will categorize tests in the result report as follows:

  • "passed" — Tests that passed on the first run
  • "flaky" — Tests that failed on the first run, but passed when retried
  • "failed" — Tests that failed on the first run and failed on all other retries

Further reading:

Custom reporters

Playwright reporters are tools that generate detailed logs and summaries of test runs. They provide information on test executions, highlighting successes, failures, and other relevant details. You can also use multiple reporters at the same time.

Playwright comes with several built-in reporters, each tailored for different needs. These include:

  • List reporter — Prints a line for each test being run, showing detailed information about each test's progress and outcomes
  • Line reporter — Produces a single line to report the last finished test and prints failures inline as they occur
  • Dot reporter — Generates a single character per successful test. This is the default reporter in CI environments, useful for reducing output noise
  • HTML reporter — Generates an HTML report for the test run, which can be explore as a web page in the browser. It provides a visual and interactive way to review test results
  • Blob reporter — Creates detailed reports containing all information about the test run, useful for merging reports from sharded tests. The output is in a compressed format
  • JSON reporter — Produces a JSON object with comprehensive information about the test run, typically written to a file for further analysis or integration with other tools
  • JUnit reporter — Generates a JUnit-style XML report, often used for integration with CI systems that support JUnit reports
  • GitHub reporter — Returns annotations for test failures, making it easier to identify and address issues directly within GitHub

In addition to the built-in options, Playwright allows developers to create custom reporters to fit their specific needs. You can achieve this by implementing the Reporter interface and defining how the test results should be processed and displayed.

Test generator

Playwright offers the ability to generate tests without coding. This Codegen feature is a great way to quickly define new tests in any of the supported programming languages. When you specify the codegen option, Playwright opens two windows:

  1. Browser window — Where you can interact with the site or web application you want to test
  2. Playwright's inspector window — Where you can record, copy, and delete tests, as well as change the programming language of the generated code

Playwright will generate the code associated with the interactions you perform on the page in the browser window. Codegen can determine the recommended locator for the elements you interact with and turns all actions you make on the page into lines of code. Thanks to a special toolbar, you can also define assertions to close the generated test logic.

UI Mode

When launching a test in UI Mode, Playwright opens a window with a list of all test files in your suite: Window Showing List Of Test Files In Suite After Launching Test In Ui Mode Here you can explore, run, and debug individual tests within these test files. UI Mode allows you to run actions back and forth to see what happens during each action, while on the right you can see the application being tested. This time-travel experience makes it easier to understand what a test does on the web application to debug it.

UI mode also enables you to filter tests by text, tag, or outcome. Other features available in this tool include seeing DOM element selectors, inspecting console errors, looking at network calls, and more.

Alternatives to Playwright

As powerful as Playwright is, no single tool can meet every developer's needs. Some developers may prefer a lighter library, while others may require features such as spies and full support for component testing. Similarly, some teams might look for extensibility through a large ecosystem of plugins.

Below is a table comparing Playwright with its main competitors to help you make the right choice about which browser automation tool to use:

Playwright Selenium Cypress Puppeteer
Tool type Framework for web testing and automation Browser automation framework and ecosystem Front-end testing tool that runs in a browser High-level API to control Chrome over the DevTools Protocol
GitHub stars 62k+ 29k+ 46k+ 87k+
npm weekly downloads ~5.6M ~2M ~5.5M ~4M
Setup Simple Complex Simple Simple
Features Several Good amount Several Limited
Supported browsers All major modern browsers All major browsers, including IE Chromium-based browsers, Firefox Chromium-based browsers, experimental Firefox support
Supported languages JavaScript, Python, Java, .NET languages Java, JavaScript, C#, Python JavaScript JavaScript
Built-in test runner Yes No Yes No
Plugins Not officially supported but available via playwright-extra Only supported in Selenium IDE Native support Not officially supported but available via puppeteer-extra

Further reading:

Conclusion

In this article, we discussed what Playwright is and how it has become one of the most popular browser automation and testing frameworks in the industry. We explored its functionality, advantages and disadvantages, main features, and how it compares to similar testing technologies. Playwright expertise unlocked!

The aim of this overview was to assist you in evaluating Playwright for your testing suite or browser automation project. If you have any further questions about what Playwright is best for and how to use it effectively, feel free to comment below.


Get set up with LogRocket's modern error tracking in minutes:

  1. Visit https://logrocket.com/signup/ to get an app ID.
  2. Install LogRocket via NPM or script tag. LogRocket.init() must be called client-side, not server-side.

NPM:

$ npm i --save logrocket 

// Code:

import LogRocket from 'logrocket'; 
LogRocket.init('app/id');
Enter fullscreen mode Exit fullscreen mode

Script Tag:

Add to your HTML:

<script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
<script>window.LogRocket && window.LogRocket.init('app/id');</script>
Enter fullscreen mode Exit fullscreen mode

3.(Optional) Install plugins for deeper integrations with your stack:

  • Redux middleware
  • ngrx middleware
  • Vuex plugin

Get started now

Top comments (0)