mcpField
V
visual-regression-testing

visual-regression-testing

github.com/jgtolentino测试与质量2245 次安装33 周前更新
代码仓库

关于 visual-regression-testing

visual-regression-testing 是用于检查 UI 组件和页面是否出现非预期视觉变化的技能。它通过 Playwright 和 jest-image-snapshot 将截图与版本控制中的基准图比较,并提供拉取请求检查、基准更新和差异报告工作流。

主要功能

  1. 01捕获并版本管理截图基准
  2. 02将截图与基准图比较
  3. 03测试多种视口和主题
  4. 04在 GitHub Actions 中运行视觉检查
  5. 05生成并上传差异报告
  6. 06配置图像比较阈值

适用场景

  1. 01发现拉取请求中的非预期 UI 变化
  2. 02审批更改前审查视觉差异
  3. 03测试组件的响应式布局
  4. 04设计有意变更后更新基准图

安装

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

$npx skills add https://github.com/jgtolentino/insightpulse-odoo --skill visual-regression-testing

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

详细介绍

视觉回归测试

此技能提供全面的视觉回归测试功能,用于检测 UI 组件中意外的视觉变化,防止视觉错误合并到生产环境。

概述

视觉回归测试的工作方式如下:

  1. 为处于已知正常状态的组件/页面截取屏幕截图(基准图)
  2. 代码变更后截取新的屏幕截图
  3. 将新截图与基准图逐像素进行比较
  4. 标记差异,供人工审核

框架:Playwright + jest-image-snapshot 方法:基于 Ant Design 的视觉回归测试方法

核心功能

1. 屏幕截图基准图管理

创建和更新基准截图,将其作为视觉对比的事实来源。

实现:tests/shared/imageTest.tsx

主要功能:

  • 自动捕获所有组件演示的基准图
  • 对基准图进行版本控制
  • 发生有意的变更时,轻松更新基准图
  • 支持多种视口尺寸和主题
2. 视觉对比测试

实现:scripts/visual-regression/

核心测试工作流:

// Example structure from tests/shared/imageTest.tsx
import { test, expect } from '@playwright/test';

test('component visual regression', async ({ page }) => {
  await page.goto('http://localhost:5173/component-demo');
  await page.waitForLoadState('networkidle');

  // Take screenshot and compare with baseline
  const screenshot = await page.screenshot();
  expect(screenshot).toMatchImageSnapshot({
    customSnapshotsDir: '__image_snapshots__',
    customDiffDir: '__image_snapshots__/diff',
    threshold: 0.1, // 0.1% pixel difference tolerance
  });
});
3. CI/CD 集成

实现:.github/workflows/visual-regression-*.yml

工作流文件:

  • visual-regression-pr.yml - 在拉取请求上运行
  • visual-regression-baseline.yml - 在 main 分支上更新基准图
  • visual-regression-report.yml - 生成并上传差异报告

PR 工作流:

  1. 检出代码并安装依赖项
  2. 启动本地服务
  3. 运行视觉回归测试
  4. 如果发现差异:
    • 生成差异截图
    • 将构件上传到 GitHub
    • 在 PR 中发布带有视觉差异预览的评论
    • 将检查标记为失败
  5. 如果没有差异,则将检查标记为通过

基准图更新工作流:

  1. 合并后在 main 分支上运行
  2. 重新生成所有基准截图
  3. 将更新后的基准图提交回代码库

文件结构

.github/workflows/
  ├── visual-regression-pr.yml          # PR visual checks
  ├── visual-regression-baseline.yml    # Baseline updates
  └── visual-regression-report.yml      # Diff reporting

tests/shared/
  └── imageTest.tsx                     # Baseline screenshot utilities

scripts/visual-regression/
  ├── capture-baselines.ts              # Generate baseline screenshots
  ├── compare-screenshots.ts            # Compare current vs baseline
  ├── generate-report.ts                # Create HTML diff report
  └── upload-to-storage.ts              # Upload to OSS/S3

__image_snapshots__/
  ├── baseline/                         # Baseline screenshots
  ├── current/                          # Latest test screenshots
  └── diff/                             # Difference highlights

使用模式

组件开发

开发新组件时:

# 1. Create component and demos
npm run dev

# 2. Generate initial baseline
npm run visual:baseline

# 3. Make changes
# ... edit component code ...

# 4. Run visual regression test
npm run visual:test

# 5. Review diffs (if any)
npm run visual:report

# 6. Update baseline if changes are intentional
npm run visual:update-baseline
PR 审核

审核者可以:

  1. 检查 CI 状态,查看是否存在视觉回归失败
  2. 点击 PR 评论中的构件链接
  3. 查看视觉差异报告
  4. 根据视觉影响批准或请求修改
CI/CD 流水线
# Example from .github/workflows/visual-regression-pr.yml
name: Visual Regression Testing

on:
  pull_request:
    branches: [main, develop]

jobs:
  visual-regression:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Install Playwright
        run: npx playwright install --with-deps chromium

      - name: Start dev server
        run: npm run dev &

      - name: Wait for server
        run: npx wait-on http://localhost:5173

      - name: Run visual regression tests
        run: npm run visual:test

      - name: Upload diff artifacts
        if: failure()
        uses: actions/upload-artifact@v4
        with:
          name: visual-diffs
          path: __image_snapshots__/diff/

      - name: Generate report
        if: failure()
        run: npm run visual:report

      - name: Comment PR with results
        if: failure()
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const report = fs.readFileSync('visual-report.md', 'utf8');
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: report
            });

