# 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:`(凭据来自 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` 或装配处) | 答案含 `- 列表`/`**加粗**` 语法时渲染为**纯文本**(无 `
  • //` 标签)。`renderMarkdown` 已实现且被单测覆盖(vitest 通过),但**生产路径零调用**:`qaToBlocks` 直接以原始 answer 生成 text 块,`AssistantMessage` 仅做 `sanitizeHtml` | markdown-it 渲染 + DOMPurify 消毒(FR-CHAT-004);402 fallback 的列表应渲染为 `
    • ` | `/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