E2E 测试是保障 Web 应用质量的最后防线, 但也是最费时的测试类型——页面定位器、等待条件、断言…… Claude Code 能帮你大幅提速:描述用户行为,直接生成测试。
Claude Code 在 Playwright 测试中的优势
擅长的任务:
根据需求/页面截图生成完整测试用例
生成 Page Object Model(POM)封装
修复脆弱测试(flaky tests)
生成测试数据 fixtures
把手动测试步骤转换为自动化测试
场景一:从用户故事生成测试
Prompt:
用户故事:
1. 注册账号(填写邮箱/密码/用户名)
2. 登录(支持记住密码)
3. 浏览商品列表,支持分类筛选
4. 添加商品到购物车并结账
帮我用 Playwright + TypeScript 写这些 E2E 测试,
使用 Page Object Model 模式。
Claude Code 生成的 POM 示例:
typescript
// tests/pages/LoginPage.ts
import { Page, Locator } from '@playwright/test'
export class LoginPage {
private emailInput: Locator
private passwordInput: Locator
private submitButton: Locator
constructor(private page: Page) {
this.emailInput = page.getByLabel('邮箱')
this.passwordInput = page.getByLabel('密码')
this.submitButton = page.getByRole('button', { name: '登录' })
}
async goto() { await this.page.goto('/login') }
async login(email: string, password: string) {
await this.emailInput.fill(email)
await this.passwordInput.fill(password)
await this.submitButton.click()
}
}
// tests/auth.spec.ts
import { test, expect } from '@playwright/test'
import { LoginPage } from './pages/LoginPage'
test.describe('用户认证', () => {
test('正常登录跳转到 dashboard', async ({ page }) => {
const loginPage = new LoginPage(page)
await loginPage.goto()
await loginPage.login('user@test.com', 'password123')
await expect(page).toHaveURL('/dashboard')
await expect(page.getByText('欢迎回来')).toBeVisible()
})
test('密码错误显示错误信息', async ({ page }) => {
const loginPage = new LoginPage(page)
await loginPage.goto()
await loginPage.login('user@test.com', 'wrong')
await expect(page.getByTestId('login-error')).toContainText('邮箱或密码不正确')
})
})场景二:修复 Flaky Tests
告诉 Claude Code:
这个测试约 30% 的情况下失败,
错误是 "Timeout waiting for element":
[粘贴失败测试代码]
Claude Code 常见修复策略:
typescript
// 修复前(脆弱):硬等待
await page.waitForTimeout(2000)
await page.click('#submit-btn')
// 修复后(稳定):等待元素可交互
await page.getByRole('button', { name: '提交' }).waitFor({ state: 'visible' })
await page.getByRole('button', { name: '提交' }).click()
// 等待 API 请求完成再断言
await Promise.all([
page.waitForResponse(resp =>
resp.url().includes('/api/order') && resp.status() === 200
),
page.getByRole('button', { name: '下单' }).click()
])
await expect(page.getByText('订单创建成功')).toBeVisible()场景三:API Mock + E2E 联合测试
typescript
test('商品列表使用 mock 数据正确渲染', async ({ page }) => {
const mockProducts = [
{ id: 1, name: 'iPhone 16', price: 5999, inStock: true },
{ id: 2, name: 'MacBook Pro', price: 14999, inStock: false },
]
// 拦截 API 请求,返回固定 mock 数据
await page.route('**/api/products', async route => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ data: mockProducts })
})
})
await page.goto('/products')
await expect(page.getByText('iPhone 16')).toBeVisible()
await expect(page.getByText('¥5,999')).toBeVisible()
// 库存不足显示售罄,按钮禁用
const macbookCard = page.getByTestId('product-card-2')
await expect(macbookCard.getByText('售罄')).toBeVisible()
await expect(macbookCard.getByRole('button', { name: '加入购物车' })).toBeDisabled()
})场景四:GitHub Actions CI/CD 并行分片
yaml
name: E2E Tests
on: [pull_request]
jobs:
e2e:
runs-on: ubuntu-latest
strategy:
matrix:
shard: [1, 2, 3]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '22' }
- run: npm ci
- run: npx playwright install --with-deps chromium
- name: Run tests (shard ${{ matrix.shard }}/3)
run: npx playwright test --shard=${{ matrix.shard }}/3
env:
BASE_URL: ${{ vars.STAGING_URL }}
- uses: actions/upload-artifact@v4
if: failure()
with:
name: playwright-report-${{ matrix.shard }}
path: playwright-report/3 个并行分片,测试速度提升约 3 倍。
高价值 Prompt 模板
[从截图生成测试]
这是登录页面截图,根据页面元素生成完整的
Playwright 登录流程测试(含正常/异常情况):
[附上截图]
[批量边界条件]
基于这个注册表单,生成所有边界条件测试:
空字段/超长输入/特殊字符/已存在邮箱/弱密码
[粘贴表单代码]
[性能断言]
用 Playwright 测试页面 Core Web Vitals:
LCP < 2.5s, CLS < 0.1
[提供页面 URL]
来源:Playwright 官方文档 + Anthropic Claude Code 文档