最佳实践

1. 基准图管理
  • 对基准图进行版本控制:将基准截图提交到 git
  • 有选择地更新:仅为有意的视觉变更更新基准图
  • 记录更新内容:在 PR 描述中注明基准图更新
  • 保持平台一致性:在 CI 环境中生成基准图,而非本地环境
2. 编写测试
  • 等待页面稳定:始终使用 page.waitForLoadState('networkidle')
  • 隐藏动态内容:屏蔽时间戳、动画和随机数据
  • 测试关键路径:重点测试面向用户的组件
  • 使用多个视口:测试响应式断点
  • 测试不同主题:如适用,测试浅色/深色模式
3. 阈值配置
// Strict comparison for critical UI
expect(screenshot).toMatchImageSnapshot({ threshold: 0.01 });

// Relaxed for minor anti-aliasing differences
expect(screenshot).toMatchImageSnapshot({ threshold: 0.1 });

// Very relaxed for charts/animations
expect(screenshot).toMatchImageSnapshot({ threshold: 0.5 });
4. 性能优化
  • 并行执行:通过多个工作线程并行运行测试
  • 选择性测试:在 PR 中仅测试受影响的组件
  • 增量基准图:缓存并复用未变更的基准图
  • 无头模式:在 CI 中始终以无头模式运行
5. 减少误报

误报的常见原因:

  • 不同操作系统之间的字体渲染差异
  • 抗锯齿差异
  • 动画时序
  • 浏览器版本差异
  • 系统字体

解决方案:

  • 使用 Docker 保持环境一致
  • 使用 CSS 冻结动画
  • 使用一致的浏览器版本
  • 对细微差异提高阈值

与现有测试的集成

视觉回归测试可补充现有测试策略:

Unit Tests (Jest)
  ↓
Component Tests (React Testing Library)
  ↓
Visual Regression (Playwright + jest-image-snapshot)
  ↓
E2E Tests (Playwright)
  ↓
Manual QA

故障排查

“截图不匹配,但看起来完全相同”

原因:特定平台的渲染差异 解决方案:

expect(screenshot).toMatchImageSnapshot({
  failureThreshold: 0.01,
  failureThresholdType: 'percent'
});
“依赖更新后基线过时”

原因:库更新更改了组件样式 解决方案:

# Review changes first
npm run visual:test

# Update all baselines if changes are expected
npm run visual:update-baseline
“CI 失败,但本地测试通过”

原因:环境不同(字体、操作系统、浏览器版本) 解决方案:在本地使用 Docker 或 GitHub Actions

# Run in Docker matching CI environment
docker run -v $(pwd):/app -w /app mcr.microsoft.com/playwright:v1.40.0 npm run visual:test

参考资料

实现文件
  • .github/workflows/visual-regression-*.yml - CI/CD 工作流
  • tests/shared/imageTest.tsx - 基线截图实现
  • scripts/visual-regression/ - 测试代码和实用工具
外部资源

高级功能

多浏览器测试
// Test across Chromium, Firefox, and WebKit
import { devices } from '@playwright/test';

const browsers = ['chromium', 'firefox', 'webkit'];
for (const browser of browsers) {
  test(`visual regression on ${browser}`, async ({ playwright }) => {
    const browserInstance = await playwright[browser].launch();
    const page = await browserInstance.newPage();
    // ... test logic
  });
}
响应式测试
// Test multiple viewports
const viewports = [
  { width: 375, height: 667, name: 'mobile' },
  { width: 768, height: 1024, name: 'tablet' },
  { width: 1920, height: 1080, name: 'desktop' },
];

for (const viewport of viewports) {
  test(`visual regression ${viewport.name}`, async ({ page }) => {
    await page.setViewportSize(viewport);
    // ... test logic
  });
}
组件隔离
// Test individual component variants
const variants = ['default', 'primary', 'danger', 'disabled'];

for (const variant of variants) {
  test(`button ${variant} variant`, async ({ page }) => {
    await page.goto(`http://localhost:5173/button/${variant}`);
    await page.waitForLoadState('networkidle');
    const screenshot = await page.locator('[data-testid="button"]').screenshot();
    expect(screenshot).toMatchImageSnapshot({
      customSnapshotIdentifier: `button-${variant}`
    });
  });
}

Agent 能力

当用户请求视觉回归测试时,Agent 应:

  1. 搭建基础设施

    • 创建 GitHub Actions 工作流
    • 配置 Playwright 和 jest-image-snapshot
    • 设置基线目录结构
    • 为常见操作添加 npm 脚本
  2. 生成测试

    • 为每个组件创建测试文件
    • 配置合适的阈值
    • 处理动态内容遮罩
    • 设置多视口测试
  3. 集成到 CI/CD

    • 配置 PR 检查
    • 设置基线更新工作流
    • 配置构建产物上传
    • 添加 PR 评论并附上差异预览
  4. 提供文档

    • 记录基线更新流程
    • 创建故障排除指南
    • 添加常见场景示例
    • 记录阈值配置

示例:完整实现

以下文件提供了完整的实现示例:

  • .github/workflows/visual-regression-pr.yml:1 - 完整的 PR 工作流
  • tests/shared/imageTest.tsx:1 - 基线截图实用工具
  • scripts/visual-regression/compare-screenshots.ts:1 - 比较逻辑

这项技能支持全面的视觉回归测试,可在视觉错误进入生产环境之前将其捕获,并确保整个应用的 UI 保持一致。

评论

支持 Markdown