Files
jerryandClaude Fable 5 0875bb036c P0/M1: 四部分重构——frontend→ui、backend→sdk 改名 + 引用修复 + 骨架
- git mv 保留历史:ui/(Vue3+Vite)、sdk/(BFF 中间层)
- 路径语义修正:db_path/figures_cache 改相对 sdk/(BFF cwd),
  历史库 sdk/backend/data 迁移至 sdk/data/(会话/图片缓存无损)
- 引用修复 ~15 处:config.py、deploy/*.sh、vitest/playwright 配置、
  单测导入路径、docs、README、gitignore、.env.example
- 骨架:agent/{qa,methodology,legacy-rag,vendor}、knowledge/manifest.yaml、
  tooling/{compile,kb,crypto,assemble,audit,tools,scripts} + README
- 门禁验证:sdk pytest 125 通过、ui vitest 158 通过、
  生产 BFF 脚本重启四上游全绿 + 静态托管 + 会话库无损

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 12:56:47 +08:00

13 KiB
Raw Permalink Blame History

TEST_REPORT_R1.md —— 第一轮全量测试报告

轮次 R1 | 日期 2026-08-25 | 测试 agent T | 模板依据 TEST_PLAN §8


1. 轮次信息

项 值
被测版本 M1 集成后(PM 已修复集成问题清单,见协调通知)
运行环境 远端 plantai-bff 机(100.109.52.26);BFF 8090(真实上游 7920/8000/7900/Neo4j 18788 全通);Vite 5180 → 8090;mock 8099 运行中
L1/L2 运行 sdk 全量 pytest(conda plantai-bff,pytest 9.1.1;本轮补充安装 pytest/pytest-asyncio/pytest-cov)
L3/L4 运行 ui vitest 2.1.8(137 用例)
L5 运行 Playwright 1.49.1 + chromium-1148,三档视口 42→48 条测试
L2s 运行 bash tests/smoke_upstreams.sh(本轮修复 Neo4j 认证缺陷后重跑)
轮次纪律 只跑测试与写报告,未修改任何产品代码(ui/src/**、sdk/app/** 零改动;测试脚本自身缺陷修复除外)

2. 首页统计

2.1 分层结果

层 总数 Pass Fail Skip 说明
L1+L2 后端(pytest 全量) 119 119 0 0 python -m pytest . -q;含 A 组自测 + T 复跑确认
L3+L4 前端(vitest) 137 137 0 0 B1 25 + B2 58 + B3 54
L5 端到端(Playwright 三档) 48 19 17 12 详见 §2.3;17 个失败收敛为 7 个产品缺陷 + 3 个测试缺陷(测试缺陷已修复,见 §2.4)
L2s 上游 smoke 7 7 0 0 首跑 Neo4j 401(测试脚本缺陷),修复认证后 7/7 PASS
合计(可执行用例) 311 282 17 12 失败均归因于缺陷清单,无环境性 flake

2.2 覆盖率(辅门禁)

项 实际 门禁 结论
后端行覆盖(pytest --cov=app) 87%(2769 行中 351 未覆盖) ≥85% 达标
前端行覆盖(vitest --coverage) 81.54%(All files) ≥80% 达标
FR 需求追溯(主门禁) 81/81,未覆盖清单为空(TEST_CASES.md 矩阵,经脚本机械验证双向零失配) 100% 达标

后端覆盖率低点(供开发参考,非缺陷):upstream.py 32%、sse_relay.py 65%。

2.3 L5 明细(48 条 = 16 用例 × 3 视口,按 TEST_CASES 的 TC-E2E 映射)

TC 映射 用例 mobile tablet desktop 结论
TC-E2E-SMOKE-01/02 冒烟 ✓ ✓ ✓ PASS
TC-E2E-01 主流程 ✘ BUG-R1-06 ✘ BUG-R1-06 ✘ BUG-R1-06 步骤 1–6 全过(新建/提问/相位推进/终态/来源/会话状态);6b markdown 断言失败阻断步骤 7–8
TC-E2E-02 检索模式 ✘ BUG-R1-07 ✘ BUG-R1-07 ✘ BUG-R1-07 真实 search 92s > 前端 30s 超时 → 必现「检索超时」
TC-E2E-03 DOWN QA 不可用降级 — — ✘ BUG-R1-04 作曲器未禁用
TC-E2E-03 ERROR 上游错误+重试 — — ✘ BUG-R1-05 展示「连接中断」而非上游 message
TC-E2E-04 核心 新建/重命名/搜索/分组 ✓ ✓ ✓ PASS(新建×2、双击重命名、大小写不敏感过滤、无匹配文案、清空恢复、零网络请求、今天分组)
TC-E2E-04 活动态 活动高亮探针 ✘ BUG-R1-02 ✘ BUG-R1-02 ✘ BUG-R1-02 点击会话无 .active
TC-E2E-04 删除 删除入口探针 ✘ BUG-R1-03 ✘ BUG-R1-03 ✘ BUG-R1-03 右键无确认弹层(死代码)
TC-E2E-05 中断 — — ✓ PASS(流式中切会话 → 原会话 error + 「已中断」标注 + 状态点 error)
TC-E2E-06 主题切换持久化 ✓ ✓ ✓ PASS
TC-E2E-07 图谱搜索/邻域/详情 ✘ BUG-R1-01 ✘ BUG-R1-01 ✘ BUG-R1-01 搜索请求无 q 参数,返回随机数据
TC-E2E-08 抽取任务/日志/上传 ✓ ✓ ✓ PASS(列表 49 任务、详情展开、日志、mock 上传成功、非 PDF 拦截)
TC-E2E-09 桌面 网格/底栏/折叠 — — ✓ PASS(260/800/380、48/824/28、body overflow hidden、4 agent 点、折叠持久化)
TC-E2E-09 平板 抽屉/scrim — ✓ — PASS
TC-E2E-09 手机 移动端专项 ✓ — — PASS(汉堡/工作台按钮/覆盖层/底栏隐藏/16px/44px/安全区/吸底)

L5 合计:19 Pass / 17 Fail / 12 Skip(skip 均为档位门控设计,非缺陷)。

2.4 测试自身缺陷(已修复,不计入产品缺陷)

编号 现象 修复
— L2s smoke 脚本 Neo4j 探测无 Basic auth → 401 补充 -u neo4j:<neo4j-password-in-.env>(凭据来自 DISCOVERY.md §2.1),重跑 7/7 PASS
— E2E 断言用 .empty-state, .app-shell 双元素选择器 → strict mode violation 改为只断言 .app-shell
— 抽屉关闭点 scrim 中心(被抽屉遮挡)→ 点击挂起直至超时 改为 Esc 优先 + 右侧安全坐标点击
— grid-template-rows 断言未考虑 Chromium 对 1fr 的像素解析 断言解析值 48/824/28

3. 缺陷清单(BUG-R1-xx)

编号 级别 对应 TC 归属 agent 现象 预期 证据
BUG-R1-01 Major TC-E2E-07(×3) B1(api/http.js;消费方 B3 api/kg.js) KG 实体搜索 UI 显示与查询无关的随机实体(!Xunethnic_group · 1 等);抓包确认请求 URL 为 /api/kg/entities 无 q 参数。http.js 的 request() 不序列化 query 参数,searchEntities(q) 的 {q, limit} 被丢弃。BFF 直测 ?q=OsSPL14 返回 17 条正确结果,排除后端问题 搜索请求应携带 ?q=<输入词>&limit=20;结果应含 OsSPL14 /tmp/r1_pw_rest.log 失败块 1/6/11;BFF 直测对比(q 有值 17 条 vs 空 q 20 条随机);截图 test-results/bench-E2E-07-*/test-failed-1.png
BUG-R1-02 Major TC-E2E-04 活动态(×3) B2(stores/chat.js) 点击会话后条目无 .active 类;chat.selectSession() 只设置 this.sessionId,未同步 sessions.activeId → 活动高亮(FR-SESSION-009)、顶栏标题/徽章(FR-SHELL-002 依赖 activeSession)、删除后切换全部失效 点击会话后该条目带 .active(渐变左条 + 8% 底) /tmp/r1_pw_rest.log 失败块 4/9/14;代码证据:chat.js selectSession 无 activeId 赋值
BUG-R1-03 Major TC-E2E-04 删除(×3) B2(SessionPanel.vue/SessionItem.vue) 删除确认弹层(.confirm-box)在 DOM 存在但无任何触发入口:SessionPanel.askDelete 定义后零调用;SessionItem 无右键/更多按钮;askDelete 也未绑定到模板 会话条目应有删除入口(右键或更多菜单),点击弹出二次确认(FR-SESSION-007) /tmp/r1_pw_rest.log 失败块 5/10/15;代码证据:grep -rn askDelete components/session/ 仅 1 处定义
BUG-R1-04 Major TC-E2E-03 DOWN B2(ChatPanel.vue) mock /api/health 返回 QA ok:false 时,作曲器 textarea 仍 enabled;Composer 的 disabled/healthNote props 已定义但 ChatPanel 从未传入(health store 未接线) QA 不可用时作曲器禁用 + 显示「知识问答服务当前不可用」(FR-HEALTH-002) /tmp/r1_pw_target.log 失败块 1;代码证据:ChatPanel 无 health 引用
BUG-R1-05 Major TC-E2E-03 ERROR B2(api/qa.js + stores/chat.js) 上游 502 错误信封(UPSTREAM_ERROR message=「上游问答服务返回错误」)被前端展示为**「连接中断,请检查网络后重试」**。原因:chatStream 的 post 抛 ApiError(信封已正确解析),但 _runStream 的 catch 路径把一切非 AbortError 标记为 disconnected,未优先检查 err instanceof ApiError 的 code/message 展示上游 message「上游问答服务返回错误」+ 重试按钮(PRD §2.2:后端 error.message 直接展示) /tmp/r1_pw_target.log 失败块 2(Received:「连接中断,请检查网络后重试」);截图 test-results/mock-scenarios-E2E-03-错误与重-3eae7-M-ERROR*/test-failed-1.png
BUG-R1-06 Major TC-E2E-01(×3) B2(chat/markdown.js 或装配处) 答案含 - 列表/**加粗** 语法时渲染为纯文本(无 <li>/<strong>/<table> 标签)。renderMarkdown 已实现且被单测覆盖(vitest 通过),但生产路径零调用:qaToBlocks 直接以原始 answer 生成 text 块,AssistantMessage 仅做 sanitizeHtml markdown-it 渲染 + DOMPurify 消毒(FR-CHAT-004);402 fallback 的列表应渲染为 <ul><li> /tmp/r1_pw_rest.log 失败块 2/7/12(HTML 头部为纯文本证据);代码证据:grep -rn renderMarkdown src/ 仅 markdown.js 内定义
BUG-R1-07 Blocker TC-E2E-02(×3) B1(api/http.js) 检索模式在真实上游必现超时:http.js 默认读超时 30s(仅 raw 流式豁免),而真实 /api/qa/search 单次 ≈92s(DISCOVERY.md §6.8)→ 34s 时前端自断,UI 显示「检索超时,请重试」。检索模式(FR-CHAT-006 第三种模式)在真实环境完全不可用 search 请求超时 ≥180s(BFF 契约读超时 180s);92s 检索正常完成并出来源 /tmp/r1_pw_rest.log 失败块 3/8/13(34.1s 失败);截图 test-results/main-flow-E2E-02-*-mobile/test-failed-1.png(可见「检索超时,请重试」);代码证据:http.js TIMEOUT_MS=30000
BUG-R1-08 Minor (TC-HEALTH 相关观察) A3(routers/health.py) /api/health 的 neo4j.detail 报告「name_norm 索引缺失或异常:['srt2_canonical_entity_id', 'srt2_canonical_entity_nam…'」,但实测实体检索走 name_norm 索引 0.09s 正常、/api/kg/status 正常列出索引——健康探测对索引状态的判定与实际矛盾,属误报 detail 仅在真实异常时出现;正常时勿提示「缺失或异常」 远端 curl http://127.0.0.1:8090/api/health 响应原文

缺陷分布:B1 ×2(BUG-R1-01/07,其中 07 为 Blocker)、B2 ×5(BUG-R1-02/03/04/05/06)、A3 ×1(Minor)。本轮无 B3 缺陷(B3 负责的 E2E-07 失败根因在 B1 http.js)。

4. 上轮缺陷修复确认表

本轮为第一轮,无上轮缺陷。

5. 遗留问题与风险

  1. QA LLM 402 余额不足(已知,非缺陷):chat 答案为 fallback 证据列表而非自然语言。涉及答案内容的断言(TC-CHAT-027 等)按 TEST_CASES §3.3 回退结构断言;依赖充值的用例未在本轮验证最终答案质量。BUG-R1-06(markdown)恰由 fallback 列表暴露——充值后自然语言答案同样会命中,修复不受 402 影响。
  2. L2 独立接口测试未建立:tests/sdk/ 仍为空(A 组单测已覆盖 routers 层 119 条)。TEST_CASES 中标注 L2 的用例(检查点节奏、级联删除、INVALID_CITATION 重试等)在后续轮次需补齐 respx mock 测试,当前靠 A 组单测 + L5 间接覆盖。
  3. E2E-01 步骤 7–8 被 BUG-R1-06 阻断未执行:刷新后历史恢复(TC-CHAT-013 的 L5 路径)待修复后补验;L1 侧 test_sessions_api.py 已覆盖持久化,风险低。
  4. Laptop 档(1024–1279)无独立 Playwright project:TEST_CASES 的 TC-RESP-002 档位用例(左栏自动折叠 64px/右栏 340px)本轮未跑,建议下轮加 laptop 项目或在该视口手动验证。
  5. 本轮 T 自身操作事故(已恢复,记录备查):为测前端覆盖率在远端执行 npm install --save-dev,短暂改写了 B1 的 ui/package.json 并打断 Playwright 依赖(一次运行中途崩溃)。已还原 package.json 至 B1 原版并用 --no-save 重装。后续 T 在远端装包一律 --no-save,写入 package.json 的需求走 PM。
  6. 测试数据污染:R1 新建会话已按前缀清理(R1主流程/R1检索/R1会话/R1中断 等),远端 SQLite 中 水稻SPL基因家族… 等自动标题会话为测试产生,已尽量清理,PM 若在意可执行一次数据盘点。
  7. 48 条 L5 中 12 条 skip 为档位门控设计(如 mock 场景仅桌面代表、E2E-05 仅桌面),已在 TEST_CASES 执行说明中记录;如需三档全跑需 PM 确认(真实上游流成本高:每档主流程 ≈1 分钟、检索 ≈92s)。

6. 证据归档

  • 远端日志:/tmp/r1_pytest.log(119 passed)、/tmp/r1_cov.log(87%)、/tmp/r1_vitest_cov.log(137 passed,81.54%)、/tmp/r1_pw_rest.log(L5 主批次)、/tmp/r1_pw_target.log(mock 场景桌面批次)、/tmp/r1_pw_full2.log(首轮全量,含 6/6 smoke)
  • 失败截图/trace:远端 ui/test-results/(按用例目录归档;7 个缺陷各有一式三份视口证据,其中 BUG-R1-04/05 为桌面证据)
  • smoke 输出:本文件 §2.1 引用;修复后 7/7 PASS