How We Reduced Testing Time By 70% — by Moving From Cypress to Playwright

Learn how Playwright can transform your developer experience.

Lisa Weilguni
Lingvano
6 min readOct 2, 2023

--

A laptop showing Playwright’s UI mode and the Cypress and Playwright logo. On the left there is the headline How We Migrated From Cypress to Playwright with a picture of the author (Lisa Weilguni) above it.

“Remove .only from Cypress test” — Does this commit message sound familiar to you? If you use Cypress for end-to-end testing, you know what I’m talking about.

We have built an extensive suite of over 200 test cases using Cypress. While it’s a powerful end-to-end testing tool, we got intrigued by Playwright. Playwright is a fast-growing, open-source framework developed by Microsoft. The promise of improved speed, uniform syntax, and cross-browser support got us interested and we decided to give it a try.

In this article, we’ll share why and how we migrated from Cypress to Playwright. You’ll learn about the key benefits of Playwright and how we tackled the migration.

We’ll also share the bumps we hit along the way. If you’re thinking about making the same move, this might help you make a decision.

Why We Migrated

We experimented with Playwright in one of our smaller React apps. Two days later we fully migrated the test suite, including the time it took to learn Playwright’s APIs. That’s when we got to experience the main benefits of Playwright first-hand.

1) Speed

Playwright is significantly faster than Cypress. The Playwright test suite runs 3x faster than the Cypress equivalent on a local development machine. In the GitHub CI, Playwright gives a 2x speedup over Cypress.

┌────────────────────────┬──────────┬────────────┬────────────┐
│ Task │ Cypress │ Playwright │ Difference │
├────────────────────────┼──────────┼────────────┼────────────┤
│ Run tests locally │ 1min 27s │ 25s │ -72% │
│ Run tests on GitHub CI │ 6min 38s │ 3min 43s │ -44% │
└────────────────────────┴──────────┴────────────┴────────────┘

2) Parallelism and sharding

The increase in speed got us quite excited already. How can it be so much faster?

One reason is that Playwright supports parallel testing out of the box. In theory, Cypress allows you to execute parallel tests. However, it’s rather inconvenient with the free version.

Playwright lets you control the amount of worker processes running at the same time and limit the total number of test failures. By default, Playwright runs all the tests in a single file in order, but you have the option to run them in parallel as well.

// playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
fullyParallel: true,
retries: process.env.CI ? 3 : 0,
workers: process.env.CI ? 1 : undefined,
});

Playwright also supports sharding out of the box. In Cypress, we had to write a pretty hacky script to divide our test suite into different shards since sharding is only available in their paid plan. Playwright makes sharding easy. It allows you to split up and run the tests on different machines at the same time, saving you loads of CI minutes.

npx playwright test --shard=1/3
npx playwright test --shard=2/3
npx playwright test --shard=3/3

3) Unified Syntax

Playwright makes switching between unit and end-to-end testing smoother.

Another issue we faced with Cypress was constantly having to context switch between Cypress syntax and Jest syntax. With Playwright we can now use the same syntax between our unit and E2E tests. Cypress seems less like JavaScript and more like a unique framework specifically designed for its own domain.

Thus, writing Cypress tests always required using a different mental model. When writing tests, we often found ourselves confusing assertions like .toBeVisible and .should(‘be.visible’).

Any JavaScript developer will find a Playwright test quite easy to grasp. It involves using async functions, waiting for promises, and assigning function return values to variables.

test('Lingvano logo is visible', async ({page}) => {
await page.goto('/home');

const logo = page.getByTestId('lingvano-logo');
await expect(logo).toBeVisible();

await logo.click();

await expect(logo).not.toBeVisible();
});

4) Developer Experience

If you use Cypress, you know the testing workflow: you open the Cypress window through the terminal, search for your spec, and run the respective test. Oh, you actually just wanted to run one specific test? Then you would go back to your code editor, mark the test as .only, and come back to the Cypress window. This can get quite annoying.

Playwright is quite a game-changer when it comes to developer experience.

First of all, the Playwright VSCode extension integrates smoothly with your code editor. You can run entire flows or single test cases with just one click without leaving your editor. Intellij IDEs support Playwright natively in the EAP version now.

Do you know the frustrating feeling when a test fails but you can’t figure out at which line? Playwright makes debugging easier by highlighting the exact line of test code where it failed. No more endless scrolling to find the error message in the logs.

Playwright VSCode Extension

If you prefer to view the tests in a separate window, Playwright offers an intuitive UI mode. It’s similar to the Cypress window but offers even more.

It lets you view traces, time-travel through test runs, and run tests in watch mode. If you work test-driven like we do, you’ll find the watch mode extremely useful during development.

Moreover, UI mode allows you to pick locators right from the DOM snapshot and inspect network logs for each action.

Playwright UI Mode

5) Cross-Browser Support

Another reason that got us hooked is Playwright’s cross-browser support. While Cypress currently supports Firefox and Chrome-family browsers (including Edge and Electron), it only has experimental support for WebKit, which is Safari’s browser engine.

Playwright supports Chromium, Firefox, and WebKit-based browsers like Safari, as well as Edge. Like Cypress, it allows you to run tests in headed as well as headless mode.

Migrating 200+ tests from Cypress

We were convinced by Playwright and ready to migrate the test suite of our React Native app. But what’s the most effective way to migrate 200+ tests you might ask?

Initially, we counted on GPT4 for rewriting tests from Cypress to Playwright. We prompted GPT4 with some examples and had it rewrite test cases based on them. Turns out GPT4 was not up-to-date with the correct Playwright syntax and often suggested non-existing assertions.

Then we switched to GitHub Copilot.

  1. Copy in the Cypress test case
  2. Start typing the Playwright test case
  3. Let Copilot complete the test case

This turned out to be quite efficient and reliable.

Playwright also offers a migration tool to help you transition. You can also find other tools to support your migration like this Cypress to Playwright converter developed by a QA engineer.

In the end, it took us around two weeks to complete the migration.

Challenges You Might Encounter

For the most part, the migration went smoothly. However, as with any change to a new framework, we did hit a few bumps along the way.

1) WebKit flakiness

While running the tests on WebKit works like a charm locally on Mac, it was quite slow and flaky in our GitHub CI pipeline.

2) Integrating MSW and Playwright

We use MSW for mocking API requests for development and automated tests.

As of now, Playwright does not fully integrate with MSW. Playwright lacks support for MSW in its window context which makes overwriting MSW handlers hard. Playwright recommends using its built-in network mocking rather than relying on a third-party library.

Wrap up

Cypress is undoubtedly a great tool, but migrating to Playwright has led to an improved developer experience and faster end-to-end test execution for us. We have found Playwright to be a powerful tool with its support for parallelism and sharding, unified syntax, and cross-browser support.

However, like any transition, the migration was not without its challenges. In our case, we encountered issues with WebKit flakiness and MSW integration. Despite these hurdles, the benefits have outweighed the drawbacks, and we are optimistic about what Playwright has to offer.

Are you considering a similar transition? Feel free to reach out to us! We hope our experience provides valuable insights and helps you make an informed decision.

Curious about our app? You can check out our production version on Web, iOS or Android.

Feel free to take a look at our public repos and other projects, where we share some details of the technical setup and infrastructure of our web, iOS, and Android React Native Expo app.

Do you have questions about our setup or ideas for improvement? Just leave a comment! Make sure to follow us to get more insights into our projects and our day-to-day developer life.

We’re happy to connect on Twitter, Instagram or LinkedIn. Also, we are always hiring. Join us! 🚀

--

--