405 lines
9.6 KiB
Markdown
405 lines
9.6 KiB
Markdown
# 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. **长期计划**: 持续优化,建立视觉回归测试
|
||
|
||
---
|
||
|
||
**文档状态**: ✅ 已验证
|
||
**下一步**: 用户审查书面规格
|