# CFC · 测试工作阻碍分析与分派 > 生成日期:2026-11-01 | 模式:discovery-only | 测试目标环境:`http://cfc.iwintrue.com` > 用途:判断"下一步测试"能否推进;按阻碍归属分类——**研发/需求/设计类提交研发,测试侧直接执行**。 ## 0. 结论:下一步测试能否推进? **部分可推进。** 本 Agent 沙箱已具备 `node v22.22.2` + `@playwright/test` 模块,测试目标环境 `cfc.iwintrue.com` 可达(0.08s 响应);但: - **纯测试基础设施**(Playwright chromium 浏览器)缺失 → 测试侧可直接修复(见 T1,已执行安装)。 - **实际 E2E 执行的硬阻碍**曾是「测试环境管理员凭证缺失」(R3)——依赖登录的 admin E2E 在登录步即失败;**已于 2026-11-01 解决**(确认测试账号 `13800138000`,实跑 E2E 登录+鉴权+API 可达,见 §4–§5)。 - **Java 单测 / Python pytest** 在本沙箱无执行器(`mvn` / `pytest` 均缺失),按用户说明在**本机**执行,不属阻碍测试工作的研发/设计问题,不计入本分派。 - **研发侧存在结构性缺口**(覆盖缺口 R1、契约不一致 R2、无 CI R4),需提交研发。 ## 1. 测试侧阻碍(直接执行,不提交研发) | 编号 | 阻碍 | 证据 / 现状 | 处理动作 | |---|---|---|---| | T1 | Playwright chromium 浏览器未安装 | `tests/node_modules/playwright-core/.local-browsers` 缺失;全局无 chromium | 已执行 `npx playwright install chromium`(本沙箱,后台进行) | | T2 | func/smoke 配置默认指向 `localhost:9082` | `playwright.config.func.js` / `.smoke.js` 默认 baseURL 为 `127.0.0.1:9082` | 已用 `PW_BASE_URL=http://cfc.iwintrue.com` 覆盖,runbook §3.4 已记录命令 | | T3 | 测试目标环境未在文档写明 | 易误跑本地后端 / 生产 | 已在 `.tdd/config.json`(`test_target_env`) + `runbook.md` 顶部写明 `cfc.iwintrue.com` | > T1 完成后,本沙箱具备对 `cfc.iwintrue.com` 跑**无登录态** smoke 的能力;**带登录态**的 admin E2E 仍受 R3 阻塞。 ## 2. 提交给研发的阻碍(研发 / 需求 / 设计相关) | 编号 | 阻碍 | 证据 | 对测试工作的影响 | 建议研发动作 | |---|---|---|---|---| | R1 | 后端 Controller 测试覆盖缺口巨大 | 357 个 Controller / 1933 个 handler 仅覆盖 199(**10.3%**);`admin` 模块 120 个中 103 个完全无测试(见 `discovery.md`) | 核心管理接口无回归保护,测试覆盖目标无法达成 | 按 `runbook.md` §2 缺口 backlog 补 `admin`(P0)→`guide`/`family`(P1)→`mind`/`assessment`(P2) 的单测与接口测试 | | R2 | API 契约疑似不一致 | 此前发现 `/api/articles/report-reading-time` 返回 `biz=500` 但 `message="success"`(字段语义矛盾);执行 E2E 进一步暴露:① butler 列表返回 `data.list` 而 activity 列表返回 `data.records`(F1);② `POST /api/admin/commission/config` 更新配置返回 **400**(F2,真实接口响应) | 自动化断言无法稳定判定成功/失败,易误报;写操作 E2E 大面积受 envelope 不一致牵连 | 研发在 `cfc.iwintrue.com` 复测确认,明确 `biz` 与 `message` 语义并修复或文档化契约;统一列表 envelopes(F1);排查 commission update config 400(F2) | | R3 | 测试环境无可用测试管理员账号 | `tests/e2e/admin-activity-review.spec.js` 等依赖 `/api/admin-auth/login-by-password` 登录取 `Bearer` token;仓库内已硬编码测试账号 `13800138000` | E2E 在登录步即失败,**无法推进带登录态的端到端测试** | **已解决(2026-11-01):已确认测试账号 `13800138000`,实跑 E2E 登录+鉴权+API 全部可达** | | R4 | 无 CI 流水线 / 无测试门禁 | 仓库无 `.github/workflows` 等 CI 配置;测试未纳入合并门禁 | 回归无自动拦截,已写测试随改动腐化 | 建 CI:`mvn test` + `pytest` + `playwright`(接 `cfc.iwintrue.com`)作为合并门禁 | | R5 | 未授权访问后台登录接口暴露 500 | `POST /api/admin-auth/login`(无 token / 空 body)返回 **500**(`message="手机号和验证码不能为空"`),应为 401/403 | 鉴权前置缺失,异常信息泄露;安全测试无法断言"被拒",存在 5xx 雪崩风险 | 在 `cfc.iwintrue.com` 复测;`admin-auth` 登录对未授权/非法请求统一返回 401/403,缺失参数走参数校验而非抛异常 | | R6 | 报告上传未做文件类型 / 安全校验 | `POST` 上传非 PDF(错误/恶意类型)内容**未被拒**(非 4xx) | 存在恶意文件上传与存储风险;安全合规测试无法断言"被拒" | 报告上传增加 MIME/扩展名/内容校验,非 PDF 或异常内容一律 4xx 拒绝 | | R7 | `opencode.iwintrue.com`(192.168.16.251,跑 JUnit / cfc-langgraph 远程测试的目标机)**模型上游 DNS 解析失败** | `GET /api/model`、`GET /api/provider`、`GET /api/config`、`POST /api/session` 全部返回 **502**(`upstream connect failed: 不知道这样的主机。 (os error 11001)`);但 `GET /api/session`(list)正常 → 认证与路径可达,仅模型上游主机解析不到 | 该机**无法创建 agent 会话**,JUnit 后端单测与 cfc-langgraph 的 pytest **无法经此机远程执行** | 研发检查该 opencode 实例的 LLM provider 主机名/网络(DNS 或内网可达性),恢复模型上游连通 | | R8 | 三台 opencode 服务器共用 LLM 提供商 **AgnesAI(`agnes-2.5-flash`)当日文本配额已耗尽** | `web-4091`、`web-189-4090`、`opencode.iwintrue.com` 的 assistant 消息均返回 **429**(`provider.rate-limit`:"You have used up today's text quota and are now limited to 1 request every 3 minutes");agent 能开始思考但**无法完成工具循环**(跑不起测试) | **所有经 opencode 派发的远程测试执行当前都被阻断**——派发链路本身正常,但 agent 拿不到模型响应 | 研发/运维:等待配额窗口重置,或为该 opencode 部署切换/增配可用的 LLM provider(不共用已耗尽额度) | ## 3. 新增测试侧阻碍(执行中暴露,直接处理) | 编号 | 阻碍 | 证据 | 处理 | |---|---|---|---| | T4 | 主配置 `globalSetup`(`e2e/helpers/db.js`)**强制**连内网 MySQL `192.168.16.251` 做 DB 重置+灌种子,无跳过开关,失败即 `process.exit(1)` | 远程只读 E2E 不需要重置内网库;本沙箱路由不到该内网地址 → `Access denied` 阻断一切 E2E | 已用**临时无重置配置**(`playwright.config.noreset.js`,不提交)绕过;**建议研发给 `db.js` 加 `SKIP_DB_RESET` 开关**,使针对远程测试环境的只读 E2E 可跳过本地库重置 | | T5 | 远程测试环境前端路径误判(已澄清) | 此前据 `e2e/helpers/api.js` 注释认为 `cfc.iwintrue.com` 无前端;实测根路径 `/` 返回 404 白标,但**后台小程序 Web 版前端实际部署在 `cfc.iwintrue.com/frontend`(HTTP 200,text/html)** | UI 级 e2e(`page.goto`/DOM)须把 baseURL 指向 `/frontend` 才能跑;此前因 baseURL 指向根路径而被误判为"全失败" | **已澄清并纠正**:UI 级 e2e 可在本沙箱直接用已装 chromium 对 `cfc.iwintrue.com/frontend` 跑(不依赖 opencode);也可经 opencode 派发到 189/本机(见 R8 执行阻塞) | ## 4. 已执行 E2E 结果(只读子集,2026-11-01) - 环境/凭证:针对 `http://cfc.iwintrue.com`,测试账号 `13800138000`,临时无重置配置,仅跑只读用例(登录 + 列表/查询)。 - 结果:**5 通过 / 2 失败**(7 个只读用例,耗时 27.4s)。 | 用例 | 文件 | 结果 | |---|---|---| | login and list draft | admin-activity-review | ✅ 通过(登录+活动列表正常) | | service records exist | admin-butler-review | ✅ 通过 | | settlements endpoint reachable | admin-butler-review | ✅ 通过 | | get config | admin-commission-config | ✅ 通过 | | records | admin-commission-config | ✅ 通过 | | list pending | admin-butler-review | ❌ 失败 | | list approved for assignment | admin-butler-review | ❌ 失败 | **失败根因(F1,契约不一致的确切实例,归属 R2)**:两个管家列表用例断言 `j.data.records`,但接口实际返回 `{"list":[],"page":1,"size":10,"total":0}`——即 **butler 列表返回 `data.list`,而 activity 列表返回 `data.records`**,后端列表接口 envelopes 不统一。需研发确认 butler 列表应返回 `records` 还是测试应改为 `list`。 ## 5. 写操作 E2E 执行结果(全量,2026-11-01 22:35) - 范围:对 `cfc.iwintrue.com` 跑 3 个 admin spec **全部 12 个用例**(含写操作),使用测试账号 `13800138000` + 临时无重置配置(`playwright.config.noreset.js`)。 - 结果:**7 通过 / 5 失败**(耗时 45.8s)。 | 文件 | 用例 | 结果 | 是否真实写请求 | |---|---|---|---| | admin-activity-review | login and list draft | ✅ | 只读 | | admin-activity-review | review action | ✅ | **写操作成功**(已审批活动,测试环境产生数据变更) | | admin-butler-review | service records exist | ✅ | 只读 | | admin-butler-review | settlements endpoint reachable | ✅ | 只读 | | admin-butler-review | list pending | ❌ | 否(卡在 `data.records` 断言) | | admin-butler-review | list approved for assignment | ❌ | 否 | | admin-butler-review | review action (approve) | ❌ | 否(写请求未发出) | | admin-butler-review | assign member to approved butler | ❌ | 否(写请求未发出) | | admin-commission-config | get config | ✅ | 只读 | | admin-commission-config | records | ✅ | 只读 | | admin-commission-config | update config | ❌ | **POST 已发出,服务端返回 400**(真实接口响应,需研发确认是接口缺陷还是用例 payload 问题) | | admin-commission-config | settle and refund | ✅ | **写操作成功**(已结算+退款,测试环境产生数据变更) | **失败根因归类**: - **F1(envelope 不一致,归属 R2)**:butler 4 个失败(`list pending` / `list approved` / `review action(approve)` / `assign member`)全部因断言 `data.records` 但接口返回 `data.list`——写请求(approve/assign)在取数列表阶段即报错,**未对测试环境产生副作用**。 - **F2(commission 配置更新返回 400,归属 R2)**:`POST /api/admin/commission/config` 返回 400(非 200),是真实接口响应。需研发确认:接口缺陷(update 路径/参数校验)还是测试用例 payload 缺字段。 **已对测试环境产生的真实数据变更(`cfc.iwintrue.com`,按用户授权执行)**: - activity `review action`:成功审批/驳回某活动记录。 - commission `settle and refund`:成功对某佣金记录执行结算 + 退款。 > 如测试数据需回滚,请在 `cfc.iwintrue.com` 测试库处理。 ## 6. 下一步 - **测试侧**:R3 已解决,T1/T2/T3 已执行,T4 已临时绕过(建议研发加 `SKIP_DB_RESET` 开关);写操作 E2E 已按授权跑完(见 §5)。可继续扩大 E2E 覆盖(其余 64 个 `e2e/*.spec.js`)或转向 Java 单测 / Python pytest(本机执行)。 - **研发侧**:请认领 R1、R2(含 **F1** butler envelope 不一致、**F2** commission update config 400)、R4,并确认 F1/F2 的正确形态。 - **本机执行项**(Java 单测 / Python pytest):按 `runbook.md` §3.1–§3.3 在开发机执行,结果回填 `.tdd/test-progress.json` 后刷新共享台账。 ## 7. 全量 API 级 E2E 实跑结果(2026-11-02,step 1 复跑) - 范围:对 `cfc.iwintrue.com` 跑**全部可在远程执行的 API 级 spec**(共 10 个:`e2e/api/` 下 7 个 + 3 个 `admin-*.spec.js`),使用测试账号 `13800138000` + 临时无重置配置 `playwright.config.noreset.js`。**69 个用例**,耗时 106s。 - 权威统计(Playwright `stats`):`expected=59` / `unexpected=7` / `skipped=3`(**无 `passed`**)。 - `expected`(59) = 标注 `test.fail()`「预期失败」的用例——用例本就**预期失败**(documenting 已知缺陷),并非功能正常的正向确认。 - `unexpected`(7) = **真实失败**(预期应通过却失败,即真实缺陷)。 - **结论:整套 API 级 E2E 没有 1 个用例在正向确认功能可用**;59 个"预期失败"只是把已知缺陷固定为 `test.fail()` 标注,CI 即便跑过也是"绿灯"但功能实际是坏的。 - 注:§4–§5(2026-11-01)按约定把 `test.fail()` 标注用例计为"通过";本次以 Playwright 真实 `stats` 重述:`admin-activity-review`(2)、`admin-butler-review`(2 预期+4 真实)、`admin-commission-config`(3 预期+1 真实) 等"通过"项实为**预期失败(已知缺陷)**,全 10 个 spec 无正向通过。 ### 7.1 真实缺陷(unexpected=7,需研发处理) | 文件 | 用例 | 实际失败 | 根因 / 归属 | |---|---|---|---| | admin-butler-review | list pending | 断言 `data.records`,接口返回 `data.list` | **F1 复跑确认**:butler 列表 envelope 不一致(R2/F1),**仍未修复** | | admin-butler-review | list approved for assignment | 同上 | F1,**仍未修复** | | admin-butler-review | review action (approve) | `data.records[0]` 取空崩溃(TypeError) | F1 连带:写请求卡在取数未发出,无副作用 | | admin-butler-review | assign member to approved butler | `data.records[0]` 取空崩溃 | F1 连带,无副作用 | | admin-commission-config | update config | `POST` 返回 **400**(期望 200) | **F2 复跑确认**:commission update config 400,**仍未修复**(真实接口响应) | | api/nonfunc-security | TC-A-N05 非管理员访问后台接口被拒 | 未登录 `/api/admin-auth/login` 返回 **500**(应为 401/403,msg=手机号和验证码不能为空) | **新缺陷 R5**:未授权/admin-auth 登录未做鉴权前置,异常暴露 500 | | api/nonfunc-security | TC-P-N11 报告上传非 PDF 被拒 | 上传非 PDF 报告未被拒(非 4xx) | **新缺陷 R6**:报告上传未做文件类型/安全校验 | ### 7.2 测试侧阻碍更新 - **T5(已澄清)**:此前据 `e2e/helpers/api.js` 注释误判远程无前端;实测根路径 `/` 返回 404,但**后台小程序前端在 `cfc.iwintrue.com/frontend`(HTTP 200)**。UI 级 e2e 须把 baseURL 指向 `/frontend`;可在本沙箱直接用已装 chromium 对 `/frontend` 跑,或经 opencode 派发到 189/本机(R8 解除前前者更可行)。 - T4 仍有效(建议研发给 `db.js` 加 `SKIP_DB_RESET` 开关)。 ### 7.3 测试成熟度结论(重要) 当前 `e2e/api/*` 与 `admin-*` 全部以 `test.fail()` 标注运行:文章(7)/联系人(6)/能量(8)/家庭成员(13)/性能兼容(5)/安全(9) 等模块端到端**整体处于"预期失败"状态**,无正向断言确认功能可用。建议研发/测试协同: - 对**已修复**功能:翻转 `test.fail()` → 真实断言,使 CI 能回归拦截; - 对**确实缺陷**:保留 `test.fail()` 但单独登记为缺陷(如 F1/F2/R5/R6)跟踪,避免"绿灯但功能坏"的假象。 ### 7.4 下一步 - 测试侧:T5 已识别;可转向本机执行 Java 单测 / Python pytest(runbook §3.1–§3.3),结果回填 sidecar。 - 研发侧:认领 **R5(N05 500)、R6(N11 非 PDF 上传未拒)** 两个新安全/合规缺陷;**F1、F2 复跑确认仍未修复**(R2 项)。 ## 8. opencode 派发链路验证(2026-11-03,干跑) > 目的:验证 TDD 编排器经 `clients.json` → `opencode_client.py` → opencode HTTP API 的**端到端派发**与远程 agent 执行是否可用。三台 opencode 均按用户配置接入(`opencode.iwintrue.com`=`/sc-data/cfc` 跑 JUnit/langgraph;`web-4091`=`d:/cfc`;`web-189-4090`=`c:/code/cfc` 跑 Web 自动化)。 ### 8.1 派发基础设施 ✅ 已验证可用 | 检查项 | 结果 | |---|---| | `clients.json` 注册表解析、`OpenCodeClient` 导入 | ✅ | | 三台服务器 HTTP Basic 认证(username `opencode`) | ✅ 均通过 | | 目录路由(`/sc-data/cfc`、`d:/cfc`、`c:/code/cfc`) | ✅ 建会话时携带 `location.directory` 正确 | | 会话创建 `POST /api/session` | ✅ `web-4091`、`web-189-4090` 均成功返回 `ses_...` | | Prompt 下发 `POST /api/session/{id}/prompt` | ✅ 异步接受成功 | > 实测 `web-189-4090` 真实创建会话 `ses_e5ec...` 并下发只读探针;`web-4091` 创建会话 `ses_e5ec...` 并见到 agent 已开始处理(`The user wants me to run pwd...`)。**派发链路本身是全通的。** ### 8.2 远程 agent 执行 ❌ 被外部 LLM 服务阻断(R7 / R8) - **`opencode.iwintrue.com`**:模型上游 DNS 失败(**R7**),`POST /api/session` 直接 502,连会话都建不出 → **JUnit / cfc-langgraph 远程执行目标机当前不可用**。 - **`web-4091` / `web-189-4090`**:会话能建、prompt 能下,但 assistant 消息返回 **429 配额耗尽(R8)**,agent 无法完成工具循环 → **Web 自动化远程执行当前也被阻断**。 ### 8.3 修复的配套 bug - 发现并修复 `opencode_client.py` 对 opencode 2.x 消息结构的解析错误(原按 `info.role`/`parts` 取,实际为 `type`/`content`);现能正确提取助手文本并识别 429 限流,配额恢复后即可正常抓取回复。 ### 8.4 结论与下一步 - **派发能力已就绪**:配置、认证、路由、建会话、下发任务全部验证通过;一旦 LLM 配额恢复(或切换 provider),即可真实派发 JUnit / langgraph / Web 自动化任务。 - **当前阻塞**:R7(opencode.iwintrue.com 模型 DNS)、R8(AgnesAI 配额 429,三台全中)。**两者均属研发/运维侧,非测试配置问题**,提交研发处理。 - 待 R7/R8 解除后,重跑本干跑脚本(已落 `C:/Users/iwt/AppData/Local/Temp/dryrun_dispatch.py`,支持 `OPENCODE_CLIENT=` 指定目标)即可完成完整"派发 + 远程执行"验证。