The E2E Testing Decision
End-to-end tests are expensive—they're slow, flaky, and require browser automation infrastructure. But they catch bugs that unit tests miss: the ones that happen when everything integrates.
Playwright and Cypress dominate the space. Here's how to choose.
Playwright
Built by Microsoft. Tests run in real browsers (Chrome, Firefox, Safari).
npm install -D @playwright/test
npx playwright install
// tests/auth.spec.ts
import { test, expect } from '@playwright/test';
test('user can sign in', async ({ page }) => {
await page.goto('/login');
await page.fill('[data-testid=email]', 'user@example.com');
await page.fill('[data-testid=password]', 'password123');
await page.click('[data-testid=submit]');
await expect(page).toHaveURL('/dashboard');
await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
});
test('shows validation errors', async ({ page }) => {
await page.goto('/login');
await page.click('[data-testid=submit]');
await expect(page.getByText('Email is required')).toBeVisible();
await expect(page.getByText('Password is required')).toBeVisible();
});
// API mocking
test('handles login API failure', async ({ page }) => {
await page.route('**/api/auth/login', route => {
route.fulfill({ status: 401, json: { error: 'Invalid credentials' } });
});
await page.goto('/login');
await page.fill('[data-testid=email]', 'user@example.com');
await page.fill('[data-testid=password]', 'wrongpassword');
await page.click('[data-testid=submit]');
await expect(page.getByText('Invalid credentials')).toBeVisible();
});
// Parallel execution across browsers
// playwright.config.ts
export default defineConfig({
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
{ name: 'safari', use: { ...devices['Desktop Safari'] } },
{ name: 'mobile', use: { ...devices['iPhone 14'] } },
],
fullyParallel: true,
workers: process.env.CI ? 4 : undefined,
});
Playwright strengths:
- Real cross-browser testing (Safari support is unique)
- Excellent auto-waiting (reduces flakiness)
- Native TypeScript support
- Runs in CI without display (headless)
- Powerful tracing/debugging (Playwright Inspector)
- Microsoft backing and rapid development
Cypress
The original JavaScript E2E testing tool. Runs tests in a browser with a unique architecture.
npm install -D cypress
npx cypress open
// cypress/e2e/auth.cy.ts
describe('Authentication', () => {
it('user can sign in', () => {
cy.visit('/login');
cy.get('[data-testid=email]').type('user@example.com');
cy.get('[data-testid=password]').type('password123');
cy.get('[data-testid=submit]').click();
cy.url().should('include', '/dashboard');
cy.contains('h1', 'Dashboard').should('be.visible');
});
it('handles API errors', () => {
cy.intercept('POST', '/api/auth/login', { statusCode: 401, body: { error: 'Invalid credentials' } });
cy.visit('/login');
cy.get('[data-testid=email]').type('user@example.com');
cy.get('[data-testid=password]').type('wrong');
cy.get('[data-testid=submit]').click();
cy.contains('Invalid credentials').should('be.visible');
});
});
Cypress strengths:
- Interactive test runner with time-travel debugging
- Real-time reloading during test development
- Built-in dashboard for test recording
- Large community and plugin ecosystem
- Component testing built-in
Direct Comparison
| Feature | Playwright | Cypress |
|---|---|---|
| Safari support | Yes | No (Chromium only) |
| True parallelism | Yes | With Cloud plan |
| TypeScript | Native | Via config |
| Cross-tab testing | Yes | Limited |
| Speed | Faster in CI | Faster in dev |
| Debugging | Inspector + traces | Time-travel UI |
| API mocking | route() |
intercept() |
| Pricing | Free | Free + paid cloud |
What to Choose
Choose Playwright if:
- You need Safari testing
- Multi-browser is a requirement
- You run many tests in CI (better parallelism)
- You prefer TypeScript-native tooling
Choose Cypress if:
- Your team is new to E2E testing (better DX for beginners)
- Interactive debugging matters more than CI speed
- You need component testing alongside E2E
- Strong Cypress ecosystem for your use case (React, etc.)
The Practical Rule
For new projects in 2025: start with Playwright. It's faster, has Safari, and Microsoft's investment means it's improving rapidly.
For teams already on Cypress: don't migrate unless you hit a specific limitation. The tool is fine and migration has costs.
Playwright E2E test setup with authentication helpers, fixtures, and CI integration: Whoff Agents AI SaaS Starter Kit.
Top comments (0)