mcpField
W
webapp-testing

webapp-testing

github.com/pixel-process-ug测试与质量382 次安装33 周前更新
代码仓库

关于 webapp-testing

webapp-testing 是使用 Playwright 测试 Web 应用的技能,面向开发者,涵盖端到端流程、视觉检查、无障碍审计、网络模拟和移动视口测试。

主要功能

  1. 01使用 Playwright 进行端到端测试
  2. 02截图与视觉回归检查
  3. 03分析浏览器控制台错误
  4. 04使用 axe-core 执行无障碍审计
  5. 05模拟网络请求
  6. 06测试移动视口

适用场景

  1. 01验证关键用户流程
  2. 02检查页面布局变化
  3. 03审计页面无障碍情况
  4. 04测试移动端响应行为

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/pixel-process-ug/superkit-agents --skill webapp-testing

安装后在 Claude Code 中输入/webapp-testing确认已加载。

详细介绍

Web 应用测试

概述

使用 Playwright 作为主要工具进行全面的 Web 应用测试。本技能涵盖端到端测试工作流,包括用于视觉验证的屏幕截图捕获、浏览器控制台日志分析、用户交互模拟、视觉回归测试、使用 axe-core 进行无障碍审计、网络请求模拟以及移动设备视口测试。

开始时请声明:“我正在使用 webapp-testing 技能进行基于 Playwright 的 Web 应用测试。”


阶段 1:测试规划

目标: 确定测试内容并搭建基础设施。

操作
  1. 确定需要测试的关键用户流程
  2. 定义测试环境和视口
  3. 设置测试 fixture 和数据
  4. 配置 Playwright 项目设置
  5. 建立视觉基准屏幕截图
用户流程优先级决策表
流程类型优先级测试深度
身份验证(登录/登出/注册)关键完整的正常流程 + 错误路径
核心业务工作流(购买、提交)关键完整的正常流程 + 错误 + 边界情况
导航和路由高所有主要路由
搜索和筛选高常见查询 + 空状态
设置和个人资料中正常流程
管理员/后台中仅关键操作
停止——在进入阶段 2 前,不要继续:
  • 已确定关键用户流程并排定优先级
  • 已定义测试环境和视口
  • Playwright 配置已就绪
  • 已定义测试数据策略

阶段 2:测试实现

目标: 使用页面对象模型和无障碍定位器编写测试。

操作
  1. 为关键页面编写页面对象模型
  2. 实现端到端测试场景
  3. 添加视觉回归快照
  4. 集成无障碍检查
  5. 为隔离测试配置网络模拟
Playwright 配置
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  testDir: './tests/e2e',
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 1 : undefined,
  reporter: [
    ['html', { open: 'never' }],
    ['junit', { outputFile: 'test-results/junit.xml' }],
  ],
  use: {
    baseURL: 'http://localhost:3000',
    trace: 'on-first-retry',
    screenshot: 'only-on-failure',
    video: 'retain-on-failure',
  },
  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 13'] } },
  ],
  webServer: {
    command: 'npm run dev',
    url: 'http://localhost:3000',
    reuseExistingServer: !process.env.CI,
  },
});
页面对象模型
class LoginPage {
  constructor(private page: Page) {}

  readonly emailInput = this.page.getByLabel('Email');
  readonly passwordInput = this.page.getByLabel('Password');
  readonly submitButton = this.page.getByRole('button', { name: 'Sign in' });
  readonly errorMessage = this.page.getByRole('alert');

  async login(email: string, password: string) {
    await this.emailInput.fill(email);
    await this.passwordInput.fill(password);
    await this.submitButton.click();
  }

  async expectError(message: string) {
    await expect(this.errorMessage).toContainText(message);
  }
}
定位器选择决策表
定位器类型优先级使用时机
getByRole首选具有 ARIA 角色的任何元素(按钮、链接、标题)
getByLabel次选带有标签的表单字段
getByPlaceholder第三选择没有可见标签的字段
getByText第四选择非交互式可见文本
getByTestId最后选择没有可用的无障碍定位器时
CSS 选择器 / XPath永不使用样式变更时会失效
停止——在进入阶段 3 前,不要继续:
  • 已为关键页面创建页面对象模型
  • 测试仅使用无障碍定位器
  • 已建立视觉基准
  • 已集成无障碍检查
  • 已为隔离测试配置网络模拟

阶段 3:CI 集成

目标: 配置可靠、快速的 CI 测试执行。

操作
  1. 配置无头浏览器执行
  2. 设置屏幕截图产物收集
  3. 配置重试和不稳定测试检测
  4. 添加报告(HTML 报告、JUnit XML)
  5. 设置视觉差异审查流程
CI 配置检查清单
  • 测试在 CI 中以无头模式运行
  • 已启用重试(CI 中重试 2 次)
  • 失败时收集屏幕截图和视频产物
  • 输出用于 CI 集成的 JUnit XML
  • 生成供手动审查的 HTML 报告
  • 合并前审查视觉差异快照
