会议日期: 2026-01-11 Epic 状态: ✅ Done 参与人员: Root (Project Lead), Bob (Scrum Master), Alice (Product Owner), Charlie (Senior Dev), Dana (QA Engineer), Elena (Junior Dev)
Epic 3 目标: 遵循 Epic 2 的成功模式,开发文件上传工具并在 web/tests/e2e/ 的真实测试中验证,解决当前测试超时阻塞问题。
交付成果:
uploadFileToField())模式验证:
会议目的:
Epic 3 遵循了 Epic 2 验证成功的模式:
| Epic | 模式 | 结果 |
|---|---|---|
| Epic 2 | Select 工具开发 → E2E 验证 → 问题修复 | ✅ 成功 |
| Epic 3 | 文件上传工具开发 → E2E 验证 → 问题修复 | ✅ 成功 |
Alice (Product Owner): "Epic 2 的模式在 Epic 3 中得到了复制和验证。'工具开发 → E2E 验证 → 问题修复 → 稳定性验证' 这个模式非常有效。"
Story 完成情况:
| Story | 描述 | 状态 | 关键成果 |
|---|---|---|---|
| 3.1 | 开发文件上传工具函数 | ✅ 完成 | UI 组件架构改进(MinioUploader 添加 testId) |
| 3.2 | 编写文件上传单元测试 | ✅ 完成 | 91.66% 覆盖率,52 个测试用例 |
| 3.3 | 在 E2E 测试中验证文件上传工具 | ✅ 完成 | 场景 1 通过,发现 FileSelector Dialog 模式 |
| 3.4 | 收集反馈并修复问题 | ✅ 完成 | 修复 Select 工具处理带 * 标签的问题 |
| 3.5 | 支持多文件同时上传 | ✅ 完成 | 函数重载,向后兼容 |
| 3.6 | 文件上传稳定性验证 | ✅ 完成 | 6 次连续运行 100% 通过 |
问题背景 (Story 3.6):
selectRadixOptionAsync() 无法处理级联依赖创新解决方案:
// packages/e2e-test-utils/src/cascade-select.ts
export async function selectCascade(
page: Page,
province: string,
city: string
): Promise<void> {
// 1. 选择省份
await selectRadixOption(page, '省份 *', province);
// 2. 等待城市选项加载(关键)
await page.waitForTimeout(1500);
// 3. 选择城市
await selectRadixOption(page, '城市 *', city);
}
Charlie (Senior Dev): "创建级联选择工具是一个工程决策。我们本可以使用 hack(增加超时),但创建专用工具更清晰、更可维护。"
验证结果:
✅ 稳定性测试最终报告:
| 运行次数 | 结果 | 耗时 | 备注 |
|---------|------|------|------|
| 第 1 次 | ✅ 6/6 passed | 5.2m | 全部通过 |
| 第 2 次 | ✅ 6/6 passed | 6.9m | 全部通过 |
| 第 3 次 | ✅ 6/6 passed | 3.3m | 全部通过 |
| 第 4 次 | ✅ 6/6 passed | 3.4m | 全部通过 |
| 第 5 次 | ✅ 6/6 passed | 3.3m | 全部通过 |
| 第 6 次 | ✅ 6/6 passed | 3.8m | 全部通过 |
| **总计** | **36/36 (100%)** | **平均 4.3m** | **无失败** |
Epic 2 发现的问题在 Epic 3 中得到解决:
| 问题 | Epic 2 状态 | Epic 3 解决方案 |
|---|---|---|
Select 工具无法处理带 * 的标签 |
未发现(测试场景不同) | Story 3.4: 新增策略 4 + 策略 5 |
修复内容 (Story 3.4):
// 策略 4: 使用精确文本匹配
const trigger = page.getByText(label, { exact: true }).or(
page.getByRole('combobox')
);
// 策略 5: 处理标签和 `*` 分离的 DOM 结构
const labelPattern = new RegExp(`^${label.replace(/\*/g, '\\*')}\\s*\\*?$`);
验证通过:
稳定性测试指标:
Dana (QA Engineer): "100% 的稳定性通过率是 Epic 3 最大的成就。6 次连续运行,没有 flaky 失败,没有超时失败。这证明了文件上传工具的可靠性。"
问题统计:
| Story | 审查问题数 | 问题类型 |
|---|---|---|
| 3.1 | 4 个 | 默认路径、空目录、选择器错误、路径遍历 |
| 3.2 | 4 个 | 测试输出、边界条件、测试文件、路径遍历覆盖 |
| 3.3 | 多个 | 测试文件未提交、硬编码超时、console.log |
| 3.4 | - | 修复 Select 工具(无审查问题) |
| 3.5 | - | 多文件上传(无审查问题) |
| 3.6 | - | 稳定性验证(无审查问题) |
Bob (Scrum Master): "代码审查在前 3 个 Story 中持续发现问题。这表明我们缺乏自动化预防机制。"
Epic 2 回顾行动项 #1 状态:
影响:
问题 (Story 3.1):
修改内容:
// PhotoUploadField.tsx - 添加测试支持
<input
type="file"
data-testid={`photo-upload-${index}`}
className="hidden" // 隐藏但可测试
{...props}
/>
Charlie (Senior Dev): "测试友好性应该是架构设计的重要考量。Epic 3 的经验表明,我们需要在组件设计阶段考虑 E2E 测试需求。"
Epic 2 HIGH 优先级行动项跟进:
| # | 行动项 | Epic 2 状态 | Epic 3 状态 |
|---|---|---|---|
| HIGH #1 | 配置 ESLint 规则 | ❌ 未完成 | ❌ 仍未完成 |
| HIGH #2 | 更新架构文档记录 TS+Playwright 陷阱 | ⏳ 部分完成 | ✅ 已完成 |
| HIGH #3 | 调整单元测试策略 | ✅ 已完成 | ✅ 已应用 |
Alice (Product Owner): "ESLint 规则还是没有配置。Epic 2 中发现的问题在 Epic 3 中重复出现。"
已完成的部分:
问题 (Story 3.3):
page.waitForTimeout() 导致测试缓慢示例:
// ❌ 硬编码超时
await page.waitForTimeout(500);
await page.waitForTimeout(1000);
// ✅ 使用 Playwright auto-waiting
await page.waitForLoadState('networkidle');
await expect(element).toBeVisible();
Dana (QA Engineer): "硬编码超时值会导致测试不稳定。如果网络慢,测试失败;如果网络快,测试浪费时间。"
| # | 行动项 | Epic 2 状态 | Epic 3 状态 |
|---|---|---|---|
| 1 | 配置 ESLint 规则捕获常见问题 | ❌ 未完成 | ❌ 仍未完成 |
| 2 | 更新架构文档记录 TS+Playwright 陷阱 | ⏳ 部分完成 | ✅ 已完成 |
| 3 | 调整单元测试策略 | ✅ 已完成 | ✅ 已应用 |
Epic 3 中的影响:
Elena (Junior Dev): "如果 ESLint 规则已配置,这些问题可以在提交前自动检测,不需要代码审查。"
完成内容:
packages/e2e-test-utils/docs/DEVELOPER_CHECKLIST.mdpackages/e2e-test-utils/eslint.config.jsEpic 3 中的应用:
负责人: Charlie 预计时间: 2 小时 截止日期: Epic 9 开始前必须完成
需要配置的规则:
// packages/e2e-test-utils/.eslintrc.js
{
rules: {
// 捕获路径遍历漏洞
'no-restricted-syntax': [
'error',
{
selector: 'CallExpression[callee.name="join"]',
message: 'Use path.join for security'
}
],
// 捕获 console.log
'no-console': ['error', { allow: ['warn', 'error'] }],
// 捕获硬编码超时
'no-restricted-globals': ['error', 'setTimeout'],
// 其他规则
'no-constant-binary-expression': 'error',
'no-unused-vars': 'error',
'prefer-const': 'error'
}
}
Alice (Product Owner): "这次必须完成。ESLint 规则将减少代码审查时间,提高代码质量。"
负责人: Charlie 预计时间: 2 小时
问题: UI 组件需要修改才能支持 E2E 测试
建议:
负责人: Elena 预计时间: 1 小时
范围: web/tests/e2e/ 目录
需要替换的模式:
page.waitForTimeout() → 使用 Playwright auto-waitingpage.waitForTimeout(500) → waitForLoadState('networkidle')负责人: Dana (QA Engineer) 预计时间: 1 小时
Epic 3 性能数据:
建议: 建立性能基准,监控测试执行时间趋势
背景:
决策: 创建 Epic 9 - 残疾人管理完整 E2E 测试覆盖(含并行隔离)
Epic 9 内容:
Alice (Product Owner): "这个决策非常正确。我们应该优先完成业务测试覆盖,工具会在需要时自然出现。"
原计划:
调整后:
理由:
Bob (Scrum Master): "Epic 9 完成后,残疾人管理和区域管理测试可以并行运行。这是正确的前置条件。"
Epic 2 规划: 10 次连续稳定性验证 Epic 3 实际: 6 次连续运行 100% 通过
决策: 6 次验证足以证明稳定性
理由:
Dana (QA Engineer): "6 次 100% 通过已经非常强了。继续运行到 10 次的边际收益递减。"
Epic 3 状态: ✅ Done
关键成果:
uploadFileToField())selectCascade())* 标签的问题关键经验:
Epic 组织更新:
Epic A: 残疾人管理 E2E 测试 🔄 进行中
├─ Epic 1-3: ✅ 已完成(工具开发)
└─ Epic 9: 🆕 当前优先级(完整业务测试)
Epic B: 区域管理 E2E 测试 ⏸️ 等待 Epic 9 完成
└─ Epic 8: 区域管理 E2E 测试
下一步:
Bob (Scrum Master): "Epic 3 是一个成功的工具开发 Epic。我们交付了高质量的文件上传工具,验证了稳定性测试策略。更重要的是,我们明确了下一步的方向 - Epic 9 将完成残疾人管理的完整业务测试覆盖。"
[文档完]