# Epic 2 Retrospective: 在现有 E2E 测试中验证 Select 工具

**会议日期:** 2026-01-10
**Epic 状态:** ✅ Done
**参与人员:** Root (Project Lead), Bob (Scrum Master), Alice (Product Owner), Charlie (Senior Dev), Dana (QA Engineer), Elena (Junior Dev)

## 会议概览

**Epic 2 目标:** 在 `web/tests/e2e/` 的现有残疾人管理测试中使用 Select 工具，验证工具在真实场景中的可用性和稳定性。

**交付成果:**
- 完成故事: 5/5 (100%) - Story 2.6 稳定性验证已跳过
- Select 工具验证: ✅ 通过（静态 + 异步场景）
- 关键 Bug 修复: ✅ listbox → option DOM 结构问题

**会议目的:**
1. 学习 Epic 2 的执行经验
2. 评估 Epic 1 回顾行动项的跟进情况
3. 为 Epic 3（扩展工具集）做准备

## 成功经验 ✅

### 1. "先验证再扩展" 策略得到验证

Epic 1 回顾中的关键决策在 Epic 2 中得到了验证：

**原 Epic 规划顺序:**
- Epic 1: Select 工具（已完成）
- ~~Epic 2: 扩展工具集~~
- Epic 3: 验证

**修正后的顺序:**
- Epic 1: Select 工具（已完成）
- **Epic 2: 验证 Select 工具** ← 当前 Epic
- Epic 3: 扩展工具集
- Epic 4: 全面验证

**Alice (Product Owner):** "这个决策非常正确。如果我们先扩展更多工具，Select 工具的问题会在 Epic 3/4 中才暴露，那时修复成本会高得多。"

**验证结果:**

| Story | 验证内容 | 结果 | 发现问题 |
|-------|---------|------|---------|
| 2.1 | 工具包安装和类型安全 | ✅ 通过 | 无 |
| 2.2 | 静态 Select 迁移（5 处） | ✅ 通过 | 无 |
| 2.3 | 异步 Select 迁移（省份/城市） | ✅ 通过 | 移除了 waitForTimeout hack |
| 2.4 | 运行测试并收集问题 | ⚠️ 发现 | DOM 结构假设错误 |
| 2.5 | 验证修复效果 | ✅ 通过 | 无 |

### 2. 发现并修复关键 DOM 结构 Bug

**问题详情 (Story 2.4):**

```typescript
// ❌ 原代码 - 等待 listbox 元素
await page.waitForSelector('[role="listbox"]', {
  timeout: DEFAULT_TIMEOUTS.static,
  state: 'visible'
});

// ✅ 修复 - 直接等待 option 元素
// findTrigger 和 findAndClickOption 中使用 getByRole("option")
```

**Charlie (Senior Dev):** "这个 bug 很关键。Epic 1 的单元测试没有发现这个问题，因为单元测试模拟了完整的 DOM 结构。真实环境中的 Radix UI Select v2.2.5 结构与假设不同。"

**修复内容:**
1. `selectRadixOption`: 改用 `getByRole("option")` 代替 `waitForSelector("[role=listbox]")`
2. `selectRadixOptionAsync`: 应用相同修复
3. 添加下拉框关闭等待逻辑（200ms + hidden 状态）
4. 缩短选择器超时（5000ms → 2000ms）

**验证结果 (Story 2.5):**
```
✅ 姓名: 完整测试_1768004957534
✅ 性别: 男
✅ 身份证号: 420101199001011234
✅ 残疾证号: 51100119900104
✅ 残疾类型: 视力残疾
✅ 残疾等级: 一级
✅ 联系电话: 13800138004
✅ 身份证地址: 湖北省武汉市测试街道1号
✅ 省份: 湖北省
✅ 城市: 武汉市
```

### 3. 代码审查流程持续有效

Epic 2 每个故事都经过了代码审查，问题全部修复：

| Story | 审查问题数 | 状态 |
|-------|-----------|------|
| 2.1 | 3 个（文档相关） | ✅ 全部修复 |
| 2.2 | 多个（行号更新、实现调整） | ✅ 全部修复 |
| 2.3 | 9 个（MEDIUM、LOW） | ✅ 全部修复 |
| 2.4 | 初始发现问题 | ✅ 已修复 |
| 2.5 | 1 个（.bak 文件） | ✅ 已修复 |

