Playwright测试专家Skill playwright-expert

这是一个用于 Playwright 端到端测试、浏览器自动化、跨浏览器测试、视觉回归、网络拦截和 CI 集成的技能。适用于 E2E 测试设置、处理不稳定测试或浏览器自动化挑战。关键词:Playwright、E2E 测试、浏览器自动化、跨浏览器测试、视觉回归、网络拦截、CI 集成。

测试 0 次安装 0 次浏览 更新于 3/19/2026

name: playwright-expert description: Playwright E2E 测试专家,用于浏览器自动化、跨浏览器测试、视觉回归、网络拦截和 CI 集成。用于 E2E 测试设置、不稳定测试或浏览器自动化挑战。

Playwright 专家

在 Playwright 上进行 E2E 测试、浏览器自动化和跨浏览器测试的专家。

何时调用

推荐专家

  • 单元/集成测试: 推荐 jest-expert 或 vitest-expert
  • React 组件测试: 推荐 testing-expert
  • 仅 API 测试: 推荐 rest-api-expert

环境检测

npx playwright --version 2>/dev/null
ls playwright.config.* 2>/dev/null
find . -name "*.spec.ts" -path "*e2e*" | head -5

问题手册

项目设置

# 初始化 Playwright
npm init playwright@latest

# 安装浏览器
npx playwright install
// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  testDir: './e2e',
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 1 : undefined,
  reporter: 'html',
  use: {
    baseURL: 'http://localhost:3000',
    trace: 'on-first-retry',
    screenshot: 'only-on-failure',
  },
  projects: [
    { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
    { name: 'firefox', use: { ...devices['Desktop Firefox'] } },
    { name: 'webkit', use: { ...devices['Desktop Safari'] } },
  ],
  webServer: {
    command: 'npm run dev',
    url: 'http://localhost:3000',
    reuseExistingServer: !process.env.CI,
  },
});

编写测试

import { test, expect } from '@playwright/test';

test.describe('认证', () => {
  test('应成功登录', async ({ page }) => {
    await page.goto('/login');
    
    await page.fill('[data-testid="email"]', 'user@example.com');
    await page.fill('[data-testid="password"]', 'password123');
    await page.click('[data-testid="submit"]');
    
    await expect(page).toHaveURL('/dashboard');
    await expect(page.locator('h1')).toContainText('欢迎');
  });

  test('应显示无效凭据错误', async ({ page }) => {
    await page.goto('/login');
    
    await page.fill('[data-testid="email"]', 'wrong@example.com');
    await page.fill('[data-testid="password"]', 'wrong');
    await page.click('[data-testid="submit"]');
    
    await expect(page.locator('.error-message')).toBeVisible();
  });
});

页面对象模型

// pages/login.page.ts
import { Page, Locator } from '@playwright/test';

export class LoginPage {
  readonly page: Page;
  readonly emailInput: Locator;
  readonly passwordInput: Locator;
  readonly submitButton: Locator;

  constructor(page: Page) {
    this.page = page;
    this.emailInput = page.locator('[data-testid="email"]');
    this.passwordInput = page.locator('[data-testid="password"]');
    this.submitButton = page.locator('[data-testid="submit"]');
  }

  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();
  }
}

// 在测试中使用
test('登录测试', async ({ page }) => {
  const loginPage = new LoginPage(page);
  await loginPage.goto();
  await loginPage.login('user@example.com', 'password');
});

网络拦截

test('模拟 API 响应', async ({ page }) => {
  await page.route('**/api/users', async (route) => {
    await route.fulfill({
      status: 200,
      body: JSON.stringify([{ id: 1, name: '模拟用户' }]),
    });
  });

  await page.goto('/users');
  await expect(page.locator('.user-name')).toContainText('模拟用户');
});

视觉回归

test('视觉比较', async ({ page }) => {
  await page.goto('/');
  await expect(page).toHaveScreenshot('homepage.png', {
    maxDiffPixelRatio: 0.1,
  });
});

处理不稳定测试

// 重试不稳定测试
test('不稳定网络测试', async ({ page }) => {
  test.slow(); // 三倍超时
  
  await page.goto('/');
  await page.waitForLoadState('networkidle');
  
  // 使用轮询断言
  await expect(async () => {
    const response = await page.request.get('/api/status');
    expect(response.ok()).toBeTruthy();
  }).toPass({ timeout: 10000 });
});

运行测试

# 运行所有测试
npx playwright test

# 运行特定文件
npx playwright test login.spec.ts

# 以头模式运行
npx playwright test --headed

# 以 UI 模式运行
npx playwright test --ui

# 调试模式
npx playwright test --debug

# 生成报告
npx playwright show-report

代码审查清单

  • [ ] 使用 data-testid 属性作为选择器
  • [ ] 复杂流程使用页面对象模型
  • [ ] 网络请求在需要时模拟
  • [ ] 正确等待策略(无任意等待)
  • [ ] 配置失败时截图
  • [ ] 启用并行执行

反模式

  1. 硬编码等待 - 使用正确断言
  2. 脆弱选择器 - 使用 data-testid
  3. 测试间共享状态 - 隔离测试
  4. CI 中无重试 - 为不稳定添加重试
  5. 测试实现细节 - 测试用户行为