Q34 of 42 · Playwright

How would you migrate from Cypress to Playwright incrementally?

PlaywrightSeniorplaywrightmigrationcypressstrategysenior

Short answer

Short answer: Set up Playwright alongside Cypress, port the highest-ROI specs first (smoke, top journeys), keep both running in CI until parity, retire Cypress area-by-area. Plan 2-4 quarters depending on suite size. Don't translate 1:1 — Playwright's fixtures, projects, and `storageState` argue for different abstractions.

Detail

Same incremental playbook as the reverse direction; the differences are in what you exploit about Playwright that Cypress couldn't do.

Phase 0 — set up alongside. Install @playwright/test, get 3-5 sample specs running in CI as a separate, allowed-to-fail job. Team learns the new framework on low-stakes specs.

Phase 1 — top journeys. Port the smoke set (login, checkout, headline feature). These exercise the patterns you'll need: fixtures, storageState, page.route, projects.

Phase 2 — bug-history coverage. Re-create regression tests for production bugs from the past 12 months. Adapts the legacy "bug → test" pipeline to the new framework.

Phase 3 — parallel run. Both suites run on every PR; failures from either block. Compare flake rates. Often Playwright wins by a margin (better auto-wait + trace viewer reduces flake debugging).

Phase 4 — area-by-area retirement. Pick the area with full Playwright coverage; delete the Cypress equivalents. Repeat.

Phase 5 — kill switch. Retire the Cypress installation when only legacy specs remain.

Where to deliberately diverge from the Cypress version:

  • Custom commands → fixtures. Cypress's cy.loginAs becomes a Playwright fixture (authedPage). Composable, typed, scoped.
  • cy.sessionstorageState setup project. A first-class Playwright pattern — log in once, share via JSON.
  • cy.interceptpage.route. Same conceptual move, different shape.
  • cy.visit + assertions → semantic locators. Replace cy.get('[data-test=...]\') with getByRole / getByLabel where possible — better refactor resilience.
  • Multi-tab / multi-context tests that Cypress couldn't do — these are where Playwright wins. Port any tests you'd previously stubbed around.
  • Cross-browser moves from "we ran on Chrome only" to "chromium + firefox + webkit projects".

Cultural moves:

  • Pair Cypress-experts with Playwright-curious engineers. The Cypress people know the test scenarios; Playwright newcomers bring the new framework's patterns.
  • Don't promise feature parity in the first quarter. Some Cypress patterns (component testing, time-travel UI) need different translations.
  • Migration metric: % of suites where Playwright covers what Cypress covered. Target 100% before retiring Cypress.

A 500-test migration realistically takes 2-4 quarters with one dedicated engineer plus team participation.

// WHAT INTERVIEWERS LOOK FOR

Phased plan with parallel-run validation, willingness to redesign rather than translate (custom commands → fixtures, cy.session → storageState), and naming Playwright's wins (multi-context, cross-browser, trace).

// COMMON PITFALL

1:1 translating Cypress patterns into Playwright — you end up with Cypress-shaped Playwright that doesn't exploit fixtures, projects, or storageState.