# Story 9.7: 稳定性验证(10 次连续运行) Status: ready-for-dev ## Story 作为测试开发者, 我想要验证所有测试的稳定性, 以便确保测试可以可靠地运行。 ## Acceptance Criteria **Given** 所有业务测试已完成并隔离 **When** 连续运行测试 10 次 **Then** 验收标准如下: 1. **测试通过率 100%** - 10/10 次运行全部通过 - 无 flaky 失败 - 无超时失败 2. **性能指标达标** - 平均执行时间 ≤ 10 分钟/次 - 无明显性能衰减 3. **并行执行稳定** - 并行模式(4 workers)10 次运行 100% 通过 - 串行模式 10 次运行 100% 通过 ## Tasks / Subtasks - [ ] **Task 1: 创建稳定性测试脚本** (AC: #1) - [ ] Subtask 1.1: 编写 bash 脚本实现 10 次连续运行 - [ ] Subtask 1.2: 添加通过/失败统计 - [ ] Subtask 1.3: 添加执行时间记录和平均时间计算 - [ ] **Task 2: 执行并行模式稳定性测试** (AC: #1, #2, #3) - [ ] Subtask 2.1: 使用 4 workers 运行 10 次测试 - [ ] Subtask 2.2: 记录每次运行的通过率和执行时间 - [ ] Subtask 2.3: 分析失败的测试(如有) - [ ] **Task 3: 执行串行模式稳定性测试** (AC: #1, #2, #3) - [ ] Subtask 3.1: 使用 1 worker 运行 10 次测试 - [ ] Subtask 3.2: 记录每次运行的通过率和执行时间 - [ ] Subtask 3.3: 对比并行和串行模式的性能差异 - [ ] **Task 4: 分析结果并生成报告** (AC: #1, #2, #3) - [ ] Subtask 4.1: 统计总体通过率 - [ ] Subtask 4.2: 计算平均执行时间和性能衰减 - [ ] Subtask 4.3: 记录 flaky 失败(如有)并分析原因 - [ ] Subtask 4.4: 更新 Story 文档和 sprint-status ## Dev Notes ### Epic 9 背景与目标 **Epic 9: 残疾人管理完整 E2E 测试覆盖(含并行隔离)** 为残疾人管理功能编写完整的、真正验证业务功能的 E2E 测试,并确保测试可以与未来的区域管理测试并行运行。 **Epic 9 Story 依赖关系:** - Story 9.1:照片上传功能测试 ✅ Done - Story 9.2:银行卡管理功能测试 ✅ Done - Story 9.3:备注管理功能测试 ✅ Done - Story 9.4:回访记录管理测试 ✅ Done - Story 9.5:完整流程测试(CRUD)✅ Done - Story 9.6:测试隔离与并行执行验证 ✅ Done - **Story 9.7(本故事)**:稳定性验证(10次连续运行)🔄 当前 ### 本 Story 的核心目标 **稳定性验证的意义:** 1. **Flaky 测试检测**:10 次连续运行可以暴露偶发性失败的测试 2. **性能基准建立**:建立测试执行时间的基准线 3. **并行执行信心**:验证并行模式在多次运行中的稳定性 4. **Epic 9 完成条件**:100% 通过率是 Epic 9 完成的必要条件 **成功标准:** - 10/10 通过 = Epic 9 完成 ✅ - < 10/10 通过 = 分析失败原因并修复 ### 待验证的测试文件清单 **Epic 9 已完成的所有测试文件:** | 测试文件 | 测试数量 | 预计时间 | 验证项 | |---------|---------|---------|--------| | `disability-person-photo.spec.ts` | 8 | ~1.1m | 照片上传、格式支持、删除 | | `disability-person-bankcard.spec.ts` | 5 | ~0.8m | 银行卡 CRUD、多张管理 | | `disability-person-note.spec.ts` | 4 | ~0.6m | 备注 CRUD | | `disability-person-visit.spec.ts` | 4 | ~0.7m | 回访记录 CRUD | | `disability-person-crud.spec.ts` | 16 | ~2.0m | 完整 CRUD 流程 | **总计:37 个测试,预计执行时间 ~5.2 分钟(4 workers)** ### 稳定性测试脚本 **脚本位置:** `web/tests/e2e/scripts/run-stability-test.sh` ```bash #!/bin/bash # Epic 9 稳定性测试脚本 # 运行所有残疾人管理测试 10 次,验证稳定性 set -e # 遇到错误立即退出 # 配置 RUNS=10 PROJECT_ROOT="/mnt/code/188-179-template-6" WEB_DIR="${PROJECT_ROOT}/web" PASSED=0 FAILED=0 TIMES=() # 切换到 web 目录 cd "${WEB_DIR}" || exit 1 echo "=========================================" echo "Epic 9 稳定性验证测试" echo "=========================================" echo "运行次数: ${RUNS}" echo "测试范围: 残疾人管理所有测试 (37 个测试)" echo "开始时间: $(date)" echo "" echo "=========================================" echo "" # 运行测试 for i in $(seq 1 ${RUNS}); do echo "=== 运行 #${i}/${RUNS} ===" START=$(date +%s) # 运行测试(4 workers 并行) if pnpm test:e2e:chromium --workers=4; then PASSED=$((PASSED + 1)) echo "✅ 运行 #${i} 通过" else FAILED=$((FAILED + 1)) echo "❌ 运行 #${i} 失败" fi END=$(date +%s) DURATION=$((END - START)) TIMES+=($DURATION) echo "⏱️ 耗时: ${DURATION}s" echo "" done # 计算统计数据 TOTAL=$((PASSED + FAILED)) PASS_RATE=$((PASSED * 100 / TOTAL)) AVG_TIME=$(awk '{sum+=$1} END {print sum/NR}' <<< "${TIMES[@]}") MIN_TIME=$(printf "%s\n" "${TIMES[@]}" | sort -n | head -1) MAX_TIME=$(printf "%s\n" "${TIMES[@]}" | sort -n | tail -1) # 输出结果 echo "=========================================" echo "稳定性测试结果" echo "=========================================" echo "通过: ${PASSED}/${TOTAL} (${PASS_RATE}%)" echo "失败: ${FAILED}/${TOTAL}" echo "" echo "执行时间统计:" echo " 平均: ${AVG_TIME}s" echo " 最快: ${MIN_TIME}s" echo " 最慢: ${MAX_TIME}s" echo "" echo "结束时间: $(date)" echo "=========================================" # 判断结果 if [ $PASSED -eq $TOTAL ]; then echo "" echo "🎉 Epic 9 稳定性验证通过!100% 成功率!" echo "✅ Epic 9 可以标记为完成" exit 0 else echo "" echo "⚠️ 稳定性不足,需要修复失败的测试" echo "❌ 请分析失败原因并修复后重新运行" exit 1 fi ``` ### 串行模式稳定性测试脚本 ```bash #!/bin/bash # Epic 9 串行模式稳定性测试脚本 # 用于对比并行和串行模式的性能差异 RUNS=10 PROJECT_ROOT="/mnt/code/188-179-template-6" WEB_DIR="${PROJECT_ROOT}/web" PASSED=0 FAILED=0 TIMES=() cd "${WEB_DIR}" || exit 1 echo "=========================================" echo "Epic 9 串行模式稳定性验证" echo "=========================================" for i in $(seq 1 ${RUNS}); do echo "=== 运行 #${i}/${RUNS} (串行模式) ===" START=$(date +%s) # 运行测试(1 worker 串行) if pnpm test:e2e:chromium --workers=1; then PASSED=$((PASSED + 1)) echo "✅ 运行 #${i} 通过" else FAILED=$((FAILED + 1)) echo "❌ 运行 #${i} 失败" fi END=$(date +%s) DURATION=$((END - START)) TIMES+=($DURATION) echo "⏱️ 耗时: ${DURATION}s" echo "" done # 输出结果(同上) # ... ``` ### 单文件稳定性测试(调试用) ```bash #!/bin/bash # 单文件稳定性测试 - 用于调试特定测试文件 TEST_FILE="${1:-disability-person-crud.spec.ts}" RUNS=10 echo "测试文件: ${TEST_FILE}" echo "运行次数: ${RUNS}" for i in $(seq 1 ${RUNS}); do echo "=== 运行 #${i} ===" pnpm test:e2e:chromium "${TEST_FILE}" --workers=2 done ``` ### Flaky 失败分析指南 **如果出现偶发性失败,按以下步骤分析:** 1. **查看失败截图** ```bash # 查看 test-results 目录 ls -la web/tests/e2e/test-results/ ``` 2. **查看错误上下文** ```bash # 查看自动生成的错误上下文 cat web/tests/e2e/test-results/**/error-context.md ``` 3. **分析失败类型** - **超时失败**:增加超时时间或优化测试逻辑 - **元素未找到**:添加等待或改进选择器 - **数据冲突**:检查唯一性策略 - **网络问题**:重试或使用 mock 数据 4. **修复后重新验证** ```bash # 单文件验证 cd web pnpm test:e2e:chromium disability-person-xxx.spec.ts --workers=2 --repeat=10 ``` ### Project Structure Notes **E2E 测试目录结构:** ``` web/tests/e2e/ ├── fixtures/ # 测试文件(图片、文档) ├── pages/ # Page Object │ └── admin/ │ └── disability-person.page.ts ├── specs/ # 测试用例 │ └── admin/ │ ├── disability-person-photo.spec.ts │ ├── disability-person-bankcard.spec.ts │ ├── disability-person-note.spec.ts │ ├── disability-person-visit.spec.ts │ └── disability-person-crud.spec.ts ├── scripts/ # 测试脚本(新增) │ ├── run-stability-test.sh │ ├── run-stability-serial.sh │ └── run-stability-single.sh └── playwright.config.ts ``` ### Previous Story Intelligence **Story 9.6 (测试隔离与并行执行验证) 的经验:** **主要改进:** 1. ✅ 所有测试移除了 `test.describe.serial` 2. ✅ 添加了 TEST_TIMESTAMP/TEST_PREFIX 模式 3. ✅ 实现了完整的 `test.afterEach` 清理机制 4. ✅ 验证了并行执行稳定性(2 workers,8/8 通过) 5. ✅ 性能提升:4 workers 下速度提升 3 倍(3.3m → 1.1m) **并行执行验证结果(来自 Story 9.6):** ``` photo.spec.ts: 8 passed (2.2m) with 2 workers ✅ note.spec.ts: 8 passed (1.1m) with 2 workers ✅ photo.spec.ts: 8 passed (3.3m) with 1 worker ✅ photo.spec.ts: 8 passed (1.1m) with 4 workers ✅ (速度提升 3x) ``` **关键模式(Story 9.6 建立):** 1. TEST_TIMESTAMP 在 test.describe 级别声明 2. createdTestData 数组用于跟踪创建的记录 3. test.afterEach 统一清理机制 4. 使用不同的省市组合避免并发冲突 **Story 9.1-9.5 的模式总结:** - ✅ 所有测试使用时间戳生成唯一 ID(正确模式) - ✅ 文件上传使用固定的测试文件路径 - ✅ 备注和回访记录使用唯一内容 - ⚠️ 需要验证 10 次运行的稳定性 ### Git Intelligence Summary **Recent Commits:** - `9e3c2dcb` - test(e2e): 完成 Story 9.6 代码审查 - 测试隔离与并行执行 - `81ba705a` - docs(e2e): 创建 Story 10.5 - 编辑订单测试 - `241c2491` - test(e2e): 完成 Story 10.4 - 创建订单测试 **Epic 9 完成状态:** - Story 9.1-9.5:所有业务测试已完成 ✅ - Story 9.6:并行隔离验证已完成 ✅ - Story 9.7:稳定性验证(当前)🔄 **测试文件模式:** - 测试文件命名:`disability-person-{feature}.spec.ts` - Page Object 方法命名:动词+名词 - 选择器策略:`data-testid` 优先 ### References **源文档引用:** - [Source: _bmad-output/planning-artifacts/epics.md#Epic-9-Story-9.7] - 完整业务需求 - [Source: _bmad-output/planning-artifacts/architecture.md#Testing-Standards] - 测试稳定性标准 - [Source: web/tests/e2e/playwright.config.ts] - Playwright 配置文件 **前置 Story 参考:** - [Source: _bmad-output/implementation-artifacts/9-1-photo-upload-tests.md] - 照片上传测试 - [Source: _bmad-output/implementation-artifacts/9-2-bankcard-tests.md] - 银行卡测试 - [Source: _bmad-output/implementation-artifacts/9-3-note-tests.md] - 备注测试 - [Source: _bmad-output/implementation-artifacts/9-4-visit-tests.md] - 回访记录测试 - [Source: _bmad-output/implementation-artifacts/9-5-crud-tests.md] - CRUD 测试 - [Source: _bmad-output/implementation-artifacts/9-6-parallel-isolation.md] - 并行隔离验证 **Playwright 文档:** - [Playwright Test Retry](https://playwright.dev/docs/test-retries) - [Playwright CI Configuration](https://playwright.dev/docs/ci) - [Playwright Best Practices](https://playwright.dev/docs/best-practices) ## Dev Agent Record ### Agent Model Used _Created by create-story workflow based on epics.md and previous stories_ ### Debug Log References ### Completion Notes List _待开发完成后填写_ ### File List **创建的文件:** - `_bmad-output/implementation-artifacts/9-7-stability-validation.md` - 本 story 文档 - `web/tests/e2e/scripts/run-stability-test.sh` - 稳定性测试脚本(待创建) - `web/tests/e2e/scripts/run-stability-serial.sh` - 串行模式脚本(待创建) - `web/tests/e2e/scripts/run-stability-single.sh` - 单文件测试脚本(待创建) **测试的文件:** - `web/tests/e2e/specs/admin/disability-person-photo.spec.ts` - `web/tests/e2e/specs/admin/disability-person-bankcard.spec.ts` - `web/tests/e2e/specs/admin/disability-person-note.spec.ts` - `web/tests/e2e/specs/admin/disability-person-visit.spec.ts` - `web/tests/e2e/specs/admin/disability-person-crud.spec.ts`