关于 visual-regression-testing
visual-regression-testing 是用于检查 UI 组件和页面是否出现非预期视觉变化的技能。它通过 Playwright 和 jest-image-snapshot 将截图与版本控制中的基准图比较,并提供拉取请求检查、基准更新和差异报告工作流。
主要功能
- 01捕获并版本管理截图基准
- 02将截图与基准图比较
- 03测试多种视口和主题
- 04在 GitHub Actions 中运行视觉检查
- 05生成并上传差异报告
- 06配置图像比较阈值
适用场景
- 01发现拉取请求中的非预期 UI 变化
- 02审批更改前审查视觉差异
- 03测试组件的响应式布局
- 04设计有意变更后更新基准图
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ jgtolentino/ insightpulse-odoo --skill visual-regression-testing安装后在 Claude Code 中输入/visual-regression-testing确认已加载。
详细介绍
视觉回归测试
此技能提供全面的视觉回归测试功能,用于检测 UI 组件中意外的视觉变化,防止视觉错误合并到生产环境。
概述
视觉回归测试的工作方式如下:
- 为处于已知正常状态的组件/页面截取屏幕截图(基准图)
- 代码变更后截取新的屏幕截图
- 将新截图与基准图逐像素进行比较
- 标记差异,供人工审核
框架: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 工作流:
- 检出代码并安装依赖项
- 启动本地服务
- 运行视觉回归测试
- 如果发现差异:
- 生成差异截图
- 将构件上传到 GitHub
- 在 PR 中发布带有视觉差异预览的评论
- 将检查标记为失败
- 如果没有差异,则将检查标记为通过
基准图更新工作流:
- 合并后在 main 分支上运行
- 重新生成所有基准截图
- 将更新后的基准图提交回代码库
文件结构
.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 审核
审核者可以:
- 检查 CI 状态,查看是否存在视觉回归失败
- 点击 PR 评论中的构件链接
- 查看视觉差异报告
- 根据视觉影响批准或请求修改
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/- 测试代码和实用工具
外部资源
- Ant Design 视觉回归测试 - 原始方法
- Playwright 截图 - 截图 API 文档
- jest-image-snapshot - 快照匹配器
- Argos CI - 视觉测试平台(Ant Design 使用)
高级功能
多浏览器测试
// 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 应:
-
搭建基础设施
- 创建 GitHub Actions 工作流
- 配置 Playwright 和 jest-image-snapshot
- 设置基线目录结构
- 为常见操作添加 npm 脚本
-
生成测试
- 为每个组件创建测试文件
- 配置合适的阈值
- 处理动态内容遮罩
- 设置多视口测试
-
集成到 CI/CD
- 配置 PR 检查
- 设置基线更新工作流
- 配置构建产物上传
- 添加 PR 评论并附上差异预览
-
提供文档
- 记录基线更新流程
- 创建故障排除指南
- 添加常见场景示例
- 记录阈值配置
示例:完整实现
以下文件提供了完整的实现示例:
.github/workflows/visual-regression-pr.yml:1- 完整的 PR 工作流tests/shared/imageTest.tsx:1- 基线截图实用工具scripts/visual-regression/compare-screenshots.ts:1- 比较逻辑
这项技能支持全面的视觉回归测试,可在视觉错误进入生产环境之前将其捕获,并确保整个应用的 UI 保持一致。
评论
支持 Markdown