Testing web applications with Node.js and Playwright

Microsoft’s web testing framework mixes browser and dev tools access to give you a comprehensive automation and test framework.

Modern application development depends on automated testing, using test frameworks to ensure that code is ready to go into application packages and out to end-users. To get the most from testing, tests are written before code and can be integrated into source control and CI/CD (continuous integration/continuous deployment) pipelines. Tests should be everywhere in your development process. Need to merge a pull request? Test the code. Need to commit to a branch? Test the code.

But there’s one area where testing is hard, especially when it needs to be automated. I’m talking about the need to interact with and test dynamic user interfaces. Web application testing is a complex process. Tools such as Selenium and webdriver are key elements in automating page content and in ensuring that you’re testing both page elements and the application as a whole. They’re important if you’re using headless browsers in an application; I’ve been using a set of Python scripts in a Twitter application built around Selenium and Chromium’s webdriver support to automate taking screenshots from an aircraft tracking application.

Introducing Playwright, Microsoft’s web testing framework

Selenium and webdriver aren’t the only tools for building end-to-end tests for modern web applications and browsers. A popular alternative is Google’s Puppeteer, which handles both sending clicks to browsers using the same techniques as Chrome’s webdriver tooling and accessing debugging information via the familiar developer tools’ APIs. A newer entrant in the browser testing league, Playwright is being developed by Microsoft as an open source project hosted on GitHub.

Playwright takes the basic Puppeteer architecture and moves it more in the direction of Selenium, adding a web automation framework and improving how Puppeteer interacts with page content. It’s designed to install quickly and easily using familiar npm syntax, using JavaScript to build web application automation and testing. It works with more browsers, with support for Chromium-based browsers such as Edge, as well as Firefox and Apple’s WebKit.

There’s an important message in Playwright’s list of supported browsers: You can’t use it with Trident- or EdgeHTML-based browsers. It’s not surprising. Microsoft has made a firm commitment to its Chromium branch in its new Edge, and both the old Edge and Internet Explorer are close to end of life. If you’re going to use Playwright for testing, you’re making a decision to support only mainstream modern browsers, so you will need to inform users what’s in store for future releases of any web applications you’re building and supporting.

Testing the web with Playwright

The ability to cross-platform test on all the major browsers with the same set of scripts is important, as is support for mobile versions of sites (as the two main mobile platforms use variants of their desktop browsers Playwright currently emulates mobile views in desktop browsers). Also important is support for headless tests, where you’re not rendering a browser UI, working instead with the generated document object model (and a shadow DOM if you’re using modern browser functionality and technologies such as web components).

You can use Playwright to automate a running browser on development desktops to inspect errors as part of application debugging, ensuring that you consistently run through all your test paths while recording additional performance information and watching for untracked UI glitches. Alternatively, it can be set up as part of a GitHub action to test new code as part of a commit or a merge, automating what could otherwise be a complex manual test.

Building and running Playwright tests

Getting started with Playwright is as easy as setting up a new Node.js project. First, have Node.js installed on your test devices. Since Playwright uses Node, you can run it on development PCs or on servers in your CI/CD pipeline, making it part of a GitHub action that can be used throughout your software development process. All you need is a single npm command, which installs the Playwright package as well as the binaries for all the supported browsers. With the install complete, you can create automation scripts using JavaScript or TypeScript to call Playwright APIs. These are all asynchronous calls, so use await statements to manage their promises.

The result is a very clear way of building scripts, starting with opening a headless browser instance, then navigating to a page before interacting with page instances. It’s a good idea to initially build tests with full browsers so you can follow how Playwright interacts with your application. A useful slow-mo option runs interactions at a more human speed, making to easier to visualize and manage tests running in desktop browsers. Once a test has been debugged and is running well, you can move it to headless mode and then run it as part of a CI/CD implementation.

Playwright includes a CLI tool that can record interactions with sites, automatically generating the JavaScript needed to run tests. The codegen option is a useful tool for quickly getting started with Playwright, showing you the code that interacts with page elements that you can then use as a template for your own tests, copying and editing generated code as necessary. TypeScript support can help write more complex tests, using strong typing to manage variables.

Working with web applications in Playwright

One of Playwright’s more helpful features is its support for browser contexts. These allow you to run isolated actions in a single browser instance, so you can set up several contexts to test several interactions at the same time. Inside each context you create pages, which are best thought of as tabs in a desktop browser. Pages support their own click interactions and can be monitored in parallel. Once you’re in a page you can use different ways of finding content to interact with, using CSS or XPath selectors, HTML attributes, or text. If you’re familiar with Selenium you should find navigating through pages familiar, with the added ability to wait for a page to fully load or for dynamic content to be rendered in a single-page web application.

You can use evaluate functions to send parameters to and from web pages to JavaScript code running in the page context. Results are returned to a test script runner in Node.js for analysis, giving you the tools needed to pass or fail tests. Playwright works with the F12 browser devtools so it can do a lot more than simply interact with page content. It can monitor network traffic, so you can use it to test both authentication and file download, among other things. It can access the browser console and record errors that might not be immediately visible in a rendered page: for example, tracking CSS issues or JavaScript libraries that fail to load.

There’s a lot in Playwright, and it makes a compelling alternative to Selenium for testing browser applications. With Microsoft continually adding to the F12 developer tools in Edge, it’ll be interesting to watch Playwright add new features that expand your options for testing browser-hosted applications and progressive web apps alongside traditional web applications.

Beyond JavaScript: Testing in Python and C#

Microsoft recently released a new version of Playwright for developers who prefer to build tests in Python rather than JavaScript. It’s a useful option, as many existing Selenium test frameworks are Python-based, and it allows you to link your testing code to analytical packages for more detailed results analysis using Python’s rich ecosystem of statistical applications and tools.

Playwright includes language bindings for C#, so you can bring Playwright into existing test frameworks for ASP.NET or other .NET tools. You shouldn’t have to change the way you work to bring in new tools, and Microsoft is promising additional language bindings for Java and Ruby. There’s the prospect of more in the future, as the Playwright documentation states that it is designed to support bindings for any language. With all the code on GitHub, there’s the opportunity to create your own bindings for your test language of choice and submit them as a pull request to the project.

Copyright © 2020 IDG Communications, Inc.