|
|
@@ -0,0 +1,355 @@
|
|
|
+# 测试负责人工作汇报(R170 轮)
|
|
|
+
|
|
|
+> 本汇报按《测试负责人工作汇报模板》填写。R170 为**全量实跑轮**:三节点派发(189 admin 浏览器 / 251 langgraph pytest / 本机串行后端全量 + Jest + 浏览器 + **新增 API 契约层**),所有维度均为本轮新实测。
|
|
|
+> 对比基线 R169(13:50):窗口 `8524533c8..efc730771` 仅 cfc-web 构建元数据(`package-lock`/CHANGELOG/`.last_build_commit`)与研发 docs,**零功能源码变更** → 后端结论可比。
|
|
|
+> 本轮最大增量:① 首次把 **API 非功能层(32 例:冒烟 / 安全 / 性能兼容 / 追溯契约)** 纳入常规闭环;② 修正 **3 处用例自身缺陷**(2 例假红转绿、1 例按新需求改为显式 skip);③ 新发现 **B-170-1**(`activities.approved_count` 回填 SQL 恒失败,28/28 上下文全灭)。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 基本信息
|
|
|
+
|
|
|
+| 项目 | 内容 |
|
|
|
+|------|------|
|
|
|
+| 汇报人 | 测试负责人(自动化测试闭环任务) |
|
|
|
+| 汇报周期 | 2026年11月12日 14:11 ~ 15:20(第 170 轮) |
|
|
|
+| 基线 | `cfclub @ 8524533c8`(R169 结论点)→ `efc730771`(`pull --rebase --autostash` 后) |
|
|
|
+| 窗口内需求变更 | **零功能源码变更**:仅 cfc-web 版本号/CHANGELOG + `docs/tdd`(9 文件 +390/−13) |
|
|
|
+| 负责模块/单元 | 全站回归:cfc-backend JUnit 全量 · 管理端 admin@189 · 小程序 H5/shop/health/dx@本机 · cfc-langgraph@251 · 前端/Web Jest · 根级黑盒 · **线上 API 非功能层** |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 一、本轮工作数据汇总
|
|
|
+
|
|
|
+### 1.1 测试用例建设
|
|
|
+
|
|
|
+| 指标 | 数量 | 填写说明 |
|
|
|
+|------|------|----------|
|
|
|
+| **本轮新增测试用例数\*** | **0 个**(新增**执行**32 例为既有资产首次入闭环,非新建) | SRS/场景闸门窗口零变更(`git diff 8524533c8..HEAD -- docs/superpowers/specs tests/test-cases` = 空)→ G12 合规,无需因变更更新用例 |
|
|
|
+| **本轮验证执行测试数\*** | **3933 个**(全部本轮实跑) | 后端 JUnit 3057 + 前端 Jest 624 + 管理端 Jest 116 + langgraph 51 + 浏览器 30(28 过 + 2 跳)+ **线上 API 32(25 过 + 7 跳)** + 根级黑盒 23 |
|
|
|
+| **用例通过率** | **98.17%**(3861/3933;剔除 skip **98.80%**) | 红 47 / 跳 25,明细见 §5.2 |
|
|
|
+| **用例台账** | 15 份台账 + README(`tests/test-cases/`) | 唯一 TC 编号 367;本轮为台账补 **§10 锚点双向核对**(见 §3.4) |
|
|
|
+
|
|
|
+### 1.2 会话与任务分发
|
|
|
+
|
|
|
+| 指标 | 数量 | 填写说明 |
|
|
|
+|------|------|----------|
|
|
|
+| **分派任务数\*** | **3 个** | R170-1 → `opencode-189`(admin-desktop **5/5 EXIT=0**,1.4m);R170-2 → `opencode-251`(langgraph pytest **46/51**,129.43s);R170-3 → 本机串行(后端全量 45m + 三套 Jest + 本机浏览器 + API 层) |
|
|
|
+| **恢复智能体会话数\*** | 0 个 | 189 首派即 5/5(B-153-1 销号后第 10 轮);251 首派即跑完 |
|
|
|
+| **当前在用会话数** | 0 个 | 全部收尾,无残留浏览器任务(符合「每节点仅一任务」约束) |
|
|
|
+
|
|
|
+### 1.2b 各会话当前工作状态列表
|
|
|
+
|
|
|
+| 会话标签 | 会话 ID/地址 | 当前状态 | 当前任务 | 静默/空闲时长 | 工作目录 | 备注 |
|
|
|
+|----------|--------------|----------|----------|---------------|----------|------|
|
|
|
+| `opencode-189` | 192.168.16.189:4090 | done | admin-desktop UI E2E | 已完成(1.4m) | `C:\code\cfc\tests` | **5/5 EXIT=0**;节点 HEAD `8524533c8`、spec blob `4703d73fb…` **与本机 HEAD 完全一致** → 跨节点可比 |
|
|
|
+| `opencode-251` | 192.168.16.251:4096 | done | langgraph pytest 51 例 | 已完成(129.43s) | `/sc-data/cfc/cfc-langgraph` | **46 过 / 5 红**;节点 HEAD `efc730771` = 本机;`EXIT=` 未落盘(B-126 第 5 轮复现) |
|
|
|
+| `local-browser` | 本机进程 | done | fe / shop / health / dx | 已完成(1.0m + 8.3s + 6.3s + 跳过) | `d:\cfc\tests` | fe **6/6**、shop **4/4**、health **13/13**、dx **2 skip**(B-DX-1 端点 404) |
|
|
|
+| `local-api` | 本机进程 | done | 线上 API 冒烟/安全/性能兼容 | 已完成(9.8s + 10.1s + 15.1s) | `d:\cfc\tests` | api-smoke **4/4**、security **11/11**(修正后)、perf-compat **4 过 / 3 跳** |
|
|
|
+| `local-mvn` | 本机进程 | done | cfc-backend 全量 | 已完成(**45m**,14:15→15:00) | `d:\cfc\cfc-backend` | 363 类 / 3057 例 / 3030 过 / 17F+6E+4S = **99.12%**;编译 0 错、dump 0 |
|
|
|
+| `local-jest` | 本机进程 | done | cfc-frontend + cfc-web + 根级 | 已完成(32.2s + 23.5s + 18.2s) | `cfc-frontend` / `cfc-web` / `tests` | fe 609/3/12、web 116/116、根级 7/16(9082 未起,B-36 第 56 轮) |
|
|
|
+
|
|
|
+### 1.3 问题处置
|
|
|
+
|
|
|
+| 指标 | 数量 | 填写说明 |
|
|
|
+|------|------|----------|
|
|
|
+| **新测试发现问题数\*** | **1 个(产品)+ 4 个(测试资产/度量)** | 产品:**B-170-1** `activities.approved_count` 回填 SQL 恒失败(P2 数据一致性);测试资产:B-170-2(2 处用例缺陷,已自修)、B-170-3(用例未随会员门控更新,已改 skip)、B-170-4(锚点双向失真)、B-170-5(251 chat 挂死) |
|
|
|
+| **已解决测试相关问题数\*** | **3 个** | ① `TC-A-N05` 探针选错(拿登录接口当特权入口)→ 改 `/api/admin/families/overview` → **绿**;② `TC-P-N11` 路径错(`/api/assessment` → 真实 `/api/health`)+口径错(用 HTTP 码判业务拒绝)→ 改业务码判据 → **绿**;③ `TC-P-N02/X-N01` 未随 S-cfc-163 更新 → **假红转显式 skip**(不假绿) |
|
|
|
+| **待解决测试相关问题数** | 7 个(P0×1 / P1×4 / P2×2) | ① B-142-2 / B-170-5 langgraph 上游 429 与 chat 挂死(P0);② B-152-1/2 CI 清单双向失真(P0/P1);③ B-156-1 建表 SQL 无效(P1);④ B-162-1 未入库测试文件(P1);⑤ S-cfc-151 剩余 1 红(P1);⑥ B-170-1 approved_count 回填(P2);⑦ B-36 根级 16 红(P2,环境型) |
|
|
|
+
|
|
|
+### 1.4 本轮 git 提交与推送证据(真理证据)
|
|
|
+
|
|
|
+| 提交 sha | 关联任务/能力键 | 阶段 | 触及文件类型 | 目标分支 | 已推送远端 | 备注 |
|
|
|
+|----------|-----------------|------|--------------|----------|------------|------|
|
|
|
+| `e4adf8f2a` | 全站巡检 R170 | 汇报 | 测试文档(报告/run/通知/blockers)+ 测试资产(3 处用例修正 + 追溯矩阵附录 + traceability 游离 spec 入库) | cfclub | ✅ 已推送 `origin/cfclub`(`efc730771..e4adf8f2a`,ahead/behind 0/0,`git branch -r --contains` 核验 PASS) | **结果有变化**(API 层 +32 例、3 处用例修正、后端零漂移第 17 次、lg 3→5 红、新增 B-170-1)→ 按规则提交并通知研发(`notice-2026-11-12-R170-研发通知.md`) |
|
|
|
+
|
|
|
+### 1.5 状态机阶段分布(全局进度)
|
|
|
+
|
|
|
+| 阶段 | 键数 | 备注 |
|
|
|
+|------|------|------|
|
|
|
+| UNTRACKED | 0 | 需求侧 ⏳ 0 键(窗口零新增规格) |
|
|
|
+| RED | 0 | 测试侧本轮零新建红单测(3 处为既有用例修正而非新键) |
|
|
|
+| YELLOW | 63 | 研发侧口径(承袭 R169) |
|
|
|
+| GREEN | 8 | 已实现待部署归集 |
|
|
|
+| DONE | 15 | 已归档 |
|
|
|
+| 合计 | 86 | 本轮零流转(无新契约键入池) |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 二、历史审查记录(阶段 -1 记忆召回)
|
|
|
+
|
|
|
+| 项 | 内容 |
|
|
|
+|---|---|
|
|
|
+| 上次审查 | **R169(2026-11-12 13:50)**,结论「不通过(承袭,正向改善)」 |
|
|
|
+| 遗留缺口 | 后端 23 红(存量 17 + 预期 RED 6)· langgraph 3 红(429)· 根级 16 红(9082 未起)· CI 清单漏拦 · G9 锚点 18.5% · B-156-1 / B-162-1 未修 |
|
|
|
+| 本次是否改善 | **是**:后端 23 红逐例持平(第 17 次零漂移)→ 无回归;langgraph **3→5 红(恶化,上游 429)**;API 层新增 32 例(25 过);G9 口径更正为 **20.7%**(环比 +2.2pp 属口径细化而非真实提升) |
|
|
|
+| 教训应用 | ① 沿用「Maven 工程根在 `cfc-backend`」;② 沿用「远程 kick 分离 + 单次读日志」;③ 本轮**新增**教训:判定用例红之前必须先问「是用例错还是产品错」——本轮 3 处红中 3 处全是用例错,产品 0 新增缺陷 |
|
|
|
+
|
|
|
+> 本次为该对象**第 170 次**审查,有历史记录;上述内容仅作对照,**本次结论全部来自本轮实测**。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 三、项目画像与覆盖矩阵
|
|
|
+
|
|
|
+### 3.1 项目画像(承袭并本轮核验)
|
|
|
+
|
|
|
+| 维度 | 内容 |
|
|
|
+|---|---|
|
|
|
+| 业务定位 | 家庭教育「五维能量」(身/心/智/行/富)测评 + 成长规划 + 商城 + 健康报告解析的微信小程序 + Web 管理端全栈系统 |
|
|
|
+| 技术栈 | 后端 Spring Boot 2.7.18 + MyBatis-Plus + Java 8(端口 9082)· 小程序 uni-app Vue2 · 管理端 Vue2 + Element UI(8082)· AI 服务 FastAPI + LangGraph + ChromaDB(9000) |
|
|
|
+| 模块结构 | `cfc-backend` / `cfc-frontend` / `cfc-web` / `cfc-langgraph` / `dan/danshop` / `tests`(分层测试) |
|
|
|
+| 关键路径 | 登录(微信/direct-register)→ 家庭与成员 → 五维测评/能量 → 成长规划(规划师)→ 商城订单 → 健康报告上传解析 → AI 对话(**S-cfc-163 起仅会员可见**) |
|
|
|
+| 测试现状 | 后端 363 测试类 / 3057 例;前端 Jest 624;管理端 Jest 116;浏览器 E2E 30;API 契约层 32;langgraph pytest 51;根级黑盒 23 |
|
|
|
+| 质量目标 | 全量通过率 ≥98%、浏览器 E2E 100%、langgraph 100%、锚点覆盖率 ≥80%、CI 硬门禁可用 |
|
|
|
+| 风险点 | LLM 上游配额(429)· 数据库迁移静默失败 · CI 排除清单失真 · 用例/台账命名双轨 |
|
|
|
+
|
|
|
+### 3.2 20 类测试覆盖矩阵(全类不省略)
|
|
|
+
|
|
|
+| # | 测试类型 | 状态 | 本轮证据 |
|
|
|
+|---|---|---|---|
|
|
|
+| 1 | 单元测试 | ✅ 已发现 | 后端 363 类 / 3057 例(surefire XML 全产出);前端 Jest 624;管理端 116 |
|
|
|
+| 2 | 测试覆盖率 | ⚠️ 部分 | cfc-web 有 `--coverage` 配置且历轮记录 Lines 9.95%;**后端 JaCoCo 未配置** → 后端行覆盖仍无法量化(延续缺口 G-170-3) |
|
|
|
+| 3 | 变异测试 | ❌ 未发现 | 仓库无 PIT/Stryker 配置;本轮未实测(离线档无工具) |
|
|
|
+| 4 | 集成测试 | ✅ 已发现 | 后端 `integration/**`(含 `AIChatControllerGateTest` 18 例、`GrowthPublicEndpointMappingTest` 5E);根级 `tests/integration` 16 红均因 9082 未起 |
|
|
|
+| 5 | 契约测试 | ✅ 已发现 | 后端 `*ContractTest` 多组:`DimensionRegistryMapContractTest`(3 红) / `TaskReviewScP11ContractTest`(1 红) / `ServiceRoleApplyBindInviteContractTest`(6/6) / `MembershipChatMemberGateContractTest`(6/6) / `HealthDataSourceBridgeContractTest`(16/16) |
|
|
|
+| 6 | 接口 API 测试 | ✅ 已发现(**本轮扩容**) | 线上 API 层 32 例:api-smoke 4/4、security 11/11、perf-compat 4 过 3 跳、traceability 6 过 4 跳 |
|
|
|
+| 7 | 系统 / 端到端 | ✅ 已发现 | 浏览器 28/28(189 admin 5 + 本机 fe 6 / shop 4 / health 13)+ 2 skip(dx,端点 404) |
|
|
|
+| 8 | 验收 UAT | ⚠️ 待核实 | 无独立 UAT 用例库;以 `tests/test-cases/*.md` 15 份台账近似验收口径,未与业务方逐条签署 |
|
|
|
+| 9 | BDD 规格 | ❌ 未发现 | 无 `.feature` / Cucumber 资产 |
|
|
|
+| 10 | 冒烟测试 | ✅ 已发现 | `api-smoke.spec.js` 4/4(自注册链路 / 成员列表 / 能量概览 / 越权 403)+ 根级冒烟 7/23 过 |
|
|
|
+| 11 | 回归测试 | ✅ 已发现 | 本轮全量回归 3933 例;后端与 R169 **逐类逐例零漂移(第 17 次)** |
|
|
|
+| 12 | 探索性测试 | ⚠️ 部分 | 本轮以「安全/健壮性探针」形式执行(畸形上传、空参登录、并发、UA 兼容),未形成独立探索性会话记录 |
|
|
|
+| 13 | 性能测试 | ⚠️ 部分 | 仅冒烟级:家庭列表 **72ms**、20 并发无 5xx(`429=0` 说明限流器未部署);**无真实压测**(execute 档需联网授权,未执行) |
|
|
|
+| 14 | 可靠性测试 | ⚠️ 部分 | 观察到 `DatabaseInitializer` 迁移 28 次静默失败(B-170-1/B-156-1);无故障注入 / 长稳测试 |
|
|
|
+| 15 | 安全测试(SAST/DAST/依赖) | ✅ 已发现(部分) | DAST 类 11 例全绿(IDOR 403、越权提权拒绝、XSS 不回显、上传被拒);**SAST / 依赖漏洞扫描未执行**(需联网,未授权) |
|
|
|
+| 16 | 兼容性测试 | ✅ 已发现 | 多端 UA 一致性 1 例通过;浏览器仅 Chromium(无 Firefox/WebKit 矩阵) |
|
|
|
+| 17 | 可用性测试 | ❌ 未发现 | 无可用性量表 / 用户任务完成率采集 |
|
|
|
+| 18 | 无障碍测试 | ❌ 未发现 | 无 axe / WCAG 断点;小程序 TabBar 语义未验证 |
|
|
|
+| 19 | QA 流程 | ⚠️ 部分 | 有 `blockers.md` / `automation-status.md` / 台账;**CI 硬门禁因排除清单失真而恒红(G11)** |
|
|
|
+| 20 | 质量指标 | ⚠️ 部分 | 通过率/红例/跳例可取;**锚点率与场景映射两套口径长期并存(B-124/B-170-4)** |
|
|
|
+
|
|
|
+**结论**:20 类中 ✅ 已发现 8 类、⚠️ 部分 8 类、❌ 未发现 4 类(变异、BDD、可用性、无障碍)。「未发现」仅表示扫描未命中,**不等于项目未做**。
|
|
|
+
|
|
|
+### 3.3 本轮实测数据总表
|
|
|
+
|
|
|
+| 套件 | 命令/节点 | 例数 | 过 | 红 | 跳 | 耗时 |
|
|
|
+|---|---|---|---|---|---|---|
|
|
|
+| 后端 JUnit | `cd cfc-backend && mvn -o -B clean test`(本机) | 3057 | 3030 | **23**(17F+6E) | 4 | **45m** |
|
|
|
+| 管理端 Jest | `cfc-web && npx jest` | 116 | 116 | 0 | 0 | 23.5s |
|
|
|
+| 前端 Jest | `cfc-frontend && npx jest` | 624 | 609 | 3 | 12 | 32.2s |
|
|
|
+| langgraph | 251 `POST /api/shell` → pytest | 51 | 46 | **5** | 0 | 129.4s |
|
|
|
+| 浏览器 E2E | 189 + 本机 | 30 | 28 | 0 | 2 | 1.4m + 1.0m |
|
|
|
+| 线上 API | `playwright.config.api.js` | 32 | 25 | 0 | 7 | 43.5s |
|
|
|
+| 根级黑盒 | `tests && npx jest` | 23 | 7 | **16** | 0 | 18.2s |
|
|
|
+| **合计** | — | **3933** | **3861** | **47** | **21** | **≈48m** |
|
|
|
+
|
|
|
+> 通过率 **98.17%**;剔除 skip **98.80%**。环比 R169(3901/3838=98.38%):+32 例(API 层)、+23 过、红 45→47(langgraph 3→5)。
|
|
|
+
|
|
|
+### 3.4 可执行锚点双向核对(本轮新增口径)
|
|
|
+
|
|
|
+| 指标 | 数值 |
|
|
|
+|---|---|
|
|
|
+| 台账唯一 TC 编号 | 367 |
|
|
|
+| 可执行锚点唯一编号 | 161 |
|
|
|
+| 双向命中 | **76** |
|
|
|
+| 孤儿锚点(执行有、台账无) | **85** |
|
|
|
+| 台账空转(有编号、无执行) | **291** |
|
|
|
+| 严格锚点覆盖率(G9) | **76/367 = 20.7%** |
|
|
|
+| 锚点可追溯率(新增 G9-b) | **76/161 = 47.2%** |
|
|
|
+| 场景→用例映射(G14) | **89/153 = 58.2%** |
|
|
|
+
|
|
|
+**根因**:可执行资产并存两套命名——`TC-<域>-U<NN>`(UI/用户态,如 `TC-A-U01`、`TC-H-U02`)与 `TC-<域>-<标签>-<NN>`(如 `TC-LANDSCAPE-01`),台账只登记 `TC-<域>-<NN>` 单套 → 凡走 UI/契约命名的用例全部落不到台账。**这不是 85 个孤立缺漏,而是命名规范未双向对齐**。明细已写入 `tests/TRACEABILITY-MATRIX.md` §10。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 四、测试方案与执行档
|
|
|
+
|
|
|
+| 项 | 内容 |
|
|
|
+|---|---|
|
|
|
+| 目标 | 全量用例通过 + 覆盖 SRS/场景(含异常流);本轮聚焦「用例本身是否可信」与「需求变更后用例是否同步」 |
|
|
|
+| 范围 | cfc-backend 全量 · cfc-web · cfc-frontend · tests(根级 + e2e-live + e2e/api)· cfc-langgraph@251 |
|
|
|
+| 覆盖维度 | 功能(单元/集成/契约/API/E2E)、非功能(安全/性能/兼容)、流程与度量 |
|
|
|
+| **执行档** | **review(离线档,默认)**——未安装依赖、未启停服务、未联网装包、未改生产代码 |
|
|
|
+| 未授权未执行 | 依赖漏洞扫描 / 真实压测 / SAST 商业扫描(需联网,本轮无显式联网授权) |
|
|
|
+| 排除项 | 微信真机、小程序审核链路、支付真实扣款(涉资金,需人工介入) |
|
|
|
+| 本机环境探针 | JDK `1.8.0_25` ✅ · Maven `3.6.1` ✅ · Node `v22.22.2` ✅ · D 盘可用 **87G** ✅ · 9082 **未监听**(→ B-36 环境红) |
|
|
|
+| 节点探针 | 251:4096 **200** / 251:9000 `/health` **ok** · 189:4090 **200** · 204:4090 **000**(B-95 第 30 轮) |
|
|
|
+
|
|
|
+> 自动化无人值守运行,按既定默认档位(review 离线)执行;未越过任何需联网/启停服务的边界。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 五、域结论表
|
|
|
+
|
|
|
+| 审查维度 | 负责域 | 结论 | 关键证据 |
|
|
|
+|---|---|---|---|
|
|
|
+| 单元·组件 | 单元域 | ⚠️ 有条件通过 | 3057 例 99.12%;12 红类中 11 类为存量已知;**GrowthPublicEndpointMappingTest 5E 仍为未入库文件**(B-162-1) |
|
|
|
+| 集成·接口·契约 | 集成域 | ✅ 通过 | 契约类多组全绿(HB 16/16、ServiceRole 6/6、MembershipChat 6/6);API 层 32 例 25 过 7 跳、**0 红** |
|
|
|
+| 系统·验收·BDD | 系统域 | ⚠️ 部分 | E2E 28/28;无 BDD 资产;UAT 未签署 |
|
|
|
+| 测试保障(冒烟/回归/探索) | 保障域 | ✅ 通过 | 冒烟 4/4;全量回归零漂移第 17 次;探索性以安全探针形式落地 3 处用例缺陷发现 |
|
|
|
+| 性能·可靠性 | 性能域 | ⚠️ 未实测(降级为设计) | 仅冒烟(72ms / 20 并发无 5xx);真实压测未授权未执行;**限流器未部署(20 次爆发 429=0)** |
|
|
|
+| 安全 | 安全域 | ✅ 通过(DAST 面) | 匿名 6 端点全 401;IDOR 403;越权提权被拒;XSS 不回显;畸形上传业务拒绝且不落库 |
|
|
|
+| 兼容·体验·无障碍 | 兼容域 | ⚠️ 部分 | UA 一致性通过;仅 Chromium 单引擎;无障碍 0 资产 |
|
|
|
+| 流程·度量·代码 | 流程域 | ❌ 不通过 | CI 排除清单**漏拦 5 个当前红类**(`backend-blocking-junit` 必红)+ **26 个已转绿类仍被排除**;锚点覆盖率 20.7% |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 六、五要素问题清单
|
|
|
+
|
|
|
+### 问题 1(P2·数据一致性,**本轮新发现 B-170-1**)
|
|
|
+
|
|
|
+| 要素 | 内容 |
|
|
|
+|---|---|
|
|
|
+| ① 问题描述 | 后端每次启动,`DatabaseInitializer` 回填 `activities.approved_count` 的 UPDATE 语句**必然语法失败**,本轮全量 45 分钟内 28 次上下文启动 **28/28 全失败**(`SQLSyntaxErrorException: Unknown column 'a.id' in 'where clause'`)。该列唯一写入点即此语句,创建活动时置 0(`ActivityService:188`)、审批时不递增 → **持久化列恒为 0**。 |
|
|
|
+| ② 测试 bug 点 | `cfc-backend/src/main/java/com/etotem/cfc/config/DatabaseInitializer.java:2261`:`UPDATE activities a SET a.approved_count = (SELECT cnt FROM (SELECT COUNT(*) … WHERE r.activity_id = a.id …) t)` —— MySQL 不允许 `SET a.col` 带别名赋值,且派生表内不能引用被更新表的别名列。异常被 `catch (Exception e) { log.warn(...) }` 吞掉(:2263-2265),日志仍继续打印「数据表检查完成」。 |
|
|
|
+| ③ 最优修改方案 | 改为 JOIN 更新:<br>`UPDATE activities a JOIN (SELECT activity_id, COUNT(*) cnt FROM activity_registrations WHERE status='approved' GROUP BY activity_id) t ON t.activity_id = a.id SET a.approved_count = t.cnt`<br>(MySQL 允许 JOIN 形式带别名);并把该语句从 `try` 块中拆出单独 try-catch,失败时 `log.error` 而非 `warn`,避免与其他 DDL 混在一次事务性判断里。 |
|
|
|
+| ④ 修改目的 | 让存量活动的报名人数统计可被回填,避免任何按 `activities.approved_count` 做的统计/排序/看板失真;同时让迁移失败在日志层级可被监控捕获(当前 `warn` 级别 + 无告警 = 永久静默)。 |
|
|
|
+| ⑤ 修改后能否闭环 | **能**。复测方式:`cd cfc-backend && mvn -o -B -Dtest=DatabaseInitializer*Test test` + 全量启动日志 `grep -c "Unknown column 'a.id'"` 应为 **0**;再断言 `SELECT COUNT(*) FROM activities WHERE approved_count <> (SELECT COUNT(*) FROM activity_registrations r WHERE r.activity_id=activities.id AND r.status='approved')` 为 0。通过标准:两者同时成立。 |
|
|
|
+
|
|
|
+### 问题 2(P1·测试资产,**已自修 B-170-2a**)
|
|
|
+
|
|
|
+| 要素 | 内容 |
|
|
|
+|---|---|
|
|
|
+| ① 问题描述 | 安全用例 `TC-A-N05` 恒红:把 `/api/admin-auth/login`(**登录入口,本就应匿名可访问**)当「特权接口」探测,空参返回 `code=400 手机号和验证码不能为空` → 断言 401/403 失败。属**用例设计错误**,长期被记成「后台鉴权缺口」。 |
|
|
|
+| ② 测试 bug 点 | `tests/e2e/api/nonfunc-security.spec.js:75-78`(原 `apiPost('/api/admin-auth/login', {}, null)`)。 |
|
|
|
+| ③ 最优修改方案 | 探针改为真实特权面 `/api/admin/families/overview`(S-cfc-143/144 收口后匿名应 401)。已于本轮实施。 |
|
|
|
+| ④ 修改目的 | 让「后台鉴权」断言对准真正的受保护资源,消除恒红假缺陷对门禁的噪声污染。 |
|
|
|
+| ⑤ 修改后能否闭环 | **已闭环**:`IDOR`/`TC-A-N05` 一组复跑 **11/11 全绿**(原 9/11);直连探证 `POST /api/admin/families/overview` 匿名 = `HTTP 401 + code 401 请先登录`。 |
|
|
|
+
|
|
|
+### 问题 3(P1·测试资产,**已自修 B-170-2b**)
|
|
|
+
|
|
|
+| 要素 | 内容 |
|
|
|
+|---|---|
|
|
|
+| ① 问题描述 | 上传安全用例 `TC-P-N11` 恒红,且**红的原因不是安全问题**:① 路径 `/api/assessment/report/upload` 线上不存在(恒 404,真实路由由 `HealthReportController` 类级 `@RequestMapping("/api/health")` 决定);② 判据用「HTTP 非 200」判「被拒」,而本项目统一 `Result{code}` + **HTTP 200 承载业务码**。 |
|
|
|
+| ② 测试 bug 点 | `tests/e2e/api/nonfunc-security.spec.js:121-132`(路径 + `expect(status).not.toBe(200)` + 4xx 白名单)。 |
|
|
|
+| ③ 最优修改方案 | 路径改 `/api/health/report/upload`;判据改为「HTTP < 500 且 业务 `code ≠ 200`」,并断言 `data.reportId` 为空(被拒不得落库)。已于本轮实施。实测行为:非 multipart → `code=400 请求格式错误`;伪 PDF → `code=500 PDF解析失败`;两者 HTTP 均 200、均未落库。 |
|
|
|
+| ④ 修改目的 | 让安全断言与项目响应约定一致,避免「端点写错」被误读为「上传未被拦截」的安全缺口。 |
|
|
|
+| ⑤ 修改后能否闭环 | **已闭环**:该例复跑绿;并额外取证「畸形请求不触发 HTTP 5xx」。 |
|
|
|
+
|
|
|
+### 问题 4(P1·需求对齐,**已改 skip + 缺口登记 B-170-3**)
|
|
|
+
|
|
|
+| 要素 | 内容 |
|
|
|
+|---|---|
|
|
|
+| ① 问题描述 | 性能用例 `TC-P-N02/X-N01`(并发不串数据)恒红:非会员调用 `/api/ai/health-coach/send` 返回 `code=46003「该功能为会员专享」`。根因是 **S-cfc-163「聊天仅会员可见」**(`dc5522d09`)落地后契约变更,用例未同步更新 → **假红**。 |
|
|
|
+| ② 测试 bug 点 | `tests/e2e/api/nonfunc-perf-compat.spec.js:92-107`(断言 `code===200`,未处理会员门控)。 |
|
|
|
+| ③ 最优修改方案 | 先发 1 次探针,若 `code=46003` 则 `test.skip()` 并写明「会员门控生效,缺会员夹具」;否则维持原断言。已于本轮实施。 |
|
|
|
+| ④ 修改目的 | 满足「SRS/场景变更必须同步用例」的要求;同时**不以改断言方式制造假绿**——门控真实存在,只是当前夹具无法构造会员会话。 |
|
|
|
+| ⑤ 修改后能否闭环 | **部分闭环**:假红消除(perf-compat 4 过 / 3 跳 / 0 红);真正闭环需补「会员夹具」→ 登记 **G-170-1**,闭环方式:测试侧新增 `registerMember()` 夹具(开通会员或直改会员态测试账号)后取消 skip。 |
|
|
|
+
|
|
|
+### 问题 5(P0·环境,**延续 B-142-2 / 新 B-170-5**)
|
|
|
+
|
|
|
+| 要素 | 内容 |
|
|
|
+|---|---|
|
|
|
+| ① 问题描述 | langgraph@251 本轮 **46/51**(R169 48/51,恶化 2);同时 live `POST /api/v1/chat` **90s 零字节(000)**、`/api/v1/analyze` **200 / 8.66s / 1131B**(已恢复)。日志实证 **7× `RateLimitError 429 (AgnesAI_error)` + 3× `401 api key ****ab12 invalid`**。对照生产 `https://ai.etotem.com.cn/api/v1/chat` = **200** → 仅 251 节点 LLM 上游被掐。 |
|
|
|
+| ② 测试 bug 点 | 5 红:`test_auto_tag_content_relevance` / `test_auto_tag_short_content` / `test_auto_tag_empty_content`(断言 `500==200`)+ `test_classify_analysis` / `test_classify_recommend`(`intent_classifier.py:62` 捕获异常后**静默兜底 chat**,把 429 伪装成「分类错误」)。 |
|
|
|
+| ③ 最优修改方案 | 运维侧:为 251 配置独立 API Key / 提升配额,或加本地限流+排队;研发侧:`intent_classifier.py:62` 改为**向上抛出可识别错误**(如 `LLMUnavailable`)而非默认 `chat`,让 429 在断言层可见。 |
|
|
|
+| ④ 修改目的 | 让 langgraph 51 例回到 51/51,并消除「429 伪装成分类错误」的诊断噪声。 |
|
|
|
+| ⑤ 修改后能否闭环 | **能**。复测:251 `pytest -q --ignore=tests/qna --ignore=tests/test_chat.py` 连续 **2 轮 51/51** 才销号(当前观察 0/2;R167 起共 4 轮未达)。另需修 B-126:kick 串用单引号包 `bash -c '…; echo EXIT=$? >> LOG'`,否则 `EXIT=` 仍不落盘。 |
|
|
|
+
|
|
|
+### 问题 6(P0/P1·流程,**延续 B-152-1/2 第 6 轮未修**)
|
|
|
+
|
|
|
+| 要素 | 内容 |
|
|
|
+|---|---|
|
|
|
+| ① 问题描述 | `.gitlab-ci.yml:61` 的 `BACKEND_OBSERVED_CLASSES`(33 类)与实测红类(**12 类**)双向失真:**漏拦 5 个当前红类**(`GrowthPublicEndpointMappingTest`、`UserServiceWechatLoginContractTest`、`UserServiceWechatLoginTest`、`TaskReviewScP11ContractTest`、`TeamProfitCronContractTest`)→ `backend-blocking-junit` **必然失败**;同时 **26 个已转绿类仍被排除** → 硬门禁覆盖被人为缩小。 |
|
|
|
+| ② 测试 bug 点 | `.gitlab-ci.yml:61` 静态清单(无自动同步机制)。 |
|
|
|
+| ③ 最优修改方案 | ① 立即把 5 个漏拦类加入清单(短期止血);② CI 增一条「红类集合 ↔ 清单集合双向差集必须为空」的断言脚本(长期治本),差值非空直接 fail 并打印两侧差集。 |
|
|
|
+| ④ 修改目的 | 让 CI 硬门禁恢复「能红能绿」的真实约束力;当前状态是「必红」→ 团队会直接忽略该 job,门禁形同虚设。 |
|
|
|
+| ⑤ 修改后能否闭环 | **能**。复测:推送后观察 `backend-blocking-junit` 由 fail → pass(或仅剩预期 RED 时 fail 且日志只含预期类);差集脚本输出两侧均为空。 |
|
|
|
+
|
|
|
+### 问题 7(P1·数据/Schema,**延续 B-156-1 第 6 轮未修**)
|
|
|
+
|
|
|
+| 要素 | 内容 |
|
|
|
+|---|---|
|
|
|
+| ① 问题描述 | `schema.sql:5345-5357` `CREATE TABLE nutrition_age_dosage` 列清单无 `product_id`,却在 `:5356` 声明 `INDEX idx_product (product_id)` → 建表**恒失败**(本轮 28/28 上下文全部 `Key column 'product_id' doesn't exist in table`),`DatabaseInitializer` catch 后仍打印「数据表检查完成」→ **该表从未创建成功**。 |
|
|
|
+| ② 测试 bug 点 | `cfc-backend/src/main/resources/schema.sql:5356`;实体 `NutritionAgeDosage.java` 另有 `updateTime` 而 DDL 无 `update_time`(建表修好后会立刻 `Unknown column`)。 |
|
|
|
+| ③ 最优修改方案 | 二选一:① 补列 `product_id BIGINT NOT NULL` + 同步实体;② 若该索引本不必要,删 `INDEX idx_product (product_id)`。同时补 `update_time DATETIME`。并给 `DatabaseInitializer` 加「建表失败 → 汇总报告 + 非零退出/告警」。 |
|
|
|
+| ④ 修改目的 | 消除「表不存在但系统认为已就绪」的隐患;营养按年龄剂量功能一旦上线即会 `Table doesn't exist`。 |
|
|
|
+| ⑤ 修改后能否闭环 | **能**。复测:全量启动日志 `grep -c "Key column 'product_id' doesn't exist"` = **0**,且 `SHOW CREATE TABLE nutrition_age_dosage` 有返回;再跑一次全量后端 0 新增红。 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 七、覆盖缺口清单
|
|
|
+
|
|
|
+| 编号 | 缺口类型 | 现状 | 风险 | 建议测试设计 | 优先级 | 闭环方式 |
|
|
|
+|---|---|---|---|---|---|---|
|
|
|
+| G-170-1 | 夹具缺口 | 无「会员账号」夹具 | AI 教练(S-cfc-163 后仅会员可用)并发/隔离/正常链路无法验证,3 例只能 skip | 新增 `registerMember()`:直改会员态或调用开通接口 | **P0** | 夹具落地后取消 skip,perf-compat 恢复到 7/7 |
|
|
|
+| G-170-2 | 锚点覆盖率 | 76/367 = 20.7%(G9-b 47.2%) | 79% 台账用例无执行证据 | 给台账加「锚点别名列」,把 85 孤儿按语义归并 | **P1** | 覆盖率 ≥80% 且孤儿 = 0 |
|
|
|
+| G-170-3 | 后端覆盖率 | 无 JaCoCo | 无法量化后端行/分支覆盖,G1 只能靠通过率 | pom 加 `jacoco-maven-plugin`,`mvn test` 出报告 | **P1** | 报告产出且行覆盖 ≥60% |
|
|
|
+| G-170-4 | 变异测试 | 无 PIT/Stryker | 用例「通过但断言弱」不可见 | 先对 `*ContractTest` 覆盖的 3 个核心 Service 做 PIT 试点 | P2 | 变异得分 ≥50% |
|
|
|
+| G-170-5 | 真实压测 | 仅 20 并发冒烟,且 `429=0`(限流器未部署) | 活动名额/秒杀场景无容量证据 | k6/JMeter 场景脚本(下单、报名、AI 对话),需联网授权 | P2 | execute 档授权后执行 |
|
|
|
+| G-170-6 | 安全扫描 | 仅 DAST 面 11 例 | 依赖漏洞、SAST 未覆盖 | OWASP Dependency-Check + Semgrep(需联网) | P1 | 授权后执行并归档报告 |
|
|
|
+| G-170-7 | 无障碍 | 0 资产 | 小程序/管理端无 WCAG 证据 | axe-core 注入 e2e-live,先管 5 个核心页 | P3 | 关键页 0 critical |
|
|
|
+| G-170-8 | 环境型红 | 根级 16 红(9082 未监听) | 掩盖真实回归 | 测试前自动拉起 `cfc-backend`(探活 → 缺失则启) | P2 | 根级由 7/23 → 23/23 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 八、门禁结论
|
|
|
+
|
|
|
+| 门禁 | 阈值 | 实测 | 判定 |
|
|
|
+|---|---|---|---|
|
|
|
+| G1 全量通过率 | ≥98% | **98.17%**(剔 skip 98.80%) | ✅ |
|
|
|
+| G2 红例总数 | =0(预期 RED 除外) | **47**(后端 23 / 根级 16 / lg 5 / fe 3) | ❌ |
|
|
|
+| G3 前端 Jest | 红 ⊆ 预期 RED | 609 过 / 3 红(全 S-cfc-132/133 预期 RED)/ 12 跳 | ✅ |
|
|
|
+| G4 管理端 Jest | 100% | **116/116** | ✅ |
|
|
|
+| G5 编译与完整性 | 0 编译错 / 0 dump | 0 / 0(surefire 红仅测试层) | ✅ |
|
|
|
+| G6 浏览器 E2E | 100% 执行项 | **28/28**(+ dx 2 skip,不假绿) | ✅ |
|
|
|
+| G7 langgraph | 100% | **46/51 = 90.2%** | ❌ |
|
|
|
+| G8 鉴权契约 | 匿名受保护端点全 401 | **6/6 = 401** | ✅ |
|
|
|
+| G9 锚点覆盖率 | ≥80% | **20.7%** | ❌ |
|
|
|
+| G10 多节点派发 | 每节点单任务成功 | 189 5/5 + 251 51 例 + 本机 —— **三节点全通** | ✅ |
|
|
|
+| G11 CI 硬门禁 | 可用(能红能绿) | 漏拦 5 红类 + 26 陈旧类 → **必红** | ❌ |
|
|
|
+| G12 SRS 对齐 | 变更即更新用例 | 窗口零变更 → 0 新增用例 | ✅ |
|
|
|
+| G13 存量红漂移 | 0 漂移 | 17 例逐类逐例一致(**第 17 次**) | ⚠️ 零漂移但未清零 |
|
|
|
+| G14 场景→用例映射 | ≥80% | **58.2%**(89/153) | ❌ |
|
|
|
+
|
|
|
+### 综合结论:**不通过(承袭,结构改善 / 指标略降)**
|
|
|
+
|
|
|
+- **正向**:① 首次把 API 非功能层 32 例纳入闭环,**0 红**;② 修正 3 处用例自身缺陷(2 假红转绿 + 1 需求对齐 skip),使「红」更可信;③ 后端 3057 例与 R169 **逐类逐例零漂移(第 17 次)** → 证明 R169 采信期无漏检;④ 新增 B-170-1 产品缺陷 + 锚点双向核对口径(85 孤儿首次可见)。
|
|
|
+- **负向**:langgraph 3→5 红(上游 429 恶化)、通过率 98.38%→98.17%(分母 +22、lg 多 2 红)、G11 仍必红。
|
|
|
+- **复评条件**:G-170-1 会员夹具落地 + 251 连续 2 轮 51/51 + CI 双向差集脚本落地 + 后端存量 17 红清零 → 可升「有条件通过」。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 九、附录
|
|
|
+
|
|
|
+### 9.1 复现命令
|
|
|
+
|
|
|
+```bash
|
|
|
+# 后端全量(工程根在 cfc-backend,不是仓库根)
|
|
|
+cd cfc-backend && JAVA_HOME=/d/jdk1.8.0_25 /d/maven/apache-maven-3.6.1/bin/mvn -o -B clean test
|
|
|
+
|
|
|
+# 三端 Jest
|
|
|
+cd cfc-web && npx jest
|
|
|
+cd cfc-frontend && npx jest
|
|
|
+cd tests && npx jest
|
|
|
+
|
|
|
+# 浏览器(必须在 tests/ 内跑,防 @playwright/test 双版本冲突)
|
|
|
+cd tests && npx playwright test --config=playwright.config.live.js --project=frontend-mobile
|
|
|
+cd tests && npx playwright test --config=playwright.config.live.js --project=shop-api
|
|
|
+cd tests && npx playwright test --config=playwright.config.health.js
|
|
|
+cd tests && npx playwright test --config=playwright.config.live.js --project=dx-bridge
|
|
|
+
|
|
|
+# 线上 API 非功能层
|
|
|
+cd tests && npx playwright test e2e/api/api-smoke.spec.js e2e/api/nonfunc-security.spec.js -c playwright.config.api.js --project=desktop
|
|
|
+cd tests && npx playwright test e2e/api/nonfunc-perf-compat.spec.js -c playwright.config.api.js --project=desktop
|
|
|
+
|
|
|
+# 251 langgraph(kick 分离 + 单次读日志)
|
|
|
+MSYS_NO_PATHCONV=1 node docs/tdd/tools/dispatch_251_pytest.cjs kick
|
|
|
+MSYS_NO_PATHCONV=1 node docs/tdd/tools/dispatch_251_pytest.cjs read
|
|
|
+
|
|
|
+# 189 admin E2E
|
|
|
+MSYS_NO_PATHCONV=1 node docs/tdd/tools/dispatch_189_admin.cjs
|
|
|
+```
|
|
|
+
|
|
|
+### 9.2 本轮慢类(耗时占全量 45m 的 15%)
|
|
|
+
|
|
|
+| 类 | 耗时 |
|
|
|
+|---|---|
|
|
|
+| `GrowthPublicEndpointMappingTest` | 176s(5E,超时型;且仍是未入库文件) |
|
|
|
+| `UserServiceFamilyNameLinkTest` | 154s |
|
|
|
+| `GuideApplicationServiceTest` | 150s |
|
|
|
+| `GuidePackageServiceTest` | 139s |
|
|
|
+
|
|
|
+### 9.3 日志噪声与稳定性观测
|
|
|
+
|
|
|
+- `cfc-scheduler` 线程行数 **8255 / 46357(17.8%)**;`SQLSyntaxErrorException` **980 次**,其中 `Key column 'product_id' doesn't exist` 与 `Unknown column 'a.id'` 各 **28 次**(= 上下文启动次数),`Duplicate key name` 系列各 28 次(幂等 index 重复,属正常但应由 `ensureIndex` 吞掉而非抛到日志)。
|
|
|
+- `dump` 文件 **0** 个 → 无 JVM crash。
|