Playwright 测试配置与使用指南
Playwright 是一个现代化的 Web 应用端到端测试框架,支持 Chromium、WebKit 和 Firefox,可以在 Windows、Linux 和 macOS 上运行。
安装
初始化项目
kotlin
npm init playwright@latest
安装过程中会询问:
- TypeScript 或 JavaScript(默认:TypeScript)
- 测试文件夹名称(默认:tests,如果 tests 已存在则用 e2e)
- 是否添加 GitHub Actions 工作流(推荐)
- 是否安装 Playwright 浏览器(默认:是)
系统要求
- Node.js:最新 20.x、22.x 或 24.x
- macOS 14 (Ventura) 或更高版本
- Debian 12/13,Ubuntu 22.04/24.04
项目结构
安装后生成以下结构:
csharp
playwright.config.ts # 测试配置
package.json
package-lock.json
tests/
example.spec.ts # 示例测试
编写测试
基础测试示例
javascript
import { test, expect } from '@playwright/test';
test('基础测试', async ({ page }) => {
await page.goto('https://example.com');
await expect(page).toHaveTitle(/Example Domain/);
});
使用 Locators
rust
test('表单提交测试', async ({ page }) => {
await page.goto('https://example.com/form');
// 填写表单
await page.fill('input[name="email"]', 'test@example.com');
await page.fill('input[name="password"]', 'password123');
// 点击提交按钮
await page.click('button[type="submit"]');
// 验证成功跳转
await expect(page).toHaveURL(/.*dashboard/);
});
断言
Playwright 提供了丰富的断言方法:
scss
// 页面状态断言
await expect(page).toHaveTitle(/Page Title/);
await expect(page).toHaveURL('https://example.com');
// 元素可见性断言
await expect(page.locator('.header')).toBeVisible();
await expect(page.locator('.loading')).toBeHidden();
// 文本内容断言
await expect(page.locator('h1')).toHaveText('Welcome');
await expect(page.locator('.count')).toContainText('5');
// 属性断言
await expect(page.locator('input')).toHaveAttribute('type', 'email');
运行测试
运行所有测试
bash
npx playwright test
运行单个测试文件
bash
npx playwright test tests/example.spec.ts
有头模式运行(显示浏览器窗口)
bash
npx playwright test --headed
运行特定浏览器
ini
npx playwright test --project=chromium
npx playwright test --project=webkit
UI 模式
UI 模式提供监视模式、实时步骤视图、时间旅行调试等:
bash
npx playwright test --ui
HTML 测试报告
测试运行后,HTML Reporter 提供可过滤的仪表板,按浏览器、通过、失败、跳过、不稳定等分类:
sql
npx playwright show-report
配置文件
playwright.config.ts 基础配置
php
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
// 测试文件夹
testDir: './tests',
// 完全并行运行测试
fullyParallel: true,
// CI 中失败时重试
forbidOnly: !!process.env.CI,
// CI 中重试次数
retries: process.env.CI ? 2 : 0,
// 并行工作进程数
workers: process.env.CI ? 1 : undefined,
// 报告器
reporter: 'html',
use: {
// 基础 URL
baseURL: 'http://localhost:3000',
// 追踪重试失败的测试
trace: 'on-first-retry',
},
// 配置不同浏览器
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
{
name: 'firefox',
use: { ...devices['Desktop Firefox'] },
},
{
name: 'webkit',
use: { ...devices['Desktop Safari'] },
},
],
});
高级功能
测试夹具(Fixtures)
csharp
import { test as base } from '@playwright/test';
// 自定义 fixture
type MyFixtures = {
authenticatedPage: Page;
};
const test = base.extend<MyFixtures>({
authenticatedPage: async ({ page }, use) => {
// 登录
await page.goto('/login');
await page.fill('input[name="email"]', 'test@example.com');
await page.fill('input[name="password"]', 'password');
await page.click('button[type="submit"]');
// 使用已认证的页面
await use(page);
},
});
test('使用自定义 fixture', async ({ authenticatedPage }) => {
await authenticatedPage.goto('/dashboard');
await expect(authenticatedPage).toHaveURL(/.*dashboard/);
});
代码生成(Codegen)
Playwright Codegen 可以通过录制用户操作生成测试代码:
arduino
npx playwright codegen https://example.com
追踪查看器
查看测试失败的详细追踪:
python
npx playwright show-trace trace.zip
更新 Playwright
sql
npm install -D @playwright/test@latest
npx playwright install --with-deps
检查版本:
css
npx playwright --version
最佳实践
-
使用 Locators 而不是 Selectors
javascript// ✅ 推荐 await page.locator('button').click(); // ❌ 不推荐 await page.$('button').click(); -
使用 Playwright 的等待机制
csharp// 自动等待元素可交互 await page.click('button'); // 显式等待 await page.waitForSelector('.loaded'); -
使用页面对象模式(Page Object Model)
typescriptclass LoginPage { constructor(private page: Page) {} async login(email: string, password: string) { await this.page.fill('input[name="email"]', email); await this.page.fill('input[name="password"]', password); await this.page.click('button[type="submit"]'); } } -
隔离测试数据
darttest.use({ storageState: 'auth.json' }); test('需要登录的测试', async ({ page }) => { // 测试逻辑 });