**Dana (QA Engineer):** "代码审查继续发挥价值。Story 2.5 中发现的 .bak 文件问题虽然小，但这种细节关注保持了代码库的整洁。"

### 4. 真实 E2E 测试的价值

**单元测试 vs E2E 测试:**

| 测试类型 | 覆盖场景 | 发现的问题 |
|---------|---------|-----------|
| 单元测试 (Epic 1) | 模拟 DOM 结构 | 无 |
| E2E 测试 (Epic 2) | 真实 Radix UI 组件 | listbox DOM 问题 |

**Elena (Junior Dev):** "Epic 1 的单元测试覆盖率达到了 93.65%，但仍然没有发现这个 DOM 结构问题。真实 E2E 测试是不可替代的。"

---

**[第一部分完 - 会议概览和成功经验]**

## 挑战和问题分析 ⚠️

### 1. DOM 结构假设与实际不符

**问题描述:**

工具假设 Select 组件的 DOM 结构包含 `[role="listbox"]` 元素，但 Radix UI Select v2.2.5 的实际结构是：

```
[role="combobox"]
  └── [role="option"]  ← 选项直接在 combobox 内部
```

**影响:**
- 导致 `waitForSelector('[role="listbox"]')` 超时
- 测试在第一个 Select 操作时失败
- 阻塞了整个 Epic 2 的验证

**根本原因分析:**

**Bob (Scrum Master):** "为什么单元测试没有发现这个问题？"

**Charlie (Senior Dev):** "因为单元测试中的 mock DOM 结构是我们假设的完美结构。我们没有使用真实的 Radix UI 组件进行测试。"

**教训:**
- 单元测试不能完全替代集成/E2E 测试
- 需要在真实组件上验证工具
- DOM 结构假设应该基于实际实现而非理想模型

### 2. Epic 1 回顾行动项未完全跟进

**Epic 1 HIGH 优先级行动项跟进情况:**

| 行动项 | 状态 | 影响 |
|--------|------|------|
| HIGH #1: 配置 ESLint 规则 | ❌ 未完成 | Epic 2 中仍有重复的代码风格问题 |
| HIGH #2: 更新架构文档记录 TS+Playwright 陷阱 | ⏳ 部分完成 | 开发者需要自己摸索 |
| HIGH #3: 创建新的 Epic 2 | ✅ 完成 | Epic 2 成功执行 |
| HIGH #4: 更新 Epic 编号 | ✅ 完成 | sprint-status 已更新 |

**Alice (Product Owner):** "HIGH #1 和 #2 没有完成。这可能是为什么我们在 Epic 2 中仍遇到一些预期内的问题。"

**未完成的行动项影响:**

1. **ESLint 规则未配置**
   - Epic 2 中仍然出现代码风格问题
   - 例如：Story 2.5 中的 .bak 文件未清理
   - 代码审查时间被浪费在可自动检测的问题上

2. **架构文档未更新**
   - TypeScript + Playwright 陷阱没有正式记录
   - 新开发者需要自己摸索
   - 知识传递效率低

### 3. 渐进式迁移策略的额外成本

**Story 2.2 → Story 2.3 的迁移策略:**

| Story | 范围 | 状态 |
|-------|------|------|
| 2.2 | 静态 Select | ✅ 完成，但保留自定义方法 |
| 2.3 | 异步 Select | ✅ 完成，移除自定义方法 |

**额外成本:**
- Story 2.2 需要添加 TODO 注释
- Story 2.3 需要再次修改相同文件
- 需要协调两个故事的边界

**Charlie (Senior Dev):** "渐进式迁移策略保持了测试连续性，但确实增加了协调成本。如果一次性迁移所有 Select，风险会更高。这是一个权衡。"

### 4. 测试超时问题（非工具问题）

**问题描述:**
- 测试在文件上传阶段超时（60秒）
- 与 Select 工具无关，是测试流程问题

**当前状态:**
- 标记为 LOW 优先级
- 需要在后续 Epic 中处理（Epic 4: 文件上传测试）

**Dana (QA Engineer):** "测试超时不是 Select 工具的问题，但它影响了 Epic 2 的完整验证。我们无法运行完整的测试套件来验证所有字段。"

---

**[第二部分完 - 挑战和问题分析]**

## Epic 1 回顾行动项跟进 📋

