# User Journey 测试改进设计文档 **文档日期**: 2026-04-08 **负责人**: 张翔 **版本**: 1.0 **状态**: 已验证 --- ## 执行摘要 通过快速验证测试,我们确认了 **Playwright 本身是有效的**,问题在于测试方式。改进后的测试方法成功发现了真实问题,证明了方案的可行性。 **核心发现**: - ✅ Playwright 工具本身有效 - ❌ 旧测试方式存在假阳性问题 - ✅ 新测试方式能真实发现问题 - ✅ 三层验证策略可行 --- ## 1. 问题分析 ### 1.1 当前问题 **用户报告**: - 测试通过了,但实际运行时页面没有内容 - Console 有 Mock API 日志,但页面无内容 **根本原因**: ```typescript // ❌ 错误的测试方式 const dataStats = page.locator('[data-testid="data-stats"]') if (await dataStats.isVisible()) { // 如果不可见,跳过验证! const statsText = await dataStats.textContent() expect(statsText).toBeTruthy() // 这行永远不会执行 } // 测试通过!但实际上什么都没验证 ``` **问题本质**: - 软验证:元素不存在就跳过验证 - 假阳性:测试通过但实际无效 - 缺乏强制验证:没有确保元素必须存在 --- ### 1.2 验证测试结果 **测试文件**: `tests/e2e/specs/validation/test-improvement-validation.spec.ts` **测试结果**: | 测试类型 | 结果 | 说明 | |---------|------|------| | ❌ 旧方式:软验证 | ✅ 通过 | **假阳性!** 元素不存在但测试通过 | | ✅ 新方式:硬验证 | ❌ 失败 | **正确!** 元素不存在,测试失败 | | ✅ 三层验证 | ❌ 失败 | API请求超时,暴露真实问题 | | ✅ 完整用户旅程 | ❌ 失败 | 案件列表元素不存在(count = 0) | | ✅ 诊断测试 | ✅ 通过 | 提供详细诊断信息 | **关键发现**: - 页面上没有 `.ant-list-item` 元素(count = 0) - API请求超时(没有调用 `/api/cases`) - 页面根本没有加载案件数据 --- ## 2. 解决方案 ### 2.1 核心原则转变 #### ❌ 旧方式(软验证) ```typescript // 软验证:元素不存在就跳过 if (await element.isVisible()) { expect(await element.textContent()).toBeTruthy() } ``` #### ✅ 新方式(硬验证) ```typescript // 硬验证:元素必须存在且可见 await expect(element).toBeVisible() const text = await element.textContent() expect(text).toBeTruthy() expect(text.length).toBeGreaterThan(0) ``` --- ### 2.2 三层验证策略 ```typescript test('真实验证用户看到的内容', async ({ page }) => { // Layer 1: API层验证 const response = await page.waitForResponse('**/api/cases') expect(response.status()).toBe(200) const data = await response.json() expect(data.length).toBeGreaterThan(0) // Layer 2: 状态层验证 const state = await page.evaluate(() => { return { cases: window.__CASE_STORE__?.getState().cases, currentCase: window.__CASE_STORE__?.getState().currentCase } }) expect(state.cases.length).toBeGreaterThan(0) // Layer 3: DOM层验证 const caseItems = page.locator('.ant-list-item') await expect(caseItems.first()).toBeVisible({ timeout: 5000 }) const count = await caseItems.count() expect(count).toBeGreaterThan(0) // Layer 4: 内容验证 const firstCaseText = await caseItems.first().textContent() expect(firstCaseText).toBeTruthy() expect(firstCaseText.length).toBeGreaterThan(10) }) ``` --- ### 2.3 增强的测试工具 #### 1. 状态验证器 ```typescript // tests/e2e/utils/state-validator.ts export async function validatePageState(page: Page, expectedState: { hasCase?: boolean hasData?: boolean activePage?: string }) { const state = await page.evaluate(() => ({ currentCase: window.__CASE_STORE__?.getState().currentCase, transactions: window.__DATA_STORE__?.getState().transactions, activePage: window.__PAGE_STORE__?.getState().activePageKey })) if (expectedState.hasCase) { expect(state.currentCase).toBeTruthy() } if (expectedState.hasData) { expect(state.transactions.length).toBeGreaterThan(0) } if (expectedState.activePage) { expect(state.activePage).toBe(expectedState.activePage) } } ``` #### 2. 内容验证器 ```typescript // tests/e2e/utils/content-validator.ts export async function validateContent( page: Page, selector: string, options: { mustBeVisible?: boolean mustHaveText?: boolean minLength?: number exactText?: string } = {} ) { const element = page.locator(selector) // 默认必须可见 if (options.mustBeVisible !== false) { await expect(element).toBeVisible({ timeout: 5000 }) } if (options.mustHaveText) { const text = await element.textContent() expect(text).toBeTruthy() if (options.minLength) { expect(text.length).toBeGreaterThanOrEqual(options.minLength) } if (options.exactText) { expect(text.trim()).toBe(options.exactText) } } } ``` #### 3. 截图验证器 ```typescript // tests/e2e/utils/screenshot-validator.ts export async function takeScreenshotAndValidate( page: Page, testName: string, step: string ) { const screenshot = await page.screenshot({ fullPage: true, path: `test-results/screenshots/${testName}-${step}.png` }) // 验证截图不为空 expect(screenshot.length).toBeGreaterThan(1000) console.log(`📸 Screenshot saved: ${testName}-${step}.png`) } ``` --- ## 3. 实施计划 ### 3.1 短期(1周内) **目标**: 修复现有测试用例 **任务清单**: - [ ] 将所有软验证改为硬验证 - [ ] 添加三层验证策略 - [ ] 创建测试工具函数 - [ ] 修复发现的问题 **预计工作量**: 2-3 天 --- ### 3.2 中期(2-4周) **目标**: 建立完整的测试体系 **任务清单**: - [ ] 添加视觉验证(截图对比) - [ ] 建立测试报告机制 - [ ] 集成到CI/CD - [ ] 建立测试数据管理 **预计工作量**: 5-7 天 --- ### 3.3 长期(1-3个月) **目标**: 持续优化和扩展 **任务清单**: - [ ] 评估是否需要引入Storybook - [ ] 考虑AI辅助测试 - [ ] 建立性能测试 - [ ] 建立安全测试 **预计工作量**: 10-15 天 --- ## 4. 技术选型 ### 4.1 核心工具 **Playwright** ✅ **已验证有效** - 优势: - 强大的选择器和断言 - 支持API拦截和验证 - 内置截图和视频录制 - 跨浏览器支持 - 活跃的社区和文档 - 劣势: - 需要正确的使用方式 - 学习曲线适中 **结论**: 继续使用Playwright,改进测试方式 --- ### 4.2 辅助工具 | 工具 | 用途 | 优先级 | |------|------|--------| | Playwright Screenshot | 视觉验证 | P0 | | Playwright Trace | 调试支持 | P0 | | Playwright API Mocking | 数据模拟 | P1 | | Percy / Chromatic | 视觉回归 | P2 | | Storybook | 组件测试 | P3 | --- ## 5. 质量保障 ### 5.1 测试原则 1. **硬验证优先**: 元素必须存在,否则测试失败 2. **多层验证**: API → 状态 → DOM → 内容 3. **快速失败**: 发现问题立即失败,不继续执行 4. **清晰诊断**: 提供详细的诊断信息 --- ### 5.2 测试覆盖率目标 | 层级 | 当前覆盖率 | 目标覆盖率 | |------|-----------|-----------| | API层 | 0% | 100% | | 状态层 | 0% | 100% | | DOM层 | 50% | 100% | | 内容层 | 30% | 100% | | **总体** | **30%** | **100%** | --- ## 6. 风险评估 ### 6.1 技术风险 | 风险 | 影响 | 概率 | 缓解措施 | |------|------|------|----------| | 测试用例维护成本高 | 中 | 中 | 建立测试工具库,提高可维护性 | | 测试执行时间长 | 低 | 低 | 使用并行执行,优化测试用例 | | 误报率高 | 高 | 低 | 使用硬验证,减少假阳性 | --- ### 6.2 业务风险 | 风险 | 影响 | 概率 | 缓解措施 | |------|------|------|----------| | 测试不通过影响交付 | 高 | 中 | 优先修复关键问题,建立分级测试 | | 测试数据管理复杂 | 中 | 中 | 建立测试数据工厂,使用Mock数据 | --- ## 7. 成功标准 ### 7.1 短期目标(1周内) - ✅ 所有测试用例使用硬验证 - ✅ 测试覆盖率提升到 60% - ✅ 无假阳性问题 - ✅ 发现并修复当前问题 --- ### 7.2 中期目标(2-4周) - ✅ 测试覆盖率提升到 80% - ✅ 建立完整的测试报告 - ✅ 集成到CI/CD - ✅ 测试执行时间 < 10分钟 --- ### 7.3 长期目标(1-3个月) - ✅ 测试覆盖率提升到 100% - ✅ 建立视觉回归测试 - ✅ 建立性能测试 - ✅ 测试执行时间 < 5分钟 --- ## 8. 附录 ### 8.1 验证测试文件 **文件**: `tests/e2e/specs/validation/test-improvement-validation.spec.ts` **测试结果**: - ❌ 旧方式:软验证 - ✅ 通过(假阳性) - ✅ 新方式:硬验证 - ❌ 失败(正确) - ✅ 三层验证 - ❌ 失败(正确) - ✅ 完整用户旅程 - ❌ 失败(正确) - ✅ 诊断测试 - ✅ 通过 --- ### 8.2 参考资料 - [Playwright 官方文档](https://playwright.dev/) - [Playwright 最佳实践](https://playwright.dev/docs/best-practices) - [测试驱动开发(TDD)](https://en.wikipedia.org/wiki/Test-driven_development) --- ## 9. 总结 ### 9.1 核心结论 1. ✅ **Playwright 工具本身有效** 2. ❌ **问题在于测试方式(软验证 vs 硬验证)** 3. ✅ **改进后的测试能真实发现问题** 4. ✅ **三层验证策略可行** --- ### 9.2 下一步行动 1. **立即行动**: 修复现有测试用例,使用硬验证 2. **短期计划**: 建立测试工具库,提高可维护性 3. **中期计划**: 集成到CI/CD,建立完整测试体系 4. **长期计划**: 持续优化,建立视觉回归测试 --- **文档状态**: ✅ 已验证 **下一步**: 用户审查书面规格