—
引言
大家好,我是coding小虫。做前端自动化测试4年了,用过Selenium、Cypress,最近一年深度使用Playwright。今天想和大家聊聊这两个热门框架的对比,帮你决定2026年该学哪个。
先说结论:两个都值得学,但推荐先学Playwright。
为什么?往下看。
—
一、框架背景对比
Cypress
- 2017年发布,专注前端E2E测试
- JavaScript/TypeScript原生支持
- 客户端运行,不走WebDriver协议
- 社区活跃,文档丰富
- 商业公司维护,有免费版和付费版
Playwright
- 2020年由Microsoft发布
- 支持JS/TS、Python、Java、.NET
- 基于Chrome DevTools Protocol
- Microsoft维护,完全开源免费
- 支持Chromium、Firefox、WebKit三引擎
| 对比项 | Cypress | Playwright |
|---|---|---|
| 发布时间 | 2017 | 2020 |
| 维护方 | 商业公司 | Microsoft |
| 开源 | 部分开源 | 完全开源 |
| 语言支持 | JS/TS | 多语言 |
| 浏览器 | Chrome系列 | Chromium/Firefox/WebKit |
| 运行方式 | 客户端 | CDP协议 |
—
二、核心技术差异
1. 运行架构
这是两个框架最本质的区别。
Cypress架构:
浏览器 Cypress运行时 测试代码
(同一个进程内)
Cypress运行在浏览器内部,可以直接访问:
- DOM
- Window对象
- Network请求
- Application状态
Playwright架构:
浏览器 CDP协议 Playwright 测试代码
(独立进程)
Playwright通过Chrome DevTools Protocol控制浏览器,类似WebDriver但更底层。
2. 各有优劣
Cypress的优势:
javascript
// Cypress可以直接访问应用内部状态
cy.window().then((win) =
{
// 直接调用应用的方法
win.app.login(‘user’, ‘pass’);
});
// 实时看到DOM变化
cy.get(‘.loading’).should(‘not.exist’);
Cypress的劣势:
javascript
// Cypress不能跨域访问
// 不能同时测试多个标签页
// 不能直接测试非JS应用(如纯HTML页面)
Playwright的优势:
javascript
// Playwright支持多页面
const page1 = await browser.newPage();
const page2 = await browser.newPage();
// 支持跨域
await page1.goto(‘https://site-a.com’);
await page2.goto(‘https://site-b.com’);
// 可以测试任何网站
await page.goto(‘https://any-site.com’);
—
三、API设计对比
元素定位
Cypress:
javascript
// Cypress使用jQuery风格的定位器
cy.get(‘#username’).type(‘user’);
cy.get(‘.btn-primary’).click();
cy.contains(‘登录’).click(); // 文本定位
// 链式调用
cy.get(‘.form’)
.find(‘input’)
.first()
.type(‘hello’);
Playwright:
javascript
// Playwright使用CSS/XPath/Text定位器
await page.locator(‘#username’).fill(‘user’);
await page.locator(‘.btn-primary’).click();
await page.getByText(‘登录’).click(); // 文本定位
// 链式调用
await page.locator(‘.form’)
.locator(‘input’)
.first()
.fill(‘hello’);
等待机制
Cypress:
javascript
// Cypress自动重试,不需要手动等待
cy.get(‘.result’).should(‘contain’, ‘success’);
// 会自动等待直到元素出现或超时(默认4秒)
Playwright:
javascript
// Playwright也自动等待
await page.locator(‘.result’).textContent();
// 默认等待30秒
// 也可以自定义等待
await page.waitForSelector(‘.result’, { timeout: 5000 });
await page.waitForFunction(() =
document.querySelector(‘.result’).textContent === ‘success’);
断言方式
Cypress:
javascript
// Cypress使用Chai断言库
cy.get(‘.price’).should(‘have.text’, ‘$100’);
cy.get(‘.item’).should(‘have.length’, 3);
cy.get(‘.error’).should(‘not.be.visible’);
// 自定义断言
cy.get(‘.data’).should(($el) =
{
expect($el.text()).to.match(/pattern/);
});
Playwright:
javascript
// Playwright使用内置断言
await expect(page.locator(‘.price’)).toHaveText(‘$100’);
await expect(page.locator(‘.item’)).toHaveCount(3);
await expect(page.locator(‘.error’)).not.toBeVisible();
// 自定义断言
await expect(page.locator(‘.data’)).toMatch(/w+/);
—
四、实际功能对比
1. 多浏览器支持
Cypress:
javascript
// Cypress配置支持Chrome、Edge、Firefox(实验性)
{
“browsers”: [
{ “name”: “chrome”, “family”: “chromium” },
{ “name”: “firefox”, “family”: “firefox” }
]
}
// Firefox支持有限,WebKit不支持
Playwright:
javascript
// Playwright原生支持三大引擎
const browser = await chromium.launch(); // Chromium
const browser = await firefox.launch(); // Firefox
const browser = await webkit.launch(); // Safari风格
// 或者使用项目配置
const projects = [
{ name: ‘chromium’, use: { browserName: ‘chromium’ } },
{ name: ‘firefox’, use: { browserName: ‘firefox’ } },
{ name: ‘webkit’, use: { browserName: ‘webkit’ } },
];
2. 并行测试
Cypress:
bash
Cypress Dashboard付费版支持并行
cypress run –parallel
#免费版需要自己配置,比较麻烦
Playwright:
bash
Playwright原生支持并行
npx playwright test –workers=4
配置文件
export default defineConfig({
workers: process.env.CI ? 4 : 1,
});
3. 测试报告
Cypress:
bash
内置Mocha报告
cypress run –reporter mochawesome
Dashboard付费版有更丰富的报告
Playwright:
bash
多种报告格式
npx playwright test –reporter=html
npx playwright test –reporter=junit
HTML报告很美观,包含视频截图
4. 网络Mock
Cypress:
javascript
// Cypress Mock网络请求
cy.intercept(‘GET’, ‘/api/users’, {
body: [{ name: ‘test’ }]
});
cy.intercept(‘POST’, ‘/api/login’, (req) =
{
req.reply({ status: 200, body: { token: ‘mock-token’ } });
});
Playwright:
javascript
// Playwright Mock网络请求
await page.route(‘**/api/users’, route =
{
route.fulfill({ body: JSON.stringify([{ name: ‘test’ }]) });
});
await page.route(‘**/api/login’, route =
{
route.fulfill({ status: 200, body: ‘{ “token”: “mock-token” }’ });
});
—
五、性能对比
我做了一个简单的性能测试:
javascript
// 测试用例:登录 –
导航 -> 5个页面操作 -> 验证
// 环境:M1 MacBook Pro,Chrome浏览器
// Cypress
// 10次平均:12.3秒
// Playwright
// 10次平均:8.7秒
Playwright更快的原因:
1. CDP协议比WebDriver更高效
2. 自动等待算法更智能
3. 并行执行更成熟
—
六、代码示例对比
登录测试
Cypress版:
javascript
// cypress/e2e/login.cy.js
describe(‘登录测试’, () =
{
beforeEach(() =
{
cy.visit(‘/login’);
});
it(‘成功登录’, () =
{
cy.get(‘#username’).type(‘testuser’);
cy.get(‘#password’).type(‘password123’);
cy.get(‘button[type=”submit”]’).click();
cy.url().should(‘include’, ‘/dashboard’);
cy.get(‘.welcome’).should(‘contain’, ‘欢迎’);
});
it(‘登录失败’, () =
{
cy.get(‘#username’).type(‘wronguser’);
cy.get(‘#password’).type(‘wrongpass’);
cy.get(‘button[type=”submit”]’).click();
cy.get(‘.error’).should(‘be.visible’);
cy.get(‘.error’).should(‘contain’, ‘用户名或密码错误’);
});
});
Playwright版:
javascript
// tests/login.spec.js
import { test, expect } from ‘@playwright/test’;
test.describe(‘登录测试’, () =
{
test.beforeEach(async ({ page }) =
{
await page.goto(‘/login’);
});
test(‘成功登录’, async ({ page }) =
{
await page.locator(‘#username’).fill(‘testuser’);
await page.locator(‘#password’).fill(‘password123’);
await page.locator(‘button[type=”submit”]’).click();
await expect(page).toHaveURL(/.*dashboard/);
await expect(page.locator(‘.welcome’)).toContainText(‘欢迎’);
});
test(‘登录失败’, async ({ page }) =
{
await page.locator(‘#username’).fill(‘wronguser’);
await page.locator(‘#password’).fill(‘wrongpass’);
await page.locator(‘button[type=”submit”]’).click();
await expect(page.locator(‘.error’)).toBeVisible();
await expect(page.locator(‘.error’)).toContainText(‘用户名或密码错误’);
});
});
API测试
Cypress版:
javascript
// Cypress做API测试
describe(‘API测试’, () =
{
it(‘获取用户列表’, () =
{
cy.request(‘GET’, ‘/api/users’)
.its(‘status’)
.should(‘eq’, 200);
cy.request(‘GET’, ‘/api/users’)
.its(‘body’)
.should(‘have.length’, 10);
});
});
Playwright版:
javascript
// Playwright做API测试
import { test, expect } from ‘@playwright/test’;
test(‘获取用户列表’, async ({ request }) =
{
const response = await request.get(‘/api/users’);
expect(response.status()).toBe(200);
const body = await response.json();
expect(body.length).toBe(10);
});
—
七、选型建议
选Cypress的场景
- 纯前端项目,需要快速上手
- 团队只会JavaScript
- 需要实时调试、时间旅行功能
- 测试场景不涉及多标签页、跨域
选Playwright的场景
- 需要测试多种浏览器(包括Safari风格)
- 团队使用Python、Java等非JS语言
- 需要高性能并行测试
- 测试场景复杂(多页面、iframe、跨域)
- 有CI/CD集成需求
我的建议
2026年推荐学Playwright
理由:
1. 多语言支持,适合各种团队
2. Microsoft维护,长期保障
3. 完全开源免费
4. 性能更好
5. 功能更全面
但Cypress依然值得学习,特别是前端团队。
—
八、学习路径
Cypress学习路径
1. 官方文档:https://docs.cypress.io/
2. 安装:npm install cypress
3. 第一个测试:npx cypress open
4. 学习API定位、断言、Mock
5. 集成CI/CD
Playwright学习路径
1. 官方文档:https://playwright.dev/
2. 安装:npm init playwright@latest
3. 第一个测试:npx playwright test
4. 学习Locator、Assertions、Page Object
5. 配置多浏览器、并行、报告
6. 集成CI/CD
—
总结
Playwright和Cypress都是优秀的E2E测试框架,各有优势:
| 场景 | 推荐 |
|---|---|
| 前端团队、纯JS项目 | Cypress |
| 多语言团队、复杂场景 | Playwright |
| 需要测试Safari | Playwright |
| 快速上手、实时调试 | Cypress |
| CI/CD集成、并行测试 | Playwright |
2026年,我的排序:Playwright
Cypress > Selenium(Web自动化)。
—
参考资料
- Playwright官方文档:https://playwright.dev/
- Cypress官方文档:https://docs.cypress.io/
- Playwright vs Cypress对比:https://playwright.dev/docs/comparisons
- RunnerGo博客系列文章
—
下期预告:Pytest高级用法全攻略 – 参数化、钩子函数与插件开发实战