### HIGH 优先级行动项

| # | 行动项 | 负责人 | 预计时间 | Epic 2 状态 |
|---|--------|--------|----------|-------------|
| 1 | 配置 ESLint 规则捕获常见问题 | Charlie | 2h | ❌ **未完成** |
| 2 | 更新架构文档记录 TS+Playwright 陷阱 | Charlie | 1h | ⏳ **部分完成** |
| 3 | 创建新的 Epic 2 | Bob | 1h | ✅ **已完成** |
| 4 | 更新 Epic 编号（2→3, 3→4, 4→5）| Bob | 0.5h | ✅ **已完成** |

### 详细分析

#### 行动项 #1: ESLint 规则 - 未完成

**原计划 (Epic 1 回顾):**
```javascript
// .eslintrc.js
{
  rules: {
    'no-constant-binary-expression': 'error',
    'no-unused-vars': 'error',
    'no-empty': ['error', { allowEmptyCatch: false }],
    'prefer-const': 'error'
  }
}
```

**Epic 2 中的影响:**
- Story 2.5 发现了未清理的 .bak 文件
- 代码审查仍然需要人工检查可自动检测的问题

**建议:** 在 Epic 3 开始前完成此行动项

#### 行动项 #2: 架构文档更新 - 部分完成

**Epic 2 中的证据:**
- Story 2.2 Dev Notes 引用了 Epic 1 回顾中的 TypeScript + Playwright 陷阱
- 但架构文档本身未更新

**Charlie (Senior Dev):** "我在故事中引用了这些经验，但没有正式更新到架构文档中。这是我的疏忽。"

#### 行动项 #3-4: Epic 规划调整 - 已完成 ✅

**Epic 2 成功创建并执行:**
- 使用现有 `web/tests/e2e/` 测试基础设施
- 验证了 Select 工具在真实场景中的可用性
- 发现并修复了关键 DOM 结构问题

**Alice (Product Owner):** "Epic 规划调整非常成功。'先验证再扩展'的策略得到了验证。"

### MEDIUM 优先级行动项

| # | 行动项 | 负责人 | Epic 2 状态 |
|---|--------|--------|-------------|
| 5 | 创建开发者自查清单 | Elena | ❌ 未完成 |
| 6 | 更新代码审查检查清单 | Charlie | ⏳ 部分完成 |

---

## 行动项 📋

### 优先级 HIGH

#### 1. 配置 ESLint 规则（从 Epic 1 延续）

**负责人:** Charlie
**预计时间:** 2 小时
**截止日期:** Epic 3 开始前

**需要配置的规则:**
```javascript
// .eslintrc.js
{
  rules: {
    // 捕获冗余的 null 检查
    'no-constant-binary-expression': 'error',

    // 捕获未使用的变量
    'no-unused-vars': 'error',

    // 捕获空 catch 块
    'no-empty': ['error', { allowEmptyCatch: false }],

    // 首选 const
    'prefer-const': 'error'
  }
}
```

**预期收益:** 自动捕获约 50% 的重复审查问题

#### 2. 更新架构文档记录 TS+Playwright 陷阱（从 Epic 1 延续）

**负责人:** Charlie
**预计时间:** 1 小时
**截止日期:** Epic 3 开始前

**文档位置:** `_bmad-output/planning-artifacts/architecture.md`

**需要添加的内容:**
- TypeScript DOM 类型问题及解决方案
- 精确文本匹配选择器规范
- DOM 结构假设必须基于真实组件验证

#### 3. 更新工具包单元测试策略

**负责人:** Dana (QA Engineer)
**预计时间:** 2 小时
**截止日期:** Epic 3 开始前

**问题:** 当前单元测试使用模拟 DOM，无法发现真实 DOM 结构问题

**建议解决方案:**
- 在单元测试中使用真实的 Radix UI 组件
- 或添加集成测试级别，使用真实组件

**Elena (Junior Dev):** "如果我们使用真实组件进行单元测试，Epic 2 的 DOM 问题就能在 Epic 1 中发现。"

### 优先级 MEDIUM

#### 4. 创建开发者自查清单（从 Epic 1 延续）

**负责人:** Elena
**预计时间:** 1 小时

