Playwright 高级配置 #
配置文件结构 #
完整配置示例 #
typescript
// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
// 全局配置
testDir: './tests',
testMatch: /.*\.spec\.ts/,
testIgnore: /.*\.skip\.ts/,
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
timeout: 30000,
globalTimeout: 60000,
// 报告器配置
reporter: [
['list'],
['html', { outputFolder: 'playwright-report', open: 'never' }],
],
// 全局设置
globalSetup: require.resolve('./global-setup'),
globalTeardown: require.resolve('./global-teardown'),
// expect 配置
expect: {
timeout: 5000,
toHaveScreenshot: {
maxDiffPixels: 100,
},
},
// use 配置
use: {
baseURL: 'http://localhost:3000',
trace: 'on-first-retry',
screenshot: 'only-on-failure',
video: 'retain-on-failure',
headless: true,
viewport: { width: 1280, height: 720 },
ignoreHTTPSErrors: true,
actionTimeout: 10000,
navigationTimeout: 30000,
},
// 项目配置
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
{
name: 'firefox',
use: { ...devices['Desktop Firefox'] },
},
{
name: 'webkit',
use: { ...devices['Desktop Safari'] },
},
{
name: 'Mobile Chrome',
use: { ...devices['Pixel 5'] },
},
{
name: 'Mobile Safari',
use: { ...devices['iPhone 12'] },
},
],
// 开发服务器
webServer: {
command: 'npm run start',
url: 'http://localhost:3000',
reuseExistingServer: !process.env.CI,
timeout: 120000,
},
});
测试运行器配置 #
测试发现 #
typescript
export default defineConfig({
// 测试目录
testDir: './tests',
// 多个目录
testDir: ['./tests', './e2e'],
// 测试文件匹配模式
testMatch: /.*\.spec\.ts/,
testMatch: ['**/*.spec.ts', '**/*.test.ts'],
// 忽略的测试文件
testIgnore: /.*\.skip\.ts/,
testIgnore: ['**/node_modules/**', '**/dist/**'],
});
并行执行 #
typescript
export default defineConfig({
// 完全并行
fullyParallel: true,
// Worker 数量
workers: 4, // 固定数量
workers: process.env.CI ? 1 : undefined, // CI 单线程
workers: '50%', // CPU 核心数的 50%
// 项目并行
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
{ name: 'webkit', use: { ...devices['Desktop Safari'] } },
],
});
重试配置 #
typescript
export default defineConfig({
// 全局重试
retries: 2,
// CI 环境重试
retries: process.env.CI ? 2 : 0,
// 特定项目重试
projects: [
{
name: 'chromium',
retries: 2,
use: { ...devices['Desktop Chrome'] },
},
],
});
超时配置 #
typescript
export default defineConfig({
// 测试超时
timeout: 30000,
// 全局超时
globalTimeout: 600000,
// expect 超时
expect: {
timeout: 5000,
},
// 操作超时
use: {
actionTimeout: 10000,
navigationTimeout: 30000,
},
});
浏览器配置 #
设备模拟 #
typescript
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
projects: [
// 桌面浏览器
{
name: 'Desktop Chrome',
use: {
...devices['Desktop Chrome'],
viewport: { width: 1920, height: 1080 },
},
},
{
name: 'Desktop Firefox',
use: { ...devices['Desktop Firefox'] },
},
{
name: 'Desktop Safari',
use: { ...devices['Desktop Safari'] },
},
// 移动设备
{
name: 'iPhone 12',
use: { ...devices['iPhone 12'] },
},
{
name: 'iPhone 12 Pro',
use: { ...devices['iPhone 12 Pro'] },
},
{
name: 'iPhone 13',
use: { ...devices['iPhone 13'] },
},
{
name: 'Pixel 5',
use: { ...devices['Pixel 5'] },
},
{
name: 'Galaxy S5',
use: { ...devices['Galaxy S5'] },
},
// 平板设备
{
name: 'iPad Pro',
use: { ...devices['iPad Pro'] },
},
{
name: 'Galaxy Tab S4',
use: { ...devices['Galaxy Tab S4'] },
},
],
});
自定义浏览器配置 #
typescript
export default defineConfig({
projects: [
{
name: 'Chrome',
use: {
// 使用安装的 Chrome
channel: 'chrome',
viewport: { width: 1920, height: 1080 },
},
},
{
name: 'Chrome Beta',
use: {
channel: 'chrome-beta',
},
},
{
name: 'Chrome Dev',
use: {
channel: 'chrome-dev',
},
},
{
name: 'Microsoft Edge',
use: {
channel: 'msedge',
},
},
{
name: 'Microsoft Edge Beta',
use: {
channel: 'msedge-beta',
},
},
],
});
浏览器启动选项 #
typescript
export default defineConfig({
use: {
// 无头模式
headless: true,
// 慢动作
launchOptions: {
slowMo: 100,
},
// 开发者工具
launchOptions: {
devtools: true,
},
// 忽略 HTTPS 错误
ignoreHTTPSErrors: true,
// 下载行为
downloadsPath: './downloads',
acceptDownloads: true,
},
});
上下文配置 #
视口和窗口 #
typescript
export default defineConfig({
use: {
// 视口大小
viewport: { width: 1280, height: 720 },
// 设备像素比
deviceScaleFactor: 2,
// 是否有触摸支持
hasTouch: true,
// 是否移动端
isMobile: true,
// 是否支持 JavaScript
javaScriptEnabled: true,
},
});
语言和区域 #
typescript
export default defineConfig({
use: {
// 语言
locale: 'zh-CN',
// 时区
timezoneId: 'Asia/Shanghai',
// 地理位置
geolocation: {
latitude: 39.9042,
longitude: 116.4074
},
// 权限
permissions: ['geolocation', 'notifications'],
// 用户代理
userAgent: 'Custom User Agent',
// 颜色方案
colorScheme: 'dark', // 'light' | 'dark' | 'no-preference'
// 减少动画
reducedMotion: 'reduce',
},
});
存储状态 #
typescript
export default defineConfig({
use: {
// 加载存储状态(cookies, localStorage)
storageState: 'auth.json',
// 或使用状态文件
storageState: {
cookies: [
{ name: 'session', value: 'abc123', domain: 'example.com', path: '/' },
],
origins: [
{
origin: 'https://example.com',
localStorage: [
{ name: 'token', value: 'xyz789' },
],
},
],
},
},
});
报告器配置 #
多报告器 #
typescript
export default defineConfig({
reporter: [
// 控制台列表
['list'],
// 详细控制台
['line'],
// 点状
['dot'],
// HTML 报告
['html', {
outputFolder: 'playwright-report',
open: 'never', // 'always' | 'never' | 'on-failure'
host: 'localhost',
port: 9323,
}],
// JSON 报告
['json', {
outputFile: 'results.json',
}],
// JUnit 报告
['junit', {
outputFile: 'junit.xml',
stripANSIControlSequences: true,
}],
// GitHub Actions
['github'],
],
});
自定义报告器 #
typescript
// my-reporter.ts
import { Reporter, TestCase, TestResult } from '@playwright/test/reporter';
class MyReporter implements Reporter {
onBegin(config, suite) {
console.log(`开始运行 ${suite.allTests().length} 个测试`);
}
onTestBegin(test: TestCase) {
console.log(`开始测试: ${test.title}`);
}
onTestEnd(test: TestCase, result: TestResult) {
console.log(`测试结束: ${test.title} - ${result.status}`);
}
onEnd(result) {
console.log(`测试完成: ${result.status}`);
}
}
export default MyReporter;
// playwright.config.ts
export default defineConfig({
reporter: [['./my-reporter.ts']],
});
全局设置 #
globalSetup 和 globalTeardown #
typescript
// global-setup.ts
import { FullConfig } from '@playwright/test';
async function globalSetup(config: FullConfig) {
console.log('全局设置开始');
// 启动测试服务器
// 初始化数据库
// 创建测试数据
// 保存认证状态
const { chromium } = require('@playwright');
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('https://example.com/login');
await page.fill('#email', 'test@example.com');
await page.fill('#password', 'password');
await page.click('button[type="submit"]');
await page.context().storageState({ path: 'auth.json' });
await browser.close();
console.log('全局设置完成');
}
export default globalSetup;
// global-teardown.ts
async function globalTeardown() {
console.log('全局清理开始');
// 清理测试数据
// 关闭服务器
console.log('全局清理完成');
}
export default globalTeardown;
// playwright.config.ts
export default defineConfig({
globalSetup: require.resolve('./global-setup'),
globalTeardown: require.resolve('./global-teardown'),
});
项目配置 #
项目依赖 #
typescript
export default defineConfig({
projects: [
// 认证设置
{
name: 'setup',
testMatch: /.*\.setup\.ts/,
},
// 依赖认证的测试
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
dependencies: ['setup'],
},
{
name: 'firefox',
use: { ...devices['Desktop Firefox'] },
dependencies: ['setup'],
},
],
});
项目特定配置 #
typescript
export default defineConfig({
projects: [
{
name: 'smoke',
testMatch: /.*smoke\.spec\.ts/,
retries: 0,
use: { ...devices['Desktop Chrome'] },
},
{
name: 'regression',
testMatch: /.*regression\.spec\.ts/,
retries: 2,
use: { ...devices['Desktop Chrome'] },
},
{
name: 'api',
testDir: './api-tests',
use: {
baseURL: 'https://api.example.com',
},
},
],
});
命令行选项 #
运行特定项目 #
bash
# 运行特定项目
npx playwright test --project=chromium
# 运行多个项目
npx playwright test --project=chromium --project=firefox
运行特定测试 #
bash
# 运行特定文件
npx playwright test login.spec.ts
# 运行特定目录
npx playwright test tests/auth/
# 运行匹配的测试
npx playwright test -g "login"
# 使用正则
npx playwright test -g "login|logout"
其他选项 #
bash
# 有头模式
npx playwright test --headed
# 调试模式
npx playwright test --debug
# UI 模式
npx playwright test --ui
# 指定 workers
npx playwright test --workers=4
# 最大失败数
npx playwright test --max-failures=3
# 重试
npx playwright test --retries=2
# 报告器
npx playwright test --reporter=html
# 生成追踪
npx playwright test --trace on
# 时间戳
npx playwright test --timestamp
环境变量 #
配置中使用环境变量 #
typescript
export default defineConfig({
use: {
baseURL: process.env.BASE_URL || 'http://localhost:3000',
},
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
});
测试中使用环境变量 #
typescript
test('使用环境变量', async ({ page }) => {
const username = process.env.TEST_USERNAME;
const password = process.env.TEST_PASSWORD;
await page.fill('#username', username);
await page.fill('#password', password);
});
最佳实践 #
1. 分离配置 #
typescript
// config/base.ts
import { defineConfig, devices } from '@playwright/test';
export const baseConfig = {
testDir: './tests',
timeout: 30000,
use: {
baseURL: 'http://localhost:3000',
trace: 'on-first-retry',
},
};
// playwright.config.ts
import { defineConfig } from '@playwright/test';
import { baseConfig } from './config/base';
export default defineConfig({
...baseConfig,
projects: [
// 项目配置
],
});
2. 使用环境区分 #
typescript
const isCI = !!process.env.CI;
const isDev = process.env.NODE_ENV === 'development';
export default defineConfig({
retries: isCI ? 2 : 0,
workers: isCI ? 1 : '50%',
reporter: isCI ? [['github'], ['html']] : [['list']],
});
3. 合理设置超时 #
typescript
export default defineConfig({
// 测试超时应该大于所有操作超时之和
timeout: 30000,
expect: {
// 断言超时
timeout: 5000,
},
use: {
// 单个操作超时
actionTimeout: 10000,
// 导航超时
navigationTimeout: 30000,
},
});
下一步 #
现在你已经掌握了高级配置,接下来学习 调试技巧 了解如何调试测试!
最后更新:2026-03-28