|
|
@@ -0,0 +1,203 @@
|
|
|
+# 测试负责人汇报 · R97(2026-11-09 06:10,本自动化闭环)
|
|
|
+
|
|
|
+> 执行明细与证据见同目录台账;本文件随 `docs/tdd/test/automation-run-2026-11-09-R97.md`、`blockers.md` 一并 push 至 `origin/cfclub` 作为研发通知载体(Agent Mail 仍未开通 `not_bound`,无企微通道)。
|
|
|
+> 基线:`cfclub` @ 跑测起点 `f985f9274`;跑测期间 HEAD 前进至 `1abfc7348`(7 个提交,**全部 docs/版本号,零源码变更**)→ 本轮结果对两个 SHA 均有效。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 一、执行总览(R97 vs R96)
|
|
|
+
|
|
|
+| 维度 | R97 结果 | R96 基线 | 变化 |
|
|
|
+|---|---|---|---|
|
|
|
+| **后端全量(JUnit)** | **333 类 / 2802 例 / 2655 过 / 132F+11E+4S = 94.75%**(剔 skip 94.89%),34 红类 / 143 红例,耗时 1:00h | 承袭 R95 2753/115 红/95.68%(**未实测**) | **★ 首次实测**(推翻 R96「本节点无 Maven」) |
|
|
|
+| cfc-frontend jest | **423 / 371 / 49 / 3 skip = 87.71%** | 423 / 371 / 49 / 3 | **零漂移** |
|
|
|
+| cfc-web jest | **116 / 116 / 0** | 116 / 116 | 零漂移 |
|
|
|
+| tests/ 根级 jest | **23 / 7 / 16** | 23 / 7 / 16 | 零漂移(B-36 环境依赖) |
|
|
|
+| **langgraph @251 实派 pytest** | **43 / 33 / 10**(183.67s,`--ignore=tests/test_chat.py`) | 本机 44 / 32 / 12 | **★ 派发 251 达成**(G10 首次通过) |
|
|
|
+| 浏览器 live(admin+frontend+shop) | **15 / 15 全绿 · 0 skip** | 15/15(1 例曾 skip) | **★ B-76/B-59 装置修复,零跳过** |
|
|
|
+| 浏览器 health-contract | **13 / 13 全绿** | 13/13 | 零漂移 |
|
|
|
+| **合计(可执行全量)** | **3435 例 / 3210 过 = 93.45%** | — | 首份可复算全量口径 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 二、后端 143 红例三层归因(关键,非全为回归)
|
|
|
+
|
|
|
+| 层 | 例数 | 类数 | 代表证据 | 性质 |
|
|
|
+|---|---|---|---|---|
|
|
|
+| **预期 RED(TDD 契约待实现)** | **94** | 14 | `Guhe*ContractTest` 13 类 85 例,失败消息直接内嵌需求编号(如「契约方法 `AttributionComplianceGate#tagEvidence` 未实现(G-3 证据码隔离,T11)」);`DietFoodHealthAdjustContractTest` 9 例(§3 A1/A3/A5) | 研发 TDD 红态,**非回归** |
|
|
|
+| **A 类(测试侧缺陷,测试可自处置)** | **37** | 14 | `CfCommissionServiceSettleTest` 8(档位查询未 stub → `Wanted but not invoked`);`ArticleAutoTagServiceTest` 4(verify 目标 `taskExecutor` 与注入不一致);`DimensionScoreServiceImplTest` 4(`No value present`);`ArticleWorkflowTest` 3(源码文案已改「仅已驳回或已撤回」,断言仍旧文案);`doNothing()` 误用 2(`DailyCheckinStreakFlowTest` / `PlannerBindInviteFlowTest`) | 夹具/桩/断言过期 |
|
|
|
+| **B 类(产品缺陷,需研发修)** | **12** | 4 | `MindFortuneControllerTest` 1(401 vs **400**,B-69 连续第 5 轮);`EnergySystemFlowTest` 6(500);`PlannerBindInviteFlowTest` 4(403);`GuideModuleIntegrationTest` 1(`Data truncation: platform_fee` 列越界) | 真缺陷 |
|
|
|
+
|
|
|
+> 口径说明:`@Test 2792 + 参数化展开 26 − @Disabled 4 − 早退截断 12 = 2802`,误差 **0**;333/333 XML 无静默丢失;`testCompile 339 源 0 错`。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 三、本轮四项结论修正(推翻前轮定性)
|
|
|
+
|
|
|
+### 3.1 推翻「本节点无 Maven」(R96)
|
|
|
+`which mvn` 为空但 **IDEA 自带 Maven 3.9.9 + `JAVA_HOME=D:\jdk1.8.0_25`** 可用 → 后端全量 1:00h 跑完。**R96 后端 95.68% 与 115 红为承袭值、未实测**,本轮为 R94 之后首次真实全量。
|
|
|
+
|
|
|
+### 3.2 **B-65(P0)证据升级:线上 200 / 251 pytest 500 —— 部署与依赖版本不一致**
|
|
|
+- 251 **live HTTP**:`POST /api/v1/analyze {report_id:1,user_id:1,focus:"general"}` → **200**,返回完整分析 JSON(15.77s,trace_id 齐全);`POST /api/v1/chat {query,...}` → **200**(28.44s,B-77 确认已闭环)。
|
|
|
+- 251 **pytest 实派**:`test_analyze.py` 2 例 **500**,异常 `ValueError: Checkpointer requires ... thread_id`。
|
|
|
+- 本机源码同因复现:`analysis_graph.py:96 MemorySaver()` + `analyze.py:35 ainvoke` 未传 config;本机 venv(langgraph **0.6.11**)直接 `ValueError`。
|
|
|
+- **判定**:不是「研发已修」,而是**运行实例依赖版本低于仓库锁版本**——线上侥幸可用,**一旦依赖升级即 100% 500**。P0 维持,修法不变(去 `MemorySaver()` 或 `ainvoke` 传 `thread_id`)。
|
|
|
+
|
|
|
+### 3.3 **B-69 证据升级:4 个 `/api/mind/**` 在「公开白名单」内**
|
|
|
+源码 `JwtInterceptor.java:79-82` 将 `/api/mind/alert/active`、`/api/mind/alert/checkin-alerts`、`/api/mind/traditional/mirror`、`/api/mind/traditional/compatibility` **列入 PUBLIC_PATHS(匿名白名单)**,线上实测匿名可达业务层:
|
|
|
+
|
|
|
+| 端点 | 匿名响应 |
|
|
|
+|---|---|
|
|
|
+| `POST /api/mind/alert/active` | `{"code":500,"message":"参数缺失:memberId"}` |
|
|
|
+| `POST /api/mind/traditional/mirror` | `{"code":200,"message":"success","data":{}}` |
|
|
|
+| 对照 `POST /api/health/plan/list` | `401` ✅ |
|
|
|
+
|
|
|
+→ 应把这 4 条从 PUBLIC_PATHS **移入 `LOGIN_REQUIRED_PATHS`**;后端 `MindFortuneControllerTest` 断言 `401` 仍红(实际 400),与线上同源。
|
|
|
+
|
|
|
+### 3.4 **B-76 / B-59 闭环(测试侧自处置)**
|
|
|
+`TC-A-U04` 首跑红(`登录身份`未自动带出),独立复跑 2/2 通过、`account-roles` 接口 5/5 均 60-110ms → 判为**装置时序竞态**而非产品回归。根因:全量串行时 `goto` 仅到 `domcontentloaded`,Vue 未挂载时 `fill()` 的 `@input` 无监听器 → 500ms 防抖查询永不发出。修复:
|
|
|
+1. 新增 `waitLoginFormReady()`(等表单可见 + 可编辑 + 登录按钮渲染);
|
|
|
+2. 新增 `fillPhoneAndAwaitRoles()`:**等 `account-roles` XHR 实际返回**并断言 200(禁止固定 sleep);
|
|
|
+3. `TC-A-U05` 原 `test.skip(登录未通过)`(吞掉前置失败、门禁显示"无失败")→ 改**硬断言**(B-59)。
|
|
|
+
|
|
|
+修复后 admin **5/5**、全套件 **15/15 零 skip**。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 四、SRS → 用例更新闭环(本轮无新增 SRS)
|
|
|
+
|
|
|
+窗口内 SRS 变更仅 3 份,**均已有对应用例**,无需补写:
|
|
|
+
|
|
|
+| SRS | 能力键 / 任务 | 对应用例 | 状态 |
|
|
|
+|---|---|---|---|
|
|
|
+| `2026-11-09-diet-recommendation-health-questionnaire-adjust.md` | S-cfc-97 | `recommendation.healthAdjustUi.test.js` 8 RED + `DietFoodHealthAdjustContractTest` 9 RED | 待实现 |
|
|
|
+| `2026-11-09-signature-canvas2d-rewrite.md` | S-cfc-116 | `signature.canvas2d.test.js` 9 RED / 2 GREEN | 待实现(源码 `enterLandscape` 仍 4 处命中、`canvasToTempFilePath` 0 命中) |
|
|
|
+| `2026-11-08-diet-recommendation-polish.md` | S-cfc-79 / S-cfc-80 | `recommendation.uiRework` 25 RED + `participantSelect` 8 RED | 待实现(`currentTab/pagedFoods/loadMore` 命中 0) |
|
|
|
+| `2026-11-08-signature-landscape-fix.md` | B-75 | 已被 v2 整份取代,旧用例归档 `.superseded.js` | 已作废 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 五、覆盖度量(本轮统一口径,可复算)
|
|
|
+
|
|
|
+| 指标 | 值 | 口径 |
|
|
|
+|---|---|---|
|
|
|
+| 场景 SC | **245** | `docs/**/*.md` 去重 `SC-*` |
|
|
|
+| SC 被测试资产引用 | **137(55.9%)** | `cfc-frontend/__tests__`、`cfc-web/src/__tests__`、`cfc-backend/src/test`、`tests/e2e*` |
|
|
|
+| TC 台账条数 | **824** | `tests/test-cases/*.md` 去重 |
|
|
|
+| 其中异常流(-E/-P) | **496(60.2%)** | 同上 |
|
|
|
+| **TC 可执行锚点** | **95(11.5%)** | 排除 `tests/e2e/api/generated/cases.json`(生成物),见 B-86 |
|
|
|
+| 测试文件 / `@Test` | 333 / 2792 | 后端 |
|
|
|
+| 控制器 / `@GetMapping` 违规 | 249 / **8** | 仍违 AGENTS.md |
|
|
|
+
|
|
|
+> ⚠️ **B-86(新增)**:`tests/e2e/api/generated/cases.json` 内含 797 个 TC 编号,会让「锚点覆盖率」虚高到 96.7%;该文件是**描述性生成物**、非可执行资产,必须先剔除再统计(与 B-30/B-32 同族陷阱)。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 六、域结论表
|
|
|
+
|
|
|
+| 审查维度 | 负责专家 | 结论 | 关键证据 |
|
|
|
+|---|---|---|---|
|
|
|
+| 单元·组件 | 苏雅 | **不通过** | 后端 34 红类,其中 A 类桩/夹具缺陷 37 例;无覆盖率/变异工具(未实测) |
|
|
|
+| 集成·接口 | 柯砚 | **不通过** | `EnergySystemFlowTest` 6×500、`PlannerBindInviteFlowTest` 4×403、`GuideModule` `platform_fee` 越界 |
|
|
|
+| 系统·验收 | 白樾 | **有条件通过** | 浏览器 15/15 + health 13/13 全绿;UAT/BDD 无资产 |
|
|
|
+| 测试保障 | 闻朔 | **不通过** | CI 为 blocking/observed 两级,observed 白名单仍含 33 类;冒烟无独立门禁 |
|
|
|
+| 性能·可靠性 | 骆骋 | **未实测** | 无压测工具/未授权;仅 `ActivityControllerTest` 222s、`GuidePackageServiceTest` 436s 作劣化信号 |
|
|
|
+| 安全 | 关屿 | **不通过** | B-69 四个 `/api/mind/**` 匿名可达业务层;health 契约 13/13 其余端点 401 正常;SAST/SCA 无工具 |
|
|
|
+| 兼容·体验 | 阮清 | **有条件通过** | 仅 admin-desktop + H5 mobile 两档;无障碍/多浏览器未测 |
|
|
|
+| 流程·度量·代码 | 何序 | **不通过** | `@GetMapping` 8 处违规;CI 无后端全量硬门禁;TC 锚点 11.5% |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 七、五要素问题清单(P-1 ~ P-6)
|
|
|
+
|
|
|
+### P-1(P0)langgraph `/api/v1/analyze` 源码级 checkpointer 缺 thread_id
|
|
|
+1. **问题描述**:251 live 返回 200,但 251 pytest 与本地 venv 均 500 `ValueError: Checkpointer requires ... thread_id`。
|
|
|
+2. **测试 bug 点**:`cfc-langgraph/tests/test_analyze.py::test_analyze_endpoint`、`::test_analyze_missing_report`(`assert 500 == 200`);生产帧 `app/graphs/analysis_graph.py:96`、`app/api/analyze.py:35`。
|
|
|
+3. **最优修改方案**:`analysis_graph.create_analysis_graph()` 删除 `checkpointer=MemorySaver()`(或改 `app/checkpointer.py` 的共享 saver),并在 `analyze.py` 的 `ainvoke` 传 `config={"configurable":{"thread_id": f"analysis-{req.report_id}-{req.user_id}"}}`。
|
|
|
+4. **修改目的**:消除「依赖版本决定成败」的隐性 P0,保证依赖升级后 analyze 不 100% 失败。
|
|
|
+5. **闭环方式**:251 重派 `pytest tests/test_analyze.py -q` → 2 例 200 转绿;并 `curl /api/v1/analyze` 连跑 3 次 200 且耗时有界。
|
|
|
+
|
|
|
+### P-2(P1)B-69:4 个 `/api/mind/**` 位于公开白名单
|
|
|
+1. **问题描述**:匿名请求可进入业务层(`alert/active` 500「参数缺失:memberId」、`traditional/mirror` 200 空数据),未在网关层拒绝。
|
|
|
+2. **测试 bug 点**:`cfc-backend/src/test/java/com/etotem/cfc/controller/mind/MindFortuneControllerTest.java::testGetTodayFortuneWithoutAuth`(`expected:<401> but was:<400>`);生产帧 `config/JwtInterceptor.java:79-82`。
|
|
|
+3. **最优修改方案**:把这 4 条从 `PUBLIC_PATHS` 移入 `LOGIN_REQUIRED_PATHS`;若确需匿名,改为显式 `userId=-1` 只读分支并在 controller 首行返回 401。
|
|
|
+4. **修改目的**:匿名不得触达用户私有数据读写路径。
|
|
|
+5. **闭环方式**:`MindFortuneControllerTest` 转绿 + 线上 4 端点匿名 curl 全 401。
|
|
|
+
|
|
|
+### P-3(P1)A 类测试侧 37 例(桩/夹具/断言过期)
|
|
|
+1. **问题描述**:`CfCommissionServiceSettleTest` 8、`ArticleAutoTagServiceTest` 4、`DimensionScoreServiceImplTest` 4、`ArticleWorkflowTest` 3、`doNothing()` 误用 2 等共 37 例红,失败信息指向测试装置而非产品。
|
|
|
+2. **测试 bug 点**:`ArticleWorkflowTest.reDraft_notRejected_*`(期望「仅已驳回的文章可重新编辑」,实际「仅已驳回或已撤回…」);`DailyCheckinStreakFlowTest.childDeletesCheckin_Success` 与 `PlannerBindInviteFlowTest.parentUnbindsGuide_Success`(`doNothing()` 作用于非 void 方法)。
|
|
|
+3. **最优修改方案**:按类逐条对齐——文案断言改为当前产品文案;`doNothing()` 改 `when(...).thenReturn(...)` 或删;`CfCommission` 补档位查询 stub;`ArticleAutoTag` 统一 mock 字段名与注入名。
|
|
|
+4. **修改目的**:把 37 例「装置红」清出,使红例集合只剩真缺陷与预期 RED,门禁信号可信。
|
|
|
+5. **闭环方式**:定向 `mvn -Dtest=A,B,C -DfailIfNoTests=false test`(须用逗号、须核对 `Tests run:` 行),37 例转绿且其余类零转红。
|
|
|
+
|
|
|
+### P-4(P1)B 类产品缺陷 12 例
|
|
|
+1. **问题描述**:`EnergySystemFlowTest` 6×500、`PlannerBindInviteFlowTest` 4×403、`GuideModuleIntegrationTest` `platform_fee` 数据截断、`MindFortune` 401/400。
|
|
|
+2. **测试 bug 点**:`com.etotem.cfc.integration.EnergySystemFlowTest`(`expected:<200> but was:<500>` ×4、`expected:<500> but was:<5001>`)、`PlannerBindInviteFlowTest.parentConfirmsBind_Success`(403)、`GuideModuleIntegrationTest.testGuidePackageCreationFlow`(`MysqlDataTruncation: Out of range value for column 'platform_fee'`)。
|
|
|
+3. **最优修改方案**:EnergySystem 查 500 的 `Caused by` 最内层;PlannerBind 核对绑定态鉴权(403 疑角色闸门);`platform_fee` 列宽 `ALTER` 或写入前按分转元裁剪。
|
|
|
+4. **修改目的**:消除集成链路上的 5xx / 越权 / 数据截断。
|
|
|
+5. **闭环方式**:对应 4 类定向复跑转绿 + 线上同路径 curl 非 5xx。
|
|
|
+
|
|
|
+### P-5(P1)langgraph 套件非终止(B-84 新增)
|
|
|
+1. **问题描述**:`tests/test_chat.py` 走真实 LLM(意图分类→主生成→任务提取→记忆 embedding),本机运行 >35 分钟未结束、251 >10 分钟未结束,整套件**无法收敛**。
|
|
|
+2. **测试 bug 点**:`cfc-langgraph/tests/test_chat.py::test_chat_endpoint`;无 `pytest-timeout`、无 LLM 桩。
|
|
|
+3. **最优修改方案**:对该用例加 `@pytest.mark.timeout(120)` 或 `monkeypatch` 掉 LLM/embedding(仅断言编排链路);并在 `pytest.ini` 设 `timeout = 180`。
|
|
|
+4. **修改目的**:让 langgraph 套件可在 CI 内有界完成,否则 251 派发与 CI 都会挂死。
|
|
|
+5. **闭环方式**:全量 `pytest tests --ignore=tests/qna` 在 ≤5 分钟内自然结束并给出汇总行。
|
|
|
+
|
|
|
+### P-6(P1)预期 RED 契约 94 例待实现
|
|
|
+1. **问题描述**:`Guhe*ContractTest` 13 类 85 例 + `DietFoodHealthAdjustContractTest` 9 例,失败消息均为「方法/常量/字段未实现」。
|
|
|
+2. **测试 bug 点**:`com.etotem.cfc.unit.GuheEvidenceIsolateContractTest`(11)、`GuheNoPathMapContractTest`(10)、`GuheKbVersionSenseContractTest`(9)、`GuheLowSideRuleLoadContractTest`(9)、`DietFoodHealthAdjustContractTest`(9)等。
|
|
|
+3. **最优修改方案**:按契约逐项实现(`AttributionComplianceGate#tagEvidence/canEnterRecommendationBasis/isExistenceRecordOnly`、`AttributionLowSideRules.EVIDENCE_PUB/COM`、`Food.adjustmentReason` 瞬态字段、`loadProfile` 读 `lifestyle.allergySymptoms`、`generateIngredientList` 读 `dietType`)。
|
|
|
+4. **修改目的**:把 TDD 红态收口为可发布能力。
|
|
|
+5. **闭环方式**:对应契约类逐类转绿 + 状态机置 YELLOW。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 八、门禁结论
|
|
|
+
|
|
|
+**不通过**(用户双目标均未达成,但本轮为「首次取得可复算全量口径」的结构性改善轮)。
|
|
|
+
|
|
|
+| 门禁 | 阈值 | 实测 | 结论 |
|
|
|
+|---|---|---|---|
|
|
|
+| G1 全量用例通过率 | ≥96% | **93.45%**(后端 94.75%) | ❌ |
|
|
|
+| G2 红例数 | 0 | **218**(143+49+16+10) | ❌ |
|
|
|
+| G3 管理端全绿 | 100% | 116/116 | ✅ |
|
|
|
+| G4 后端可构建 | 0 编译错 | testCompile 339 源 0 错 | ✅ |
|
|
|
+| G5 结果完整性 | 无静默丢失 | 333/333 XML | ✅ |
|
|
|
+| G6 浏览器套件 | 28/28 | **28/28(零 skip)** | ✅ |
|
|
|
+| G7 langgraph 零失败 | 0 红 | 10 红 | ❌ |
|
|
|
+| G8 鉴权契约 | 13/13 | 13/13 | ✅ |
|
|
|
+| G9 SRS/TC 可执行锚点 | ≥80% | **11.5%** | ❌ |
|
|
|
+| **G10 节点派发** | 251 实派 | **pytest 43 例在 251 实跑回传** | ✅ **首次通过** |
|
|
|
+| G11 CI 硬门禁 | 全量 blocking | 仍为 blocking/observed 两级,observed 含 33 红类 | ❌ |
|
|
|
+| G12 SRS 变更→用例更新 | 100% | 3 份 SRS 均有对应用例 | ✅ |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 九、对照用户双目标
|
|
|
+
|
|
|
+- **目标① 所有用例通过**:❌ 3210/3435 = 93.45%。结构:**预期 RED 契约 94 + 前端预期 RED 49 + A 类装置 37 + B 类产品 12 + 根级环境 16 + langgraph 10**。其中「一修即绿」的 A 类 37 例由测试侧自处置(下轮)。
|
|
|
+- **目标② 覆盖全部 SRS + 用户场景(含异常流)**:❌ 场景 245 个、被测试引用 137(55.9%);TC 台账 824 条、异常流 496(60.2%,**设计层够**)、但可执行锚点仅 95(11.5%)→ 异常流「有设计、缺执行锚定」。
|
|
|
+
|
|
|
+## 十、复评条件(下轮验收判据)
|
|
|
+
|
|
|
+1. P-1(thread_id)修 → 251 `test_analyze` 2 例转绿 + 本地 venv 同步转绿。
|
|
|
+2. P-2(mind 白名单)修 → `MindFortuneControllerTest` 转绿 + 线上 4 端点匿名 401。
|
|
|
+3. P-3(A 类 37 例)测试侧处置 → 后端红例 143→106、通过率升至约 96.0%。
|
|
|
+4. P-5(test_chat 超时)处置 → langgraph 套件可在 ≤5 分钟收敛,251 派发纳入常规。
|
|
|
+5. P-6(94 契约)逐类实现 → 后端通过率越过 99%。
|
|
|
+
|
|
|
+## 十一、证据清单(本机,未入库)
|
|
|
+
|
|
|
+| 文件 | 内容 |
|
|
|
+|---|---|
|
|
|
+| `_r97_backend.log` | 后端全量,1:00h,BUILD FAILURE(测试红) |
|
|
|
+| `_r97_aggregate.py` / `_r97_red_cases.tsv` | 333 类聚合 + 143 红例逐条(类/方法/消息) |
|
|
|
+| `_r97_jest_fe.log` | 前端 423/371/49/3 |
|
|
|
+| `_r97_jest_web.log` | 管理端 116/116 |
|
|
|
+| `_r97_browser_live2.json` | live 15/15(零 skip) |
|
|
|
+| `_r97_browser_health.json` | health 13/13 |
|
|
|
+| `_r97_pytest2.log` | 本机 langgraph 部分输出(后因 CPU 争抢主动终止) |
|
|
|
+| 251 会话 `ses_e42f48001ffe68snntYwLew6N6` | 251 实派 pytest:10 failed / 33 passed / 183.67s |
|
|
|
+| 251 会话 `ses_e4303bd70ffexUVzJkgwbxS5n4` | 251 仓库 HEAD `4f1cf92ec` / 分支 `cfclub` |
|