**清单内容:**
- [ ] 所有导出函数都有完整的 JSDoc
- [ ] 内部函数使用 `@internal` 标记
- [ ] 错误处理使用 `E2ETestError` 而非原生 `Error`
- [ ] DOM 结构假设必须基于真实组件验证
- [ ] 文本选择器使用 `:text-is()` 而非 `:has-text()`
- [ ] 配置对象继承 `BaseOptions`
- [ ] 超时值使用 `DEFAULT_TIMEOUTS` 常量

#### 5. 解决测试超时问题

**负责人:** Dana (QA Engineer)
**预计时间:** 1-2 小时

**问题描述:**
- 测试在文件上传阶段超时（60秒）
- 影响完整测试套件的执行

**可能的解决方案:**
1. 增加测试超时时间
2. 优化文件上传逻辑
3. 分离文件上传测试到独立套件

**当前计划:** 在 Epic 4（文件上传测试）中处理

### 优先级 LOW

#### 6. 更新代码审查检查清单（从 Epic 1 延续）

**负责人:** Charlie
**预计时间:** 0.5 小时

**添加检查点:**
- 检查 DOM 结构假设是否基于真实组件验证
- 验证是否遵循"先验证再扩展"原则

---

## 关键决策 🎯

### 决策 1: 跳过 Story 2.6 稳定性验证

**原计划:**
- Story 2.6: 稳定性验证（连续 10 次，100% 通过）

**实际情况:**
- Story 2.5 已确认 Select 工具工作正常
- 所有字段都成功填写
- 测试超时与 Select 工具无关

**决策:** 跳过 Story 2.6，Epic 2 标记为完成

**理由:**
1. Select 工具已充分验证（静态 + 异步场景）
2. 10 次稳定性测试的边际收益递减
3. 测试超时问题阻塞了完整验证
4. Epic 3（扩展工具集）更有价值

**Alice (Product Owner):** "我同意跳过 Story 2.6。Select 工具已经验证充分，继续扩展工具集的价值更高。"

### 决策 2: 单元测试策略调整

**问题:** 单元测试使用模拟 DOM，无法发现真实 DOM 结构问题

**可选方案:**

| 方案 | 优点 | 缺点 |
|------|------|------|
| A. 继续使用模拟 DOM | 快速、独立 | 无法发现 DOM 问题 |
| B. 使用真实组件 | 发现真实问题 | 依赖外部组件 |
| C. 添加集成测试 | 两全其美 | 增加测试层级 |

**决策:** 采用方案 C - 添加集成测试级别

**Charlie (Senior Dev):** "单元测试应该保持快速和独立。我们添加一个集成测试级别，使用真实组件验证工具。"

### 决策 3: Epic 3 前完成 HIGH 优先级行动项

**未完成的 HIGH 行动项:**
1. 配置 ESLint 规则
2. 更新架构文档
3. 调整单元测试策略

**决策:** Epic 3 暂缓，先完成这些行动项

**理由:**
1. 这些改进将降低 Epic 3 的代码审查成本
2. 文档更新将提高 Epic 3 的开发效率
3. 测试策略调整将避免类似 DOM 问题再次发生

**Bob (Scrum Master):** "我们花 2-3 小时完成这些改进，Epic 3 会更顺利。这是值得的前期投入。"

---

## 总结 📝

**Epic 2 状态:** ✅ **Done**

**关键成果:**
- ✅ Select 工具在真实 E2E 测试中验证通过
- ✅ 发现并修复关键 DOM 结构问题
- ✅ "先验证再扩展"策略得到验证
- ✅ 代码审查流程持续有效

**关键经验:**
1. **真实 E2E 测试不可替代** - 单元测试无法发现 DOM 结构问题
2. **DOM 结构假设必须验证** - 不能基于理想模型开发工具
3. **渐进式迁移有价值** - 但需要额外的协调成本
4. **行动项跟进很重要** - Epic 1 的未完成行动项影响了 Epic 2

**下一步:**
1. ✅ Epic 2 完成并归档
2. 🆕 完成技术改进（ESLint、文档、测试策略）
3. ⏸️ Epic 3 暂缓，等待改进完成
4. 📋 创建 Epic 3 准备检查清单

**Bob (Scrum Master):** "Epic 2 是一个成功的验证 Epic。我们发现并修复了关键问题，验证了架构决策的正确性。更重要的是，我们学到了真实 E2E 测试的价值，这将指导后续的开发。"

---

**[文档完]**