停止——满足以下条件时,CI 集成完成:
  • 测试在 CI 流水线中可靠运行
  • 失败时会收集产物
  • 已识别并修复不稳定测试(而非跳过)

屏幕截图捕获模式

全页
test('homepage renders correctly', async ({ page }) => {
  await page.goto('/');
  await expect(page).toHaveScreenshot('homepage.png', {
    fullPage: true,
    maxDiffPixelRatio: 0.01,
  });
});
元素级
test('navigation bar matches design', async ({ page }) => {
  await page.goto('/');
  const nav = page.getByRole('navigation');
  await expect(nav).toHaveScreenshot('navbar.png');
});
动态内容遮罩
test('dashboard layout', async ({ page }) => {
  await page.goto('/dashboard');
  await expect(page).toHaveScreenshot('dashboard.png', {
    mask: [
      page.locator('[data-testid="timestamp"]'),
      page.locator('[data-testid="user-avatar"]'),
      page.locator('.chart-container'),
    ],
    animations: 'disabled',
  });
});

浏览器日志分析

test('no console errors on page load', async ({ page }) => {
  const consoleErrors: string[] = [];

  page.on('console', msg => {
    if (msg.type() === 'error') consoleErrors.push(msg.text());
  });
  page.on('pageerror', error => {
    consoleErrors.push(error.message);
  });

  await page.goto('/');
  await page.waitForLoadState('networkidle');
  expect(consoleErrors).toEqual([]);
});

使用 axe-core 进行无障碍测试

import AxeBuilder from '@axe-core/playwright';

test('page has no accessibility violations', async ({ page }) => {
  await page.goto('/');
  const results = await new AxeBuilder({ page })
    .withTags(['wcag2a', 'wcag2aa', 'wcag21aa'])
    .exclude('.third-party-widget')
    .analyze();
  expect(results.violations).toEqual([]);
});

网络请求模拟

test('displays users from API', async ({ page }) => {
  await page.route('**/api/users', async route => {
    await route.fulfill({
      status: 200,
      contentType: 'application/json',
      body: JSON.stringify([{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]),
    });
  });
  await page.goto('/users');
  await expect(page.getByText('Alice')).toBeVisible();
});

test('handles API errors gracefully', async ({ page }) => {
  await page.route('**/api/users', route =>
    route.fulfill({ status: 500, body: 'Internal Server Error' })
  );
  await page.goto('/users');
  await expect(page.getByText('Something went wrong')).toBeVisible();
});

移动设备视口测试

test.describe('mobile responsive', () => {
  test.use({ viewport: { width: 375, height: 667 } });

  test('hamburger menu works', async ({ page }) => {
    await page.goto('/');
    await expect(page.getByRole('navigation')).not.toBeVisible();
    await page.getByRole('button', { name: 'Menu' }).click();
    await expect(page.getByRole('navigation')).toBeVisible();
  });
});

测试组织

tests/
  e2e/
    auth/
      login.spec.ts
      register.spec.ts
    checkout/
      cart.spec.ts
      payment.spec.ts
    fixtures/
      test-data.ts
      auth.setup.ts
    pages/
      login.page.ts
      dashboard.page.ts
    utils/
      helpers.ts

反模式 / 常见错误

反模式错误原因正确做法
CSS 选择器或 XPath样式变更会导致失效使用可访问的定位器(角色、标签、文本)
page.waitForTimeout()延迟时间随意,测试不稳定使用 expect().toBeVisible() 或类似方法
详细测试第三方组件被测内容并非你的代码测试集成,而不是第三方组件的内部实现
硬编码测试数据在不同环境中会失效使用夹具和工厂
测试依赖执行顺序脆弱且难以调试每个测试都必须独立
忽略不稳定的测试会削弱对测试套件的信任修复根本原因或将其隔离
截图未遮盖动态内容每次截图都不同,测试总会失败遮盖时间戳、头像和图表
不进行无障碍检查缺少关键质量门槛在每个页面上使用 axe-core

集成点

技能关联
senior-frontend通过端到端测试检验前端组件
testing-strategy端到端测试位于测试金字塔顶端
acceptance-testing用户流程测试可作为验收测试
performance-optimization可通过端到端测试验证性能预算
code-review检查测试是否使用可访问的定位器
security-review在端到端测试中测试安全标头和身份验证流程

质量检查清单

  • 覆盖所有关键用户流程
  • 测试使用可访问的定位器(角色、标签、文本)
  • 对隔离测试进行网络模拟
  • 已审核并批准视觉回归基线
  • 对所有页面进行无障碍扫描
  • 针对响应式功能进行移动视口测试
  • 不使用 waitForTimeout(使用恰当的断言)
  • 已配置带重试的 CI 流水线
  • 失败时收集截图产物
  • 已识别并修复不稳定的测试(而非跳过)

技能类型

FLEXIBLE — 根据项目的关键路径调整测试深度。强烈建议采用页面对象模型模式和可访问的定位器。每个页面都必须进行无障碍检查。合并前必须审核视觉回归基线。

评论

支持 Markdown