AI 소식12 min

Ditched Cypress for Playwright — Speed, Cost, and CI Were All Different

Moving a Cypress suite to Playwright in 2026. 290ms vs 420ms per action, 45.1% vs 14.4% QA share, 91% vs 72% satisfaction, free --shard parallelization. Install to CI walkthrough.

목차 (9)

April 2026 · AI Trends

A Cypress suite of 180 tests was eating nine minutes per pull request. Parallel execution needed the paid Cypress Cloud plan, starting at $67 a month. For a small team, that kept hurting.

Switching to Playwright trimmed the PR pipeline noticeably. Parallelization on GitHub Actions matrix was free. Safari testing was built in. Bottom line: for a new project, just go Playwright.

This post walks through installation, the page object pattern, network interception, and CI parallel runs — with direct numbers against Cypress. If you're evaluating E2E tooling or considering a migration, it's worth the read.

At a glance
· Market share: Playwright 45.1% / Cypress 14.4% (State of JS 2025, published Jan 2026)
· Satisfaction: Playwright 91% / Cypress 72% — the widest gap on record
· Execution speed: Playwright averages 290ms/action · Cypress 420ms (~1.45x faster)
· RAM for 10 parallel tests: Playwright 2.1GB / Cypress 3.2GB — 40~60% lower CI cost
· Parallel: Playwright --shard is free / Cypress Cloud starts at $67/month
· Browsers: Playwright bundles Chromium · Firefox · WebKit · Edge binaries / Cypress is Chromium-only
· GitHub stars: Playwright 78,000+ · weekly npm downloads 33M+ (early 2026)
Lazy Developer Series
Fixed 7 security vulnerabilities in one sweep
Production email outage debugging — FeedMission SaaS
Read EP.06 →

At a glance — Playwright vs Cypress

Here's the core matrix. Execution speed, parallel cost, browser coverage, network interception, and market share all lean Playwright. State of JS 2025 put satisfaction at 91% vs 72% — the widest gap ever between these two. Cypress still has the best time-travel debugger and the friendlier first-run UI.

Numbers look decisive, but a working Cypress suite is a different story. Compare migration cost to the gains directly — don't decide from a table alone.

Playwright vs Cypress full comparison — speed, RAM, CI cost, browser support, satisfaction, market share
Playwright vs Cypress — key metrics / GoCodeLab
ItemPlaywrightCypress
Avg speed (per action)290ms420ms
Parallel executionFree (--shard)Cypress Cloud $67+/mo
Browser supportChromium · FF · WebKit · EdgeChromium-based only
Network interceptBuilt-inPlugin required
RAM (10 parallel)2.1 GB3.2 GB
Satisfaction (State of JS 2025)91%72%
QA market share (2026)45.1%14.4%

Installation and basic configuration

Node.js 18 or higher is all that's needed. One command generates the config file automatically. Browser binaries are installed alongside it.

# Run from project root
npm init playwright@latest

# Install browser binaries (auto on first run)
npx playwright install

After running the command, playwright.config.ts is generated. baseURL, timeout, and the browser list are managed here. Chromium, Firefox, and WebKit are configured by default.

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

export default defineConfig({
  baseURL: 'http://localhost:3000',
  timeout: 30_000,
  retries: process.env.CI ? 2 : 0,
  projects: [
    { name: 'chromium' },
    { name: 'firefox' },
    { name: 'webkit' },
  ],
});

Setting retries to 2 in CI is standard practice — it muffles false failures from flaky networks. Locally it stays at 0 so failures surface immediately.

Writing the first test

Files matching *.spec.ts are auto-detected. One test() is one scenario. expect() handles assertions.

// tests/login.spec.ts
import { test, expect } from '@playwright/test';

test('redirects to dashboard on successful login', async ({ page }) => {
  await page.goto('/login');
  await page.getByLabel('Email').fill('test@example.com');
  await page.getByLabel('Password').fill('password123');
  await page.getByRole('button', { name: 'Sign in' }).click();
  await expect(page).toHaveURL('/dashboard');
});

Locators are DOM selectors. getByRole(), getByLabel(), and getByText() cover most cases. Semantic selectors outlive CSS-class ones when DOM structure shifts.

getByLabel('Email') resolves the input paired with the matching label. As long as the label text stays put, selector stability survives HTML rewrites. That's the real advantage over CSS-class selectors.

Structuring with the page object pattern

A page object is a class that groups all selectors for a UI surface. When a button id changes, you touch one file instead of twenty tests.

// pages/LoginPage.ts
import { type Page } from '@playwright/test';

export class LoginPage {
  constructor(private readonly page: Page) {}

