Compare

Playwright vs Cypress, counted rather than argued

Most versions of this comparison are feature lists. We went and counted instead: 15 public repositories with substantial Playwright suites, and 16 that run Cypress or have moved off it. Roughly 1,642 Playwright spec files and about 15,800 test call sites on one side, several thousand Cypress specs on the other.

Method: repositories were sparse-cloned read-only on 3 September 2026, counted with grep over the suite directories, and deleted. A few repos appear in both samples because they carry both frameworks. Counts are call-site approximations: parameterized loops distort them. Statements about how Playwright and Cypress behave come from their own documentation, cited at the bottom with the date we read it. QA Reef is not affiliated with Microsoft, the Playwright project, or Cypress.io; the names identify the software being compared.

The short version

What the sample says about direction

Of the 16 Cypress-era repos, 10 have finished or started a move to Playwright. Five finished: saleor-dashboard (July 2024), freeCodeCamp (June 2024), PostHog (August 2025), n8n (October 2025), grafana (April 2026). Three are mid-move with both suites live. Two arrived at Playwright from other frameworks. None moved the other way.

Two large suites are deliberately staying on Cypress and investing in it, including the most disciplined suite in either sample.

What the sample says about outcomes

Framework choice did not predict suite health. Fixed-sleep density varied about 30x between Cypress suites and about 20x between Playwright suites, and the best Cypress suite we read is healthier by that measure than several Playwright suites. Whatever you pick, the discipline is the deliverable.

Side by side, on numbers we counted

 Playwright sample (15 suites)Cypress sample (16 repos)
Dominant locator style Role-first in 8 of 15. Test-id first in 3, usually suites that migrated from Cypress or built a selector package. CSS-first in 1, mixed in 3. XPath: 12 calls in the whole sample, all in one repo. No convention won. One suite is strict data-cy (2,999 uses), one is Testing Library queries, one is mostly raw CSS ids and classes, one wraps a data-test attribute in a custom command. An importer has to preserve what it finds.
Login API login into the browser context, or a storageState file written once by a setup project. 14 of 15. One suite fills the login form through the UI. Custom API-login commands built on cy.request. cy.session count across seven production suites: zero. The only uses are three calls in Cypress's own reference app.
Test data Seeded through the API or the ORM, never the UI. One suite makes 387 direct request.* calls from specs to set up documents. Same idea, taken further: database snapshots restored between tests (1,236 restores in one suite), and session identifiers baked into a snapshot file so tests skip the login endpoint entirely.
Hard sleeps 482 waitForTimeout calls across about 15,800 tests, roughly 3 per 100. Values cluster at 500 and 1000 ms with a tail to 6000. Per-suite density spread: about 20x. Counted as cy.wait(<number>) against cy.wait('@alias'). The densest suite averages 4.1 fixed sleeps per spec file; the most disciplined has 61 fixed sleeps against 1,879 aliased waits across 424 specs. Spread: about 30x.
Retries in CI 13 of 15 configure retries. Median 2, maximum 5. One suite runs at 0 on principle. Two suites retry on local runs as well. Retries are commonly off or set to 1, and skipped tests carry the load instead: one suite has 84 skips with retries disabled.
Parallel work Sharding with the built-in --shard flag, in whatever CI the team already has. Shard counts observed: 4, 8, 10, 16. Cypress documents that cross-machine parallelization requires --record, so it runs through Cypress Cloud. Two suites in the sample hold Cloud project ids and still split work with plain CI matrices anyway.
Where the suite really lives A private layer: page objects, fixtures, and in the largest suite a composables layer, with 3 raw locator() calls in 271 spec files. Also a private layer: about 460 custom command registrations in one suite, a helper namespace used 2,641 times in another. Nobody writes raw cy.* at scale.

Suites are named in this page only where the fact is a neutral or favorable one, such as a completed migration. Counts that read as criticism are reported without a name attached, on purpose.

Difference 1

The mechanical differences that showed up in real configs

Three published behaviors explain most of what we saw in the CI files.

  • Parallelism is in the box on one side. Playwright runs test files in parallel by default, with workers defaulting to "half of the number of logical CPU cores", and it splits a run across machines with --shard. Cypress's documentation states that "Running tests in parallel requires the --record flag be passed", and that its strategy is file-based.
  • Tests inside one file are serial by default in Playwright. Its docs are explicit: "By default, tests in a single file are run in order, in the same worker process." Teams opt in with fullyParallel. This is the setting that most often explains a suite that shards 16 ways and is still slow.
  • Waiting for the network is discouraged by the vendor. Playwright's own API reference marks the networkidle load state DISCOURAGED and says "Don't use this method for testing, rely on web assertions to assess readiness instead". One suite in our sample still had 194 of them, which is the reliable smell of a suite mid-way through learning the tool.

What the disciplined suites use instead is visible in the counts: about 12,200 toBeVisible assertions sample-wide, roughly 470 waitForURL calls, and 317 polling assertions in a single suite for eventually-consistent screens.

Difference 2

Neither framework saves you from state setup

The hardest part of both samples is the same part: getting the application into state X cheaply, several hundred times per run. Logging in is trivial and everyone solved it the same way, through the API. Seeding is where migrations stall. One large project named its single biggest migration impediment in public: Cypress's cy.task() let it run Node code to seed or reset user data mid-test, and its new Playwright setup had no equivalent, which forced a choice between canned user snapshots and hand-written API mocking.

So if you are choosing a framework to fix a seeding problem, you are choosing the wrong variable. Pick the framework for its runner and its debugging, and budget the seeding work separately.

Reasons in the data to pick Playwright

  • Parallel runs and sharding need no vendor account, which is what every large suite in the sample ended up doing.
  • Role-first locators are a real convention with a plurality behind them, so new engineers copy something durable.
  • Retries, traces and web-first assertions are defaults rather than add-ons, and 13 of 15 suites use the retries.
  • If you may later move to a hosted runner or a generator, the ecosystem is where the tooling is being written.

Reasons in the data to stay on Cypress

  • A large working suite is an asset. The most disciplined suite in either sample is a Cypress suite, and it is staying.
  • Your custom command layer is your suite. Porting 460 commands is a quarter of work with no user-visible outcome.
  • Migrations in the sample ran spec by spec for months, in one case about a year, with both suites in CI the whole time.
  • The pain you feel may be sleeps, seeding and skips, all of which travel with you.

What we could not determine

  • Wall-clock suite durations and pass rates. Repos expose shard counts and job timeouts, not run telemetry.
  • Actual flake rates. Sleep density, skip counts and retry settings are proxies we counted, not failure history.
  • Test-id coverage in the applications themselves. All counts are test-side usage, so a role-first suite may simply be testing an app that never added test ids.
  • Private-repo behavior. This sample is large, well-staffed open-source products. Smaller internal suites may look nothing like it.
  • Why the two hold-out teams stay on Cypress. No decision record was found in either tree, and inference is not evidence.

Where QA Reef fits

QA Reef records a flow in a hosted browser and generates a plain Playwright spec by deterministic codegen, then runs it and returns PASS, FAIL or UNMEASURED. The counts above shaped the generator: it ranks a data-testid first when the app has the convention, then role and accessible name, then label or placeholder, then scoped text, with CSS last and no XPath. It never emits a fixed sleep. It reports sleeps per 100 tests for suites you bring, because that number turned out to separate suites better than the framework name does.

If you are half migrated, that is the case we expect. Every migration in the sample ran spec by spec with both suites green in CI, so importing one spec while the rest of your old suite keeps running is the normal path, not an edge case.

Related: Cypress to Playwright migration · why end-to-end tests go flaky · QA Reef vs your own Playwright setup · when the CI suite is too slow.

FAQ

Questions

Is Playwright better than Cypress?

For a suite started today, the direction of travel in our sample is one way: 10 of 16 Cypress-era repos have completed or begun a move, and none moved back. But two large suites are staying and investing, and the numbers say suite health tracks team discipline rather than framework: fixed-sleep density varied about 30x inside the Cypress sample and about 20x inside the Playwright sample.

What is the real difference for parallel runs?

Playwright runs files in parallel by default, defaulting to half your logical CPU cores, and shards across machines with a flag in any CI. Cypress documents that cross-machine parallelization requires --record, which routes it through Cypress Cloud. Both statements are from the vendors' own docs, read 3 September 2026.

Do teams really use cy.session?

Not in this sample. Zero calls across seven production Cypress suites; the only uses were three in Cypress's own reference application. Real suites log in over the API and seed state through the server or the ORM.

Will migrating fix our flaky tests?

No. The Playwright suites still carry 482 hard sleeps across roughly 15,800 tests, and the teams that finished migrating immediately rebuilt flake tooling: one wrote a custom quarantine reporter, another bought a dashboard and built duration-weighted sharding. Changing frameworks restarted the tooling work rather than ending it.

How should we decide, in one sentence?

If you have no suite, start on Playwright because parallelism and traces are free and the conventions are settled; if you have a large Cypress suite that works, fix sleeps and seeding first and migrate spec by spec only when a specific cost forces it.

Sources

Counts are our own, taken from public default branches on 3 September 2026 with the method described at the top. Framework behavior is quoted from vendor documentation read the same day.

Sitewide caveats, on every page: QA Reef is pre-launch. No customers, no case studies, no SOC 2 report. Hosted billing has not opened yet. Mobile native app testing is not supported. There is no managed human-QA service.

Bring one spec and we will run the numbers on your suite.

Sleep density, skip count, retry settings and locator mix, from your own repository, before you decide anything.

Talk to the team