SKILL.md
readonly只读
name
playwright-expert
description
在编写 Playwright 的 E2E 测试、搭建测试基础设施或调试不稳定的浏览器测试时使用。调用此技能可编写测试脚本、创建页面对象、配置测试夹具、设置报告器、集成 CI、实现 API 模拟或执行视觉回归测试。触发词:Playwright、E2E 测试、端到端、浏览器测试、自动化、UI 测试、视觉测试、页面对象模型、测试不稳定。
Playwright 专家
E2E 测试专家,精通 Playwright,用于实现稳健、可维护的浏览器自动化。
核心工作流程
- 分析需求 - 确定要测试的用户流程
- 设置 - 使用适当的设置配置 Playwright
- 编写测试 - 使用 POM 模式、合适的选择器、自动等待
- 调试 - 运行测试 → 检查跟踪 → 识别问题 → 修复 → 验证修复
- 集成 - 添加到 CI/CD 流水线
参考指南
根据上下文加载详细指导:
| 主题 | 参考 | 加载时机 |
|---|---|---|
| 选择器 | references/selectors-locators.md |
编写选择器、选择器优先级 |
| 页面对象 | references/page-object-model.md |
POM 模式、夹具 |
| API 模拟 | references/api-mocking.md |
路由拦截、模拟 |
| 配置 | references/configuration.md |
playwright.config.ts 设置 |
| 调试 | references/debugging-flaky.md |
不稳定的测试、跟踪查看器 |
约束
必须做
- 尽可能使用基于角色的选择器
- 利用自动等待(不要添加任意超时)
- 保持测试独立(无共享状态)
- 使用页面对象模型以提高可维护性
- 启用跟踪/截图以便调试
- 并行运行测试
禁止做
- 使用
waitForTimeout()(应使用适当的等待) - 依赖 CSS 类选择器(脆弱)
- 在测试之间共享状态
- 忽略不稳定的测试
- 无充分理由使用
first()、nth()
代码示例
选择器:基于角色(正确) vs CSS 类(脆弱)
// ✅ 基于角色的选择器 — 对样式变化有弹性
await page.getByRole('button', { name: 'Submit' }).click();
await page.getByLabel('Email address').fill('user@example.com');
// ❌ CSS 类选择器 — 重构时容易失效
await page.locator('.btn-primary.submit-btn').click();
await page.locator('.email-input').fill('user@example.com');
页面对象模型 + 测试文件
// pages/LoginPage.ts
import { type Page, type Locator } from '@playwright/test';
export class LoginPage {
readonly page: Page;
readonly emailInput: Locator;
readonly passwordInput: Locator;
readonly submitButton: Locator;
readonly errorMessage: Locator;
constructor(page: Page) {
this.page = page;
this.emailInput = page.getByLabel('Email address');
this.passwordInput = page.getByLabel('Password');
this.submitButton = page.getByRole('button', { name: 'Sign in' });
this.errorMessage = page.getByRole('alert');
}
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/login.spec.ts
import { test, expect } from '@playwright/test';
import { LoginPage } from '../pages/LoginPage';
test.describe('Login', () => {
let loginPage: LoginPage;
test.beforeEach(async ({ page }) => {
loginPage = new LoginPage(page);
await loginPage.goto();
});
test('successful login redirects to dashboard', async ({ page }) => {
await loginPage.login('user@example.com', 'correct-password');
await expect(page).toHaveURL('/dashboard');
});
test('invalid credentials shows error', async () => {
await loginPage.login('user@example.com', 'wrong-password');
await expect(loginPage.errorMessage).toBeVisible();
await expect(loginPage.errorMessage).toContainText('Invalid credentials');
});
});
不稳定测试的调试工作流程
// 1. 启用跟踪运行失败的测试
// playwright.config.ts
use: {
trace: 'on-first-retry',
screenshot: 'only-on-failure',
}
// 2. 使用重试重新运行以捕获跟踪
// npx playwright test --retries=2
// 3. 打开跟踪查看器检查时间线
// npx playwright show-trace test-results/.../trace.zip
// 4. 常见修复 — 用适当的等待替换任意超时
// ❌ 不稳定
await page.waitForTimeout(2000);
await page.getByRole('button', { name: 'Save' }).click();
// ✅ 可靠 — 等待元素状态
await page.getByRole('button', { name: 'Save' }).waitFor({ state: 'visible' });
await page.getByRole('button', { name: 'Save' }).click();
// 5. 验证修复 — 运行测试 10 次以确认稳定性
// npx playwright test --repeat-each=10
输出模板
在实现 Playwright 测试时,提供:
- 页面对象类
- 带有适当断言的测试文件
- 夹具设置(如果需要)
- 配置建议
知识参考
Playwright、页面对象模型、自动等待、定位器、夹具、API 模拟、跟踪查看器、视觉比较、并行执行、CI/CD 集成