  emailInput = () => this.page.getByLabel('Email');
  passwordInput = () => this.page.getByLabel('Password');
  submitButton = () => this.page.getByRole('button', { name: 'Sign in' });

  async login(email: string, password: string) {
    await this.emailInput().fill(email);
    await this.passwordInput().fill(password);
    await this.submitButton().click();
  }
}

Put page classes under pages/ and have your tests import them. Selectors change? Edit one class file. Twenty tests get updated at once.

Mocking APIs via network interception

Use it when third-party APIs are flaky or when you need to reproduce error paths. route.fulfill() injects a synthetic response — a programmable fake server for payment failures, server errors, timeouts.

// Mock the payment API
await page.route('**/api/payments', async (route) => {
  await route.fulfill({
    status: 500,
    contentType: 'application/json',
    body: JSON.stringify({ error: 'Payment failed' }),
  });
});

Cypress needs cy.intercept() plus plugins for comparable behavior — more surface area and more failure modes. Playwright ships it built-in.

GitHub Actions parallel execution

The key argument is --shard. Actions matrix hands you parallel VMs by default — free. Cypress Cloud charges for the equivalent.

# .github/workflows/e2e.yml
jobs:
  test:
    strategy:
      matrix:
        shard: [1, 2, 3, 4]
    steps:
      - run: npx playwright test --shard=${{ matrix.shard }}/4

HTML reports are auto-generated. Upload them as artifacts and Slack integrations will surface failure traces on each PR.

Playwright vs Cypress head-to-head

Both are valid picks. Team circumstances decide, not absolute rankings. Cypress keeps its UI clarity and friendly error output — approachable for non-dev contributors too. If a working Cypress suite is already there, migration is usually not worth the churn.

Pricing comparison
ItemPlaywrightCypress
Base usageFree (open source)Free (open source)
Parallel executionFree (--shard)Cloud plan required
CI dashboardFree (HTML report)$67+/month
Team size limitsNoneVaries by plan

Which tool for which case

For new projects, lock in Playwright as the default. $0 cost, multi-browser out of the box, and the ecosystem is moving faster in 2026.

ScenarioPickWhy
Starting a new projectPlaywrightFree sharding, multi-browser default
Existing Cypress teamStay on CypressMigration cost > switching gain
Frequent Safari bugsPlaywrightWebKit-based Safari testing
Non-dev writing testsCypressApproachable UI, friendlier errors
Cost-conscious CIPlaywrightNo additional parallel fees
Gradual migrationRun bothNew tests in Playwright, keep Cypress

If Cypress is current, write new tests in Playwright first. Run both in parallel and let the old suite age out. Forced migration rarely pays off.

Playwright pre-flight checklist

- Node.js 18+ installed
- baseURL set in playwright.config.ts
- retries: 2 in CI recommended
- Page objects under pages/ once you cross ~20 tests
- trace: 'on-first-retry' for failure replay
- GitHub Actions matrix with --shard

FAQ

Q. Should I choose Playwright or Cypress?

Small team and CI cost matters? Playwright. Free parallelization and multi-browser are standard. Already have a working Cypress suite? No urgency to swap.

Q. Does Playwright support Safari?

Yes. A WebKit-based binary simulates Safari behavior. Cypress only supports Chromium-based browsers. Projects with frequent iOS WebView issues particularly benefit.

Q. Is parallel execution free in CI?

Yes. --shard runs free inside GitHub Actions. Cypress Cloud is paid. Only runner time counts against your GitHub quota.

Q. Is the page object pattern mandatory?

It pays off at scale. One selector file instead of twenty test edits. If you have fewer than 20 tests, decide later based on how the suite grows.

Q. Can I keep Jest alongside Playwright?

Yes. Jest for unit/integration, Playwright for E2E. Split scripts: test:unit and test:e2e in package.json is the common shape.

Playwright is the default E2E choice in 2026. Easy install, free parallelization, multi-browser by default. New project? Start here.

For Cypress users, migration is justified but optional. If migration feels heavy, write new tests in Playwright and run both — no conflict in doing so.

Official sources
- Playwright docs: https://playwright.dev
- State of JS 2025 (testing section): https://stateofjs.com
- Playwright on GitHub: github.com/microsoft/playwright
Lazy Developer Series
Real SaaS build journal
FeedMission with Claude — security, payments, widgets.
Read EP.06 →
Found GoCodeLab useful?
Get notified when new posts ship.
Subscribe to GoCodeLab

Figures and features reflect the state as of April 2026. Consult each project's docs for the latest.

Playwright is an open-source project maintained by Microsoft; Cypress is an open-source project by Cypress.io.

공유하기
XLinkedInFacebook