Playwright vs Cypress vs Selenium

Evaluate Playwright for a new browser suite needing several browser engines and isolated sessions; evaluate Cypress when its browser-centered workflow fits your frontend testing; retain or evaluate Selenium when WebDriver, language bindings, and existing browser infrastructure fit your organization. A mature working suite deserves a concrete reason to migrate.

Start with the hardest required journey: authentication across origins, a second window, a download, or two users interacting. Browser automation tools look remarkably similar while clicking one button. The differences emerge when the application gets less polite.

TL;DR

Quick Example

Use this complete local fixture to define a shared behavioral contract. Save it as fixture.html and serve it from a disposable local test server. It changes only browser memory; it sends no request and represents no real reservation system.

The acceptance contract is the same for all three tools: the initial status is “Not reserved,” the button is enabled, clicking changes the status to “Reserved,” and the button becomes disabled. Reloading resets the fixture. These outcomes are more useful than comparing the number of characters needed to express a click.

For example, in an existing Playwright Test project configured to serve this fixture at http://127.0.0.1:8080/fixture.html, a complete test file is:

The server and browser installation are prerequisites, not supplied by this test file. Playwright documents retrying assertions. Express the same contract with Cypress queries/assertions or Selenium's explicit conditions, rather than replacing assertions with fixed sleeps. This is a teaching example, not a three-runner benchmark.

Core Concepts

Automation and a test framework are different layers

Selenium's overview distinguishes WebDriver, IDE, and Grid. WebDriver drives browser behavior; Grid provides remote execution capabilities. Your language's test framework supplies additional organization, assertions, fixtures, and reporting.

Playwright offers browser APIs in several languages. Its language guide distinguishes the Node.js Playwright Test runner from Python, Java, and .NET integrations. Do not assume every runner feature or configuration file transfers unchanged between those language environments.

The interaction boundary matters

Cypress documents architectural trade-offs, including control of one open browser at a time and a plugin route for multiple tabs. Match its supported pattern to your actual flow. An older comparison that simply says “no tabs” omits useful conditions.

For every candidate, test the exact combination of windows, origins, frames, downloads, and identities the product needs. Supported individual features do not guarantee that their combination matches your test design.

Engine coverage is not every browser deployment

Playwright documents Chromium, Firefox, WebKit, and branded browser channels. A WebKit run is useful coverage, but it does not establish every behavior of every deployed Safari/OS combination. Define any additional real-browser or device checks the product requires.

Cypress's browser guide includes Chromium-family browsers and Firefox, plus experimental WebKit support. Record experimental status and platform conditions instead of presenting every entry as an equivalent production support promise.

Compare the complete workflow

Use the table to build questions for a pilot. It is not a feature-score ranking. Licensing, hosted orchestration, artifact retention, and access controls also depend on the services you choose around the open-source tool.

Run a migration pilot that can fail usefully

Choose a small group of tests with representative dependencies. Include a simple page, the authentication boundary, the slowest workflow, and a case that currently flakes. Record discovered tests, intentional skips, retries, and the known failure modes before conversion.

Preserve assertions rather than merely preserving green results. Deliberately break one expected response in the disposable pilot and confirm the new suite detects it. Check that failing tests generate enough information for someone who did not write them to diagnose the problem.

Next, compare setup ownership. Decide how each test obtains a user, seeds data, clears changes, and avoids collisions with concurrent runs. Shared mutable accounts can make an otherwise reliable runner appear random. Increasing retries may conceal the collision while making CI slower.

Keep selectors tied to a stable interaction contract. Accessible roles and names can work well where they accurately describe the UI; dedicated test identifiers can support other cases. A long selector following the current DOM nesting is more likely to encode incidental layout than the intended behavior.

Migrate further only when the pilot preserves coverage and offers a specific benefit: better browser fit, simpler maintenance, or more useful failure artifacts. Reverse the decision if a required flow depends on unsupported behavior or an adapter the team cannot maintain. Keeping the current suite while improving its fixtures can be a better investment.

Measure speed and parallelism honestly

Separate browser installation, application startup, test setup, execution, and artifact upload. Compare identical browser/OS coverage and the same number of attempts. One candidate may look faster simply because it ran fewer projects or omitted a slow setup step.

Measure total CI duration and machine time. More workers can shorten elapsed time while increasing resource demand and exposing shared-data conflicts. Add realistic limits for databases, accounts, and external services rather than assuming test cases are independent because they live in separate files.

Record several runs, the failure rate, and diagnosis effort. This article reports no comparative timing measurements. Its fixture establishes a small interaction contract; it cannot predict the throughput of an end-to-end suite.

Best Practices

Wait for observable conditions

Use the tool's supported retry or explicit-wait mechanism for the state the user needs. Selenium's waiting guidance explains conditions and warns about mixing wait strategies. A fixed delay guesses when work should finish.

Isolate identities and data

Give concurrent tests independent state where practical. Make cleanup and ownership explicit, and retain enough failure context to find leaked state. Browser isolation alone cannot isolate a shared backend record.

Keep a small real-system path

Mocks are useful for deterministic branches, but also test essential integration journeys against the intended environment. Label which boundaries are real so a mock-only success does not become a deployment claim.

Common Mistakes

Choosing from a hello-world timing

Bad: Switch a large suite because one button test starts faster.

Correct: Compare representative journeys, browser coverage, failure artifacts, and maintenance effort under equivalent conditions.

Treating retries as a fix

Bad: Add attempts until intermittent failures disappear from the headline result.

Correct: Investigate state collisions, missing conditions, and real application races. Keep retry counts visible in reports.

Calling migration complete after conversion

Bad: Count rewritten files while ignoring discovered test count and lost assertions.

Correct: Preserve behavior coverage, prove meaningful failures are caught, and review changed skips and dependencies.

FAQ

Is Playwright replacing Selenium?

It is an option for many browser suites, but an existing WebDriver ecosystem may still meet important requirements. Evaluate your language, browser matrix, remote infrastructure, and maintenance burden rather than predicting a universal replacement.

Can Cypress test more than Chrome?

Yes. Check its current browser guide and distinguish supported browsers from experimental modes. Pin and verify the combination used in CI.

Which tool is fastest?

Measure equivalent workflows in your environment. This page provides no speed multiplier or universal winner.

Should I rewrite a working Selenium suite?

Only when a concrete constraint justifies the migration. A representative pilot should demonstrate preserved failure detection and a useful operating benefit.

Related Topics

References