# 视觉回归测试 (Visual Regression Testing) 本项目使用 [Playwright](https://playwright.dev/) 的 `toHaveScreenshot()` API 实现视觉回归测试,对关键页面在多种视口与主题下进行像素级快照对比,以捕获 UI 的意外变化。 ## 目录结构 ``` tests/visual/ ├── visual.config.ts # 视觉测试配置(页面、视口、主题、快照路径) ├── homepage.spec.ts # 登录页视觉测试 ├── admin-dashboard.spec.ts # 管理员仪表盘视觉测试 ├── teacher-dashboard.spec.ts # 教师仪表盘视觉测试 ├── student-dashboard.spec.ts # 学生仪表盘视觉测试 ├── helpers/ │ ├── auth.ts # 认证辅助(登录、setupAuthState) │ └── visual-helpers.ts # 视觉通用辅助(视口、主题、遮罩) └── __screenshots__/ # 快照基线存储目录(自动生成) ``` ## 覆盖范围 | 页面 | 路径 | 视口 | 主题 | 是否需要登录 | |------|------|------|------|--------------| | 登录页 | `/login` | desktop / tablet / mobile | light / dark | 否 | | 管理员仪表盘 | `/admin/dashboard` | desktop / tablet / mobile | light / dark | 是 (admin) | | 教师仪表盘 | `/teacher/dashboard` | desktop / tablet / mobile | light / dark | 是 (teacher) | | 学生仪表盘 | `/student/dashboard` | desktop / tablet / mobile | light / dark | 是 (student) | 视口尺寸: - desktop: 1920 × 1080 - tablet: 768 × 1024 - mobile: 375 × 812 ## 运行测试 ### 前置条件 - 需要启动开发服务器(Playwright 会通过 `webServer` 配置自动启动) - 需要登录的视觉测试需要 `DATABASE_URL` 环境变量,否则会自动跳过 - 测试账号默认为 `admin@xiaoxue.edu.cn / 123456`,可通过环境变量覆盖 ### 运行命令 ```bash # 运行所有视觉回归测试 npm run test:visual # 运行单个测试文件 npx playwright test --project=visual-chromium tests/visual/homepage.spec.ts # 以 UI 模式运行(便于调试) npx playwright test --project=visual-chromium --ui ``` ### 环境变量 | 变量 | 默认值 | 说明 | |------|--------|------| | `DATABASE_URL` | - | 数据库连接串,未设置时需要登录的测试会跳过 | | `VISUAL_ADMIN_EMAIL` | `admin@xiaoxue.edu.cn` | 管理员测试账号 | | `VISUAL_ADMIN_PASSWORD` | `123456` | 管理员测试密码 | | `VISUAL_TEACHER_EMAIL` | `admin@xiaoxue.edu.cn` | 教师测试账号 | | `VISUAL_TEACHER_PASSWORD` | `123456` | 教师测试密码 | | `VISUAL_STUDENT_EMAIL` | `admin@xiaoxue.edu.cn` | 学生测试账号 | | `VISUAL_STUDENT_PASSWORD` | `123456` | 学生测试密码 | ## 更新基线 当 UI 发生**预期内**的变化时,需要更新快照基线: ```bash # 更新所有视觉快照基线 npm run test:visual:update # 更新单个测试文件的基线 npx playwright test --project=visual-chromium tests/visual/homepage.spec.ts --update-snapshots ``` 更新后的快照应作为 PR 的一部分提交到版本库,以便团队评审 UI 变更。 ## 处理误报 视觉测试可能因为动态内容(时间戳、用户名、实时数据等)产生误报。本项目通过以下方式消除误报: ### 1. 动态元素遮罩 `maskDynamicElements()` 辅助函数会自动遮罩以下选择器: - `[data-testid='timestamp']` - `[data-testid='current-time']` - `[data-testid='user-avatar']` - `[data-testid='user-name']` - `time` - `[data-visual-dynamic]` 可在测试中追加额外需要遮罩的选择器: ```ts const masks = await maskDynamicElements(page, ["[data-testid='stat-card-value']"]) ``` ### 2. 标记动态元素 在组件代码中为动态元素添加 `data-visual-dynamic` 属性,即可自动被遮罩: ```tsx
{new Date().toLocaleString()}
``` ### 3. 调整容差 `playwright.config.ts` 中配置了默认容差 `maxDiffPixelRatio: 0.01`(允许 1% 像素差异)。若特定页面需要更宽松的容差,可在断言时覆盖: ```ts await expect(page).toHaveScreenshot("name.png", { maxDiffPixelRatio: 0.05, }) ``` ### 4. 禁用动画 默认配置 `animations: "disabled"`,避免动画过渡态导致快照不稳定。 ## CI 集成 ### GitHub Actions 示例 ```yaml name: Visual Regression on: pull_request: paths: - "src/**" - "tests/visual/**" - "playwright.config.ts" jobs: visual: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 cache: npm - run: npm ci - run: npx playwright install --with-deps chromium # 启动数据库(按需) - run: npm run db:setup env: DATABASE_URL: ${{ secrets.TEST_DATABASE_URL }} - name: Run visual tests run: npm run test:visual env: DATABASE_URL: ${{ secrets.TEST_DATABASE_URL }} CI: "true" - name: Upload snapshot diff if: failure() uses: actions/upload-artifact@v4 with: name: snapshot-diff path: test-results/ retention-days: 7 ``` ### CI 注意事项 1. **快照基线需提交到版本库**: `tests/visual/__screenshots__/` 目录应纳入 Git 跟踪 2. **跨平台一致性**: 不同操作系统的字体渲染存在差异,建议 CI 与本地使用相同的 Linux 容器环境。若本地为 Windows/macOS,可能出现少量误报,以 CI 结果为准 3. **storageState 缓存**: `tests/visual/.auth/` 目录应加入 `.gitignore`,不要提交登录态文件 ## 与 E2E 测试的关系 | 维度 | E2E 测试 | 视觉测试 | |------|----------|----------| | 目录 | `tests/e2e/` | `tests/visual/` | | Playwright 项目 | `chromium` | `visual-chromium` | | 运行命令 | `npm run test:e2e` | `npm run test:visual` | | 关注点 | 功能正确性 | UI 视觉一致性 | | 断言方式 | DOM/行为断言 | 像素快照对比 | 两个测试套件相互独立,可分别运行,互不影响。