9.6 KiB
9.6 KiB
User Journey 测试改进设计文档
文档日期: 2026-04-08
负责人: 张翔
版本: 1.0
状态: 已验证
执行摘要
通过快速验证测试,我们确认了 Playwright 本身是有效的,问题在于测试方式。改进后的测试方法成功发现了真实问题,证明了方案的可行性。
核心发现:
- ✅ Playwright 工具本身有效
- ❌ 旧测试方式存在假阳性问题
- ✅ 新测试方式能真实发现问题
- ✅ 三层验证策略可行
1. 问题分析
1.1 当前问题
用户报告:
- 测试通过了,但实际运行时页面没有内容
- Console 有 Mock API 日志,但页面无内容
根本原因:
// ❌ 错误的测试方式
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 核心原则转变
❌ 旧方式(软验证)
// 软验证:元素不存在就跳过
if (await element.isVisible()) {
expect(await element.textContent()).toBeTruthy()
}
✅ 新方式(硬验证)
// 硬验证:元素必须存在且可见
await expect(element).toBeVisible()
const text = await element.textContent()
expect(text).toBeTruthy()
expect(text.length).toBeGreaterThan(0)
2.2 三层验证策略
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. 状态验证器
// 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. 内容验证器
// 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. 截图验证器
// 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 测试原则
- 硬验证优先: 元素必须存在,否则测试失败
- 多层验证: API → 状态 → DOM → 内容
- 快速失败: 发现问题立即失败,不继续执行
- 清晰诊断: 提供详细的诊断信息
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 参考资料
9. 总结
9.1 核心结论
- ✅ Playwright 工具本身有效
- ❌ 问题在于测试方式(软验证 vs 硬验证)
- ✅ 改进后的测试能真实发现问题
- ✅ 三层验证策略可行
9.2 下一步行动
- 立即行动: 修复现有测试用例,使用硬验证
- 短期计划: 建立测试工具库,提高可维护性
- 中期计划: 集成到CI/CD,建立完整测试体系
- 长期计划: 持续优化,建立视觉回归测试
文档状态: ✅ 已验证
下一步: 用户审查书面规格