196 KiB
TEST_CASES.md —— 需求测试用例与追溯矩阵
版本 1.0 | 作者 T(测试 agent)| 用例唯一来源:
PRD.md(81 FR);请求/响应依据:API.md;分层与轮次纪律:TEST_PLAN.md;上游事实:DISCOVERY.md本波(M0)交付:用例清单 + 双向追溯矩阵 + 执行说明 + E2E 骨架(2 条冒烟)。全量执行从 M2 集成后开始,按 TEST_PLAN §5 轮次纪律。 覆盖判据:每个 FR 至少 1 条 TC,且每条 TC 至少映射 1 个 FR(双向完整 = 主门禁 100%)。
1. 用例清单
1.1 编号与通用约定
- 编号:
TC-<模块>-<序号>;E2E 主线场景:TC-E2E-<主线号>-<视口>(视口 M=Mobile 390×844 / T=Tablet 768×1024 / D=Desktop 1440×900)。 - 测试层:L1 后端单元(pytest -m unit,A 组自测)|L2 后端接口(pytest -m api,respx mock 上游,T 主写)|L2s 上游 smoke(
bash tests/smoke_upstreams.sh)|L3 前端单元(vitest)|L4 前端组件(vitest + @vue/test-utils)|L5 端到端(Playwright,三档视口)|L6 验收(PM 人工)。 - 优先级:P0 = 主流程/数据正确性/安全;P1 = 重要功能与降级;P2 = 视觉细节/辅助路径。
- 可断言性要求:预期列均为可观察结果(元素存在/计数/请求体字段/HTTP 状态/存储值),无「检查是否正确」类断言。
- 「依赖充值」标注:上游 QA 当前 LLM 402 降级(DISCOVERY.md §6.1),凡断言涉及自然语言答案内容的用例均标注「依赖充值」——充值前只能验证结构(answer 字段存在、非空或为 fallback 证据列表、text 块已渲染),充值后验证完整断言。检索/证据/图谱/来源类断言不受 402 影响。
- 时序说明:流水线用例中的「pipeline 块状态依次 running→done」属 UI 状态推断,若无专门组件埋点,用例从渲染的相位卡/pipeline 卡状态文本断言;帧时序由 mock
sse_frames.json保证(与 TEST_CASES 无关的 fixture 细节以 PM 的 mock 为准)。
1.2 SHELL 应用外壳(FR-SHELL-001~007)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-SHELL-001 | FR-SHELL-001 | 桌面三栏网格精确尺寸 | Desktop 1440×900;AppShell 已挂载 | 1. 打开应用;2. 计算 .app-shell 的 grid-template-columns 与 rows 实际值(getComputedStyle);3. 计算 .session-panel/.chat-panel/.bench-panel 宽度 |
columns = 260px minmax(0,1fr) 380px;rows = 48px minmax(0,1fr) 28px;三栏实际宽度 260/800/380(1440 下);body computed overflow:hidden |
L5-D | P0 |
| TC-SHELL-002 | FR-SHELL-001 | 缩放下无横向滚动条 | Desktop 初始 1440×900 | 1. 将视口改为 1280×900、再 1440×900;2. 检查 document.documentElement.scrollWidth 与 clientWidth |
两档下 scrollWidth ≤ clientWidth;body 不出现横向滚动条 |
L5-D | P1 |
| TC-SHELL-003 | FR-SHELL-002 | 顶栏结构:Logo/标题/徽章/主题按钮 | 已有一个活动会话;浅色主题 | 1. 打开应用;2. 断言 .top-bar 高 48px;3. 检查左 Logo 圆点与「海古纪 PlantAI」文字(gradient text);4. 检查中部会话标题与状态徽章;5. 检查右侧主题切换按钮 |
.top-bar offsetHeight=48;logo 文字存在且带 background-clip:text 渐变;中部标题=当前会话 title;主题按钮可点 |
L5-D | P1 |
| TC-SHELL-004 | FR-SHELL-002 | 顶栏无会话时显示「就绪」 | 数据库无任何会话 | 打开应用 | 顶栏中部徽章文本=「就绪」(labels.js 对应键) | L4 | P2 |
| TC-SHELL-005 | FR-SHELL-002 | 顶栏长标题省略 | 存在 title 为 60+ 字符的会话 | 1. 打开该会话;2. 检查顶栏标题元素 computed style | 标题 text-overflow=ellipsis;不换行(white-space:nowrap);单行渲染 | L5-D | P2 |
| TC-SHELL-006 | FR-SHELL-003 | 状态栏静态结构 | AppShell 已挂载;/api/health、/api/qa/info 正常 |
1. 检查 .status-bar 高 28px;2. 检查左 4 个 .agent-dot-item;3. 检查右侧版本/会话数/健康标记 |
高=28px;agent 点数量=4;右侧文本含 PlantAI RAG v0.1 与 QA 版本号(来自 /api/qa/info 的 version,如 1.1.73-assertion-anchored) |
L5-D | P1 |
| TC-SHELL-007 | FR-SHELL-003 | 问答进行中状态栏四点联动 | 会话空闲;mock normal(SSE 回放) | 1. 发起提问;2. 在 SSE 进行中读取四个 agent 点的状态类 | 相位推进到 X 时第 X 个点激活(如 planning 时第 1 点 pulse);progress 全部结束后四点定格(成功态) | L5-D | P1 |
| TC-SHELL-008 | FR-SHELL-004 | 左栏折叠为 64px 图标轨 | Desktop 1440×900;左栏展开 | 1. 点击左栏折叠按钮;2. 检查 .session-panel 宽度与图标按钮(3 个 34×34);3. 刷新页面;4. 再次检查 |
折叠后宽度=64px;图标按钮=3 个;过渡 300ms;刷新后仍折叠 | L5-D | P1 |
| TC-SHELL-009 | FR-SHELL-004 | 左栏折叠状态持久化 | 同上 | 1. 折叠;2. 检查 localStorage['pa-side-collapsed'] |
localStorage 值为折叠标记;展开后标记被清除/反转 | L5-D | P2 |
| TC-SHELL-010 | FR-SHELL-005 | 右栏折叠保留手柄条 | Desktop 1440×900;右栏展开 | 1. 点击右栏折叠;2. 检查手柄条尺寸与可见性;3. 点击手柄展开;4. 检查 localStorage['pa-bench-collapsed'] |
折叠后 .bench-panel 隐藏但手柄条 28px 可见可点;点击后恢复展开;刷新后保持折叠态 |
L5-D | P1 |
| TC-SHELL-011 | FR-SHELL-006 | Aurora 背景不遮挡交互 | 任意视口;AppShell 已挂载 | 1. 检查 aurora 层 computed style;2. 点击顶栏主题按钮、会话列表项、作曲器输入框(逐个执行且均生效) | aurora 层 position:fixed、z-index:0、pointer-events:none;上述交互全部可操作 |
L5-D | P1 |
| TC-SHELL-012 | FR-SHELL-006 | 浅色主题 aurora 衰减 | 已切浅色 | 检查 aurora 层或根元素的 --pa-aurora-opacity |
computed 值=.08(UI_SPEC §1.2 令牌值) |
L4 | P2 |
| TC-SHELL-013 | FR-SHELL-007 | 首屏初始化顺序与并行请求 | 深色主题已存 localStorage;无会话 | 1. 打开应用;2. 网络面板记录启动期请求 | documentElement.dataset.theme 在应用挂载前已写入(断言:无白色闪屏——深色下首帧背景即深色;实现断言:main.js 在 createApp 前写 dataset);启动期存在 GET /api/sessions、/api/health、/api/qa/info 三个请求且并行(无串行依赖) |
L5-D + L3 | P0 |
| TC-SHELL-014 | FR-SHELL-007 | 首屏接口失败不阻塞渲染 | mock 对 /api/health 返回 500(或 BFF 停止) |
打开应用 | 页面仍渲染 AppShell 与欢迎空态;健康标记显示降级/离线态;无未捕获异常 | L5-D(mock error 场景) | P1 |
| TC-SHELL-015 | FR-SHELL-007 | 无会话显示欢迎空态 | 数据库无会话 | 打开应用 | 对话区显示欢迎空态(渐变菱形 + 标题 + 3 张建议卡) | L5-D | P1 |
1.3 THEME 主题与无障碍(FR-THEME-001~006)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-THEME-001 | FR-THEME-001 | 深色默认主题 | 首次打开(无 pa-theme 存储) | 1. 打开应用;2. 检查 documentElement.dataset.theme 与 --pa-canvas computed 值 |
theme='dark';canvas=#0A0A10(rgb(10,10,16)) | L5-D | P0 |
| TC-THEME-002 | FR-THEME-001 | 浅色主题逐组件走查 | 已切浅色 | 逐个检查顶栏、会话项、气泡、作曲器、bench 面板的计算样式 | 无失色:各元素背景/文字均来自浅色令牌(canvas=#F6F8FC,surface-1=#FFFFFF);无深色令牌残留(如 #0A0A10 不再出现于背景) | L5-D(或 L6 人工走查) | P0 |
| TC-THEME-003 | FR-THEME-002 | 主题切换即时生效 | 默认深色 | 1. 点击顶栏主题按钮;2. 立即检查 documentElement.dataset.theme 与 localStorage;3. 刷新后复查 |
dataset.theme 即时='light';localStorage['pa-theme']='light';刷新后仍为 light;再切回同理 |
L5-D | P0 |
| TC-THEME-004 | FR-THEME-002 | 主题图标旋转动画 | 同上 | 切换主题时检查图标 transform | 图标日/月互换且 rotate 180°(transition 400ms) | L5-D | P2 |
| TC-THEME-005 | FR-THEME-003 | 浅色 glow 衰减 | 已切浅色 | 检查根元素 --pa-glow-opacity computed 值 |
值=.35(深色下=1) | L4 | P2 |
| TC-THEME-006 | FR-THEME-004 | 动效降级(reduced motion) | 系统「减少动态效果」开启;Playwright 以 reducedMotion:'reduce' 启动 context |
1. 打开应用;2. 检查 aurora/状态点/按钮的 animation 计算样式;3. 发起一次问答 | @media (prefers-reduced-motion: reduce) 生效:所有元素 animation-duration=0 或 animation 为 none;running 状态以静态符号(实心点 + 文字徽章)可辨认,无 pulse/shimmer/spin 运动 |
L5-D(reducedMotion context) | P1 |
| TC-THEME-007 | FR-THEME-005 | 焦点环样式 | 任意视口 | Tab 键聚焦顶栏主题按钮与作曲器 textarea | :focus-visible 输出 2px rgba(94,106,210,.5) 焦点环(outline-offset 1px) |
L5-D | P1 |
| TC-THEME-008 | FR-THEME-005 | 纯键盘完成主流程 | 空数据库;mock normal | 只用 Tab/Enter/Esc 完成:新建会话 → 聚焦输入 → 输入问题 → ⌘/Ctrl+Enter 发送 → Tab 切换工作台 tab → Esc 关闭面板 | 每一步可达且生效;Tab 顺序符合视觉顺序(顶栏 → 会话列表 → 对话 → 作曲器 → 工作台) | L5-D(键盘驱动) | P0 |
| TC-THEME-009 | FR-THEME-006 | 对比度达标(深色) | 深色主题 | 抽检 .app-shell 内 3 处文本(正文 ink、muted、subtle)的计算颜色与 canvas 背景,按 WCAG 公式计算对比度 |
ink/canvas ≥15:1;ink-muted/canvas ≥4.5:1;ink-subtle 仅用于非关键信息 | L5-D + L3(工具函数断言,可脚本化) | P1 |
| TC-THEME-010 | FR-THEME-006 | 对比度达标(浅色) | 浅色主题 | 同 TC-THEME-009 步骤,浅色令牌 | ink(#16182A)/canvas(#F6F8FC) ≈ 计算值 ≥ 深色同等标准;ink-muted/canvas ≥4.5:1 | L5-D | P1 |
1.4 SESSION 会话管理(FR-SESSION-001~009)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-SESSION-001 | FR-SESSION-001 | 列表按 updated_at 倒序 | 数据库 ≥3 个会话,updated_at 互异(fixtures 保证) | 1. GET /api/sessions;2. 前端渲染列表;3. 依次读取条目标题 |
条目顺序 = updated_at 从新到旧 | L2(fixture 会话数据)+ L4 | P0 |
| TC-SESSION-002 | FR-SESSION-001 | 分组「今天/昨天/更早」 | ≥3 个会话,时间分别落在今天/昨天/2 天前 | 渲染列表 | 三个组标签(11px/500/字距0.6px)按序出现,组内条目归属正确;组内按时间倒序 | L4(clock mock) | P1 |
| TC-SESSION-003 | FR-SESSION-001 | 空列表引导文案 | 数据库无会话 | 渲染列表 | 显示引导文案(「暂无会话」类 labels 文案);不渲染列表条目 | L4 | P2 |
| TC-SESSION-004 | FR-SESSION-002 | 状态点四态区分 | 4 个会话分别 idle/running/done/error | 渲染列表 | 形状可区分:idle=空心、running=空心+脉冲动画、done=实心 success 色、error=实心 error 色;running 有 animation,其余无 | L4 | P1 |
| TC-SESSION-005 | FR-SESSION-003 | 新建会话 | 任意初始状态 | 1. 点击「新建会话」按钮;2. 观察网络请求与界面 | 发出 POST /api/sessions;列表新增一条「新会话」;切换为活动会话;对话区显示欢迎空态;不产生空消息(GET 详情 messages 为空数组) |
L5-D + L2 | P0 |
| TC-SESSION-006 | FR-SESSION-003 | 新建连点不重复 | 同上 | 快速连点新建按钮 2 次 | 产生 2 个独立会话(列表+2,两条 POST);均切到最后创建的一个 | L5-D | P1 |
| TC-SESSION-007 | FR-SESSION-004 | 选择会话加载历史 | 会话含 text/table/sources/graph 块消息 | 点击该会话条目 | 发出 GET /api/sessions/{id};加载中显示骨架屏;完成后消息按块类型渲染:markdown 文本、表格(md-table 样式)、来源、图谱块均出现 |
L5-D(mock 会话详情含全块) | P0 |
| TC-SESSION-008 | FR-SESSION-004 | 切换会话中断进行中流 | 会话 A 流式进行中;会话 B 存在 | 点击会话 B | 会话 A 的 SSE 连接 abort(Network 面板连接关闭);会话 A 状态置 error;切回会话 A 后其消息标注「已中断」 | L5-D(mock slow/正常流) | P0 |
| TC-SESSION-009 | FR-SESSION-005 | 搜索过滤(中文/英文/大小写) | ≥3 个会话,标题含中英文混排 | 1. 输入中文关键词;2. 输入英文小写;3. 输入英文大写;4. 输入无匹配词;5. 清空 | 匹配为 title 大小写不敏感子串;无匹配显示「无匹配会话」;清空恢复全量;过滤期间无网络请求 | L5-D + L4 | P1 |
| TC-SESSION-010 | FR-SESSION-006 | 重命名提交 | 活动会话 | 1. 双击标题进入编辑;2. 输入新名;3. 回车 | PATCH /api/sessions/{id} 请求体 {title:新名};列表与顶栏标题同步更新 |
L5-D + L2 | P1 |
| TC-SESSION-011 | FR-SESSION-006 | 重命名取消与空标题 | 同上 | 1. 编辑中按 Esc;2. 再次编辑并清空标题后回车 | Esc 放弃改动;空标题提交按钮禁用或提交被拒,不发出 PATCH 空 title | L5-D | P2 |
| TC-SESSION-012 | FR-SESSION-007 | 删除需二次确认 | 2 个会话 | 1. 右键/菜单点删除;2. 出现确认弹层时点取消 | 未删除(列表不变、无 DELETE 请求) | L5-D | P1 |
| TC-SESSION-013 | FR-SESSION-007 | 删除当前会话切换 | 2 个会话;选中其中一个 | 删除并确认 | DELETE /api/sessions/{id} 204;当前会话切换到剩余最新一个;刷新列表后已删会话不再出现 |
L5-D + L2 | P0 |
| TC-SESSION-014 | FR-SESSION-007 | 删除最后一个会话显示空态 | 仅 1 个会话 | 删除并确认 | 列表空;对话区显示欢迎空态 | L5-D | P1 |
| TC-SESSION-015 | FR-SESSION-007 | 级联删除消息 | 会话含 2 条消息;BFF 真实 | 删除会话后 GET /api/sessions/{id} |
返回 404(NOT_FOUND 信封);SQLite 中该会话消息行一并删除(L2 断言数据库) | L2 | P0 |
| TC-SESSION-016 | FR-SESSION-008 | 首问自动标题 | 新建会话 | 1. 提问(问题 40+ 字符);2. 检查 PATCH 请求与列表标题 | PATCH 请求体 title = 问题前 30 字符 + 省略号;列表标题同步变化 | L5-D + L2 | P0 |
| TC-SESSION-017 | FR-SESSION-008 | 手动改名后不覆盖 | 会话 meta.title_manual=true(改过名) | 1. 再次提问;2. 检查是否发出 title PATCH | 不发出改 title 的 PATCH;标题保持手动值 | L2(会话固定数据)+ L4 | P1 |
| TC-SESSION-018 | FR-SESSION-009 | 活动态高亮 | ≥2 个会话 | 1. 选中会话 A;2. 检查其 computed style;3. 悬停另一项 B 对比 | A 有 2px 渐变左竖条 + g-to 8% 底色 + 内描边;与悬停态(B)可区分 | L5-D | P2 |
1.5 CHAT 对话与问答(FR-CHAT-001~015)
1.5.1 基础渲染
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-CHAT-001 | FR-CHAT-001 | 欢迎空态元素与建议卡 | 无消息 | 打开应用 | 显示 46px 渐变菱形(✧)+ 渐变标题「海古纪 PlantAI 知识工作台」+ 副标题 + 3 张建议卡 | L5-D | P1 |
| TC-CHAT-002 | FR-CHAT-001 | 建议卡点击即提问 | 无消息;mock normal | 点击第 1 张建议卡 | 卡片文本进入作曲器并直接发送;出现用户气泡(内容=卡片文本)与助手骨架;发出 POST /api/qa/chat/stream |
L5-D | P0 |
| TC-CHAT-003 | FR-CHAT-002 | 用户气泡样式与长文本换行 | 任意 | 发送 300 字无空格长文本 | 气泡右对齐,宽度 ≤ 父容器 70%;文本换行且不溢出(scrollWidth ≤ 气泡宽度) | L5-D | P2 |
| TC-CHAT-004 | FR-CHAT-003 | 助手消息头部与悬停竖线 | 已有助手消息 | 1. 检查头部(24px 渐变头像 ✦ + 「PlantAI 智能体」+ 时间);2. 悬停消息左缘 | 头部三要素齐全;左缘 2px 竖线 hover 时出现渐变 | L5-D | P2 |
| TC-CHAT-005 | FR-CHAT-003 | 多块混排顺序 | 消息 blocks 为 [pipeline,text,table,sources,graph](mock 会话详情) | 渲染该消息 | 各块按 blocks 数组顺序渲染;无块丢失 | L5-D | P1 |
| TC-CHAT-006 | FR-CHAT-004 | Markdown 表格样式 | 消息含表格块(mock 含 md-table 内容的 text 块) | 渲染 | 表格带 md-table 类:thead 2px 渐变下边框;数据格 mono 字体(表头为「说明」的列保持比例字体) | L5-D | P1 |
| TC-CHAT-007 | FR-CHAT-004 | 脚本注入被消毒 | 向问答返回的 answer 注入 <script>window.__pwned=1</script> 与 <img src=x onerror=...>(mock fixture 或 BFF 层构造) |
渲染该答案 | window.__pwned 为 undefined;DOM 中不存在 script 标签;onerror 未执行;内容经 DOMPurify 后 v-html |
L5-D(注入 fixture)+ L3(sanitize 单测) | P0 |
| TC-CHAT-008 | FR-CHAT-014 | 流式自动滚动到底 | mock normal;消息区可滚动 | 发起提问 | 流式更新期间滚动条持续贴近底部(scrollTop+clientHeight ≥ scrollHeight−10) | L5-D | P1 |
| TC-CHAT-009 | FR-CHAT-014 | 上滚暂停自动滚动 | 流式进行中 | 向上滚动 ≥100px | 不再自动贴底;出现「回到最新」按钮 | L5-D | P1 |
| TC-CHAT-010 | FR-CHAT-014 | 「回到最新」恢复滚动 | 上滚暂停状态 | 点击「回到最新」按钮 | 滚动回底部;恢复自动滚动;按钮消失 | L5-D | P1 |
| TC-CHAT-011 | FR-CHAT-015 | 内联引用 chip 跳转高亮 | 答案含引用标记(citation 编号)与对应来源 | 点击引用 chip | bench 切换到「文献来源」tab 并滚动定位到对应条目;该条目高亮 2s 后消失;chip 编号与列表条目序号一致 | L5-D | P1 |
1.5.2 作曲器
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-CHAT-012 | FR-CHAT-005 | 输入框高度自适应 | 桌面 | 1. 输入 1 行文本测基线(min-height 46px);2. 输入 10 行文本 | 基线 ≥46px;随内容增高,最大 160px 后内部滚动(scrollHeight > clientHeight) | L5-D | P2 |
| TC-CHAT-013 | FR-CHAT-006 | 三模式切换 | 桌面;mock normal | 依次点击 问答/方案/检索 pill | 激活 pill 渐变底+白字+青光;非激活态可区分;切换即生效 | L5-D | P0 |
| TC-CHAT-014 | FR-CHAT-006 | 问答模式请求体 | mock 正常;问答模式 | 提问并抓取 POST /api/qa/chat/stream 请求体 |
body.use_llm=true;question 为输入文本;无 native_chain 字段(或为 modes.js 定义默认) | L5-D + L3(modes.js 参数集断言) | P0 |
| TC-CHAT-015 | FR-CHAT-006 | 方案模式请求体 | 方案模式 | 同上 | body.use_llm=true;native_chain_enabled=true;native_chain_max_hops=3;native_chain_top_k=5;端点仍为 /api/qa/chat/stream |
L5-D + L3 | P0 |
| TC-CHAT-016 | FR-CHAT-006 | 检索模式请求与响应 | 检索模式 | 1. 提问;2. 观察端点为 /api/qa/search;3. 等待完成;4. 检查消息块 |
body.use_llm=false;响应 answer 为空;消息只含 sources(+pipeline)块,无 text 答案块 | L5-D + L2 | P0 |
| TC-CHAT-017 | FR-CHAT-007 | 快捷键发送 | 桌面 | 输入文字后按 ⌘/Ctrl+Enter | 发送;出现用户气泡 | L5-D | P0 |
| TC-CHAT-018 | FR-CHAT-007 | Enter 换行 | 桌面 | 输入文字后按 Enter(非组合键) | 不发送;textarea 内换行(行数+1) | L5-D | P1 |
| TC-CHAT-019 | FR-CHAT-007 | 中英文输入法快捷键 | IME 输入法激活(模拟 composition 事件) | composition 期间按 Enter | 不触发发送(组合输入确认才触发) | L3(composition 事件模拟) | P1 |
| TC-CHAT-020 | FR-CHAT-007 | 空输入与忙碌禁用 | 流式进行中 | 1. 空输入点发送;2. 流式中点发送 | 按钮 disabled(opacity .45);无新请求;底部提示文案显示快捷键说明 | L5-D | P1 |
| TC-CHAT-021 | FR-CHAT-011 | 停止流式 | mock slow(长流) | 1. 提问;2. 流式中点击「停止」 | 发送按钮已变为「停止」;点击后 SSE 连接关闭(Network 断言);消息置 error 并标注「已停止」;已收到的块保留 | L5-D | P0 |
| TC-CHAT-022 | FR-CHAT-011 | 停止后无悬挂请求 | BFF 真实 + 上游 QA | 流式中停止;随后检查 BFF 日志 | 前端 abort 后 BFF 取消上游请求(BFF 侧无悬挂 upstream 连接;日志有取消记录) | L2(respx 断言 abort)+ L5 | P1 |
1.5.3 流式主流程(FR-CHAT-008)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-CHAT-023 | FR-CHAT-008 | 主流程-用户消息立即落库 | mock normal;新会话 | 发送问题 | 用户气泡立即出现(不等后端);发出 POST /api/sessions/{id}/messages,body={role:user,text};落库成功 |
L5-D + L2 | P0 |
| TC-CHAT-024 | FR-CHAT-008 | 主流程-会话置 running 与骨架 | 同上 | 发送后观察 | 会话状态置 running(左栏状态点脉冲动画);底栏 4 agent 点复位;出现助手骨架消息(status=streaming)含 pipeline 块,五相位全 waiting | L5-D | P0 |
| TC-CHAT-025 | FR-CHAT-008 | 主流程-progress 相位推进与阶段卡 | mock normal(sse_frames 12 帧) | 提问后观察 | 每帧 progress:pipeline 对应相位 running、此前相位 done;工作台「检索过程」新增阶段卡,数量=progress 帧数(11 个 stage 帧);阶段卡 label 为中文(如「已识别实体」) | L5-D | P0 |
| TC-CHAT-026 | FR-CHAT-008 | 主流程-complete 生成三块 | mock normal;提问完成 | 等待 complete | 消息含 text 块(揭示动画结束为最终文本)、sources 块、graph 块;pipeline 五相位全部 done;消息状态 done;会话状态 done | L5-D | P0 |
| TC-CHAT-027 | FR-CHAT-008 | 主流程-答案内容(依赖充值) | mock normal(mock 答案为固定文本);真实上游需充值 | 断言答案文本 | mock 下:答案文本与 mock fixture 一致(可断言内容);真实上游:answer 为自然语言答案(依赖充值,当前 402 下为 fallback 证据列表) | L5-D / L6 | P1 |
| TC-CHAT-028 | FR-CHAT-008 | 主流程-检查点持久化节奏 | BFF 真实;流 ≥3s | 提问并抓取 PATCH 请求 | 流式中每约 3s 发出 PATCH /api/sessions/{id}/messages/{mid}(块检查点);终态再发一次终态 PATCH(done/error) |
L2 + L5 | P0 |
| TC-CHAT-029 | FR-CHAT-008 | 主流程-长任务持续反馈(240s) | mock slow(长流,或上游真实 ~92s) | 提问并计时观察 | 240s 内任一时刻页面均有视觉反馈(相位卡 shimmer/已耗时计数);无静止超过 5s 的状态(5s 间隔采样断言有动画元素或文本变化) | L5-D(slow 场景) | P0 |
| TC-CHAT-030 | FR-CHAT-008 | 网络中断重试按钮 | 流式中断网(playwright context.setOffline(true)) | 1. 流式中断网;2. 观察消息状态;3. 恢复网络;4. 观察是否自动重连;5. 点「重试」 | 消息置 error,文案「连接中断」;出现「重试」按钮;不自动重连(恢复网络后无新请求,需手动点击);点重试后重新发起同问题请求 | L5-D(offline 模拟) | P0 |
| TC-CHAT-031 | FR-CHAT-008 | 刷新恢复中断会话 | 流式进行中刷新页面 | 刷新后检查该会话 | 显示最后检查点内容;标注「已中断」;会话状态 error;不自动重试 | L5-D | P0 |
| TC-CHAT-032 | FR-CHAT-008 | 同一会话并发提问防护 | 流式进行中 | 观察发送按钮 | 按钮 disabled;无法发送第二个问题 | L5-D | P1 |
| TC-CHAT-033 | FR-CHAT-008 | 同会话提问可引用上文(默认开;设置中关闭后恢复独立) | 同一会话已完成一次提问 | 第二次提问并抓取请求体 | 第二次请求只含当前 question,无历史消息拼接(max_rounds:1 语义);UI 有「每次提问独立检索」提示文案 | L2 + L5 | P1 |
1.5.4 流水线卡与揭示动画(FR-CHAT-009 / FR-CHAT-010)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-CHAT-034 | FR-CHAT-009 | 五相位视觉与颜色 | 流式中与完成后分别观察 pipeline 卡 | 检查五个 p-step 的颜色令牌与状态字形 | 相位色:规划#C0A8DD、检索#9FBBE0、证据#9FC9A2、生成#DFA88F、完成#C08532;状态字形 ✓done/●running/◌waiting;running 相位带 11px 旋转 spinner;卡头「⚙ 检索流水线」+ 整体状态徽章(语义色) | L5-D | P0 |
| TC-CHAT-035 | FR-CHAT-009 | 相位与语义色不混用 | 流式中出现错误(mock error 场景) | 检查 pipeline 卡 | 相位点颜色只随相位走(五相位色);整体成败徽章只用语义色(success/error)——两者不互换 | L5-D | P1 |
| TC-CHAT-036 | FR-CHAT-010 | 揭示动画与跳过 | mock normal;答案长度已知 | 1. 观察 complete 后答案揭示;2. 点击「跳过」 | 揭示速度 30ms/字符,尾部 8×15px 青色闪烁光标 + 3px shimmer 进度线;点「跳过」后立即显示全文,reveal 元素移除 | L5-D | P1 |
| TC-CHAT-037 | FR-CHAT-010 | 长答案 8s 上限 | mock 构造 >2000 字符答案 | 测量揭示总时长 | 速度自动加快,总时长 ≤8s | L5-D | P2 |
1.5.5 错误与重试(FR-CHAT-012)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-CHAT-038 | FR-CHAT-012 | 引用校验失败重试 | BFF 对 invalid_llm_citation 已自动重试一次仍失败(L2 构造) | 观察响应与界面 | 前端展示「引用校验失败,请重试」(INVALID_CITATION 信封 message)并提供重试按钮 | L2(respx 断言 BFF 重试一次)+ L5 | P0 |
| TC-CHAT-039 | FR-CHAT-012 | 其他错误展示 message | mock scenario=error | 提问 | 消息置 error;展示 error.message 文案(上游错误中文文案);提供重试按钮;已收到块保留 | L5-D(error 场景) | P0 |
| TC-CHAT-040 | FR-CHAT-012 | 重试同位置替换 | 错误后 | 点击重试 | 用相同问题与模式重新发起;不新增用户消息(消息列表长度不变,同一条助手消息位置更新) | L5-D | P0 |
| TC-CHAT-041 | FR-CHAT-012 | SSE error/timeout 事件 | mock 构造 event:error 与 event:timeout 帧 | 提问 | error 帧→展示 error.message;timeout 帧→文案「检索超时」;两者均置消息 error 并保留已收到块 | L5-D(定制 mock 流) | P1 |
1.5.6 持久化与恢复(FR-CHAT-013)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-CHAT-042 | FR-CHAT-013 | 块联合完整落库 | BFF 真实;完成一次问答 | 检查 SQLite 该消息行 | blocks 含 text/table/sources/graph/pipeline 等全部完成块;无 stream 块(瞬态已转 text);raw 字段保存完整归一化响应 | L2 | P0 |
| TC-CHAT-043 | FR-CHAT-013 | 刷新后恢复全部块 | 完成一次含表格/来源/图谱的问答 | 刷新页面并打开该会话 | GET /api/sessions/{id} 后全部块正确重渲染(表格、来源、图谱可见);无数据丢失 |
L5-D | P0 |
1.6 RETRIEVAL 检索过程(FR-RETRIEVAL-001~006)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-RETRIEVAL-001 | FR-RETRIEVAL-001 | 阶段卡与 progress 帧一一对应 | mock normal;完成一次问答 | 统计工作台 Tab1 卡片数与 Network 中 progress 帧数 | 卡片数 = progress 帧数(sse_frames 11 个 stage 帧 → 11 张卡);每卡含相位色图标 + 阶段中文名 + 状态点 + 耗时 mono | L5-D | P0 |
| TC-RETRIEVAL-002 | FR-RETRIEVAL-001 | 阶段卡展开体参数块 | 已有一张阶段卡 | 展开卡头 | 展开体显示 details 参数块(mono)+ 摘要行(如 entities 列表) | L5-D | P2 |
| TC-RETRIEVAL-003 | FR-RETRIEVAL-002 | 相位筛选 | 一次问答后存在 4 个相位卡片 | 依次点击 全部/规划/检索/证据/生成 chip | 激活 chip 实心 #5E6AD2 底 + 白字;筛选后仅显示对应相位卡片(计数=对应相位帧数) | L5-D | P1 |
| TC-RETRIEVAL-004 | FR-RETRIEVAL-003 | 展开折叠与默认态 | 流式中(running 卡)与完成后各观察一次 | 1. 流式中看卡默认态;2. 完成后看默认态;3. 点击头部 | 运行中的卡默认展开;完成后自动折叠;点击切换展开/折叠;chevron 旋转 90°;展开体 fade-slide 200ms;各卡状态互相独立 | L5-D | P1 |
| TC-RETRIEVAL-005 | FR-RETRIEVAL-004 | 运行中效果 | 流式中 | 检查 running 卡 | 头部 shimmer 扫光(1.8s 循环)+ 状态点脉冲;完成后动效停止(animation none/移除) | L5-D | P2 |
| TC-RETRIEVAL-006 | FR-RETRIEVAL-005 | 检索计划展示与无 plan 不显示 | mock normal(fixture 含 retrieval_plan)与无 plan 的响应各一次 | 检查列表顶部 | 含 retrieval_plan 时顶部只读信息块展示 plan;无 plan 时该区域不渲染(无空框);另展示 /api/qa/info 的 12 段 pipeline 静态说明 |
L5-D | P1 |
| TC-RETRIEVAL-007 | FR-RETRIEVAL-006 | 空态 | 未提问 | 打开工作台 Tab1 | 显示「发起提问后,这里会实时展示检索过程」;无假卡片 | L5-D | P2 |
1.7 SOURCE 文献来源(FR-SOURCE-001~006)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-SOURCE-001 | FR-SOURCE-001 | 来源列表条目数与元素 | mock normal 完成问答(source_count=4) | 打开工作台 Tab2 | 条目数 = 4(与响应 source_count 一致);每条:序号 + 标题(超长省略)+ mono 元信息行(PMID:xxx / DOI:xxx / 分数)+ 证据片段(默认 2 行截断) | L5-D | P0 |
| TC-SOURCE-002 | FR-SOURCE-001 | 证据片段展开 | 有一条来源 | 点击片段 | 展开显示完整 snippet;再点收起 | L5-D | P2 |
| TC-SOURCE-003 | FR-SOURCE-002 | 字段缺失不渲染占位 | mock 构造 source 缺 pmid/pmcid/doi/section 的组合 | 渲染列表 | 缺失字段位置不显示占位符;页面文本中不含 undefined、null 字样 |
L5-D | P0 |
| TC-SOURCE-004 | FR-SOURCE-003 | 外链优先级 | 4 个 source:a 有 url;b 无 url 有 doi;c 无 url/doi 有 pmid;d 无 url/doi/pmid 有 pmcid;e 全无 | 检查各条目链接 | a 链=url;b=https://doi.org/{doi};c=PubMed PMID 链接;d=PMC 链接;e 无链接图标;点击新标签打开且带 rel="noopener" |
L5-D | P1 |
| TC-SOURCE-005 | FR-SOURCE-004 | 证据链分组与展开 | 响应 chains 含 ≥2 个 chain_id | 打开证据链区 | 按 chain_id 分组显示;组徽章显示跳数;展开后逐跳列表 源实体 —[关系]→ 目标实体,每跳附 paper_id/PMID;顺序与 hops 数组一致 |
L5-D | P1 |
| TC-SOURCE-006 | FR-SOURCE-005 | 会话级聚合 | 同一会话完成 2 次问答(相同 paper 出现多次) | 切到「本会话全部」 | 发出 GET /api/sessions/{id}/sources;按 paper_id 去重;每条 count = 该 paper 累计出现次数;去重后条数正确 |
L5-D + L2 | P1 |
| TC-SOURCE-007 | FR-SOURCE-006 | 空态 | mock scenario=empty 完成问答(source_count=0) | 打开工作台 Tab2 | 显示「本次检索未命中文献」;无空列表框(无 .ft-item 元素) | L5-D(empty 场景) | P1 |
1.8 EXTRACT 提取任务(FR-EXTRACT-001~006)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-EXTRACT-001 | FR-EXTRACT-001 | 任务列表与派生百分比 | mock 任务列表(含 queued/running/completed/failed 各一) | 打开工作台 Tab3 | 发出 GET /api/extraction/jobs;列表与响应一致;百分比派生正确:queued=5、running(35/75 按 stage)、completed=100、failed 无进度条且显示错误态;100% 为纯 success 色且无 sweep 扫光 |
L5-D + L2(BFF 派生断言) | P0 |
| TC-EXTRACT-002 | FR-EXTRACT-002 | 任务详情 | 已有一个任务 | 点击展开 | GET /api/extraction/jobs/{id};显示 status、message(中文进度)、stats 统计字段(stage/species/figure_table 计数) |
L5-D | P1 |
| TC-EXTRACT-003 | FR-EXTRACT-002 | 未完成任务 plan 不显示 | 一个 running 任务 | 展开详情 | plan 为 null 时不显示 plan 区块且无报错 | L5-D | P1 |
| TC-EXTRACT-004 | FR-EXTRACT-003 | 运行日志 | mock 正常 | 打开运行日志 | GET /api/extraction/run-log;mono 等宽展示;长日志在最大高度内滚动(scrollHeight > clientHeight 时出现内部滚动);自动贴底 |
L5-D | P2 |
| TC-EXTRACT-005 | FR-EXTRACT-004 | 上传 PDF 成功 | 构造 ≤50MB PDF;mock 上传成功 | 附件按钮 → 选 PDF → 上传 | POST /api/extraction/upload(multipart,Content-Type 含 multipart/form-data);显示上传进度;成功返回 job_id 并刷新列表(出现新任务) |
L5-D | P1 |
| TC-EXTRACT-006 | FR-EXTRACT-004 | 非 PDF 被拒 | 一个 .txt 文件 | 尝试上传 | 被拒绝(前端拦截或 422);不发出上传请求(前端拦截时)或返回 VALIDATION 信封 | L5-D + L2 | P1 |
| TC-EXTRACT-007 | FR-EXTRACT-004 | 超 50MB 被拒 | 一个 >50MB PDF | 尝试上传 | 被拒绝;提示超出大小限制;不发出上传请求 | L5-D | P2 |
| TC-EXTRACT-008 | FR-EXTRACT-004 | 上游失败错误文案 | mock 返回 502(MinerU 不可用) | 上传 | 展示上游 message 的明确错误文案(非堆栈);任务列表/详情为失败态 | L5-D | P1 |
| TC-EXTRACT-009 | FR-EXTRACT-005 | 轮询节奏 | 列表含一个 running 任务 | 观察 12s 内网络请求 | 每 5s 轮询一次 GET /api/extraction/jobs;全部终态后轮询停止(再观察 12s 无新请求) |
L5-D | P1 |
| TC-EXTRACT-010 | FR-EXTRACT-005 | 切 tab 暂停轮询 | running 任务存在;切换到其他 tab | 观察网络 | 离开 Tab3 期间无 jobs 轮询请求;切回恢复 | L5-D | P2 |
| TC-EXTRACT-011 | FR-EXTRACT-006 | 离线降级 | mock 对 extraction 返回 503(degraded) | 打开 Tab3 | 显示离线提示与重试按钮;其他 tab(检索/来源/图谱)不受影响可正常使用 | L5-D(degraded 场景) | P1 |
1.9 KG 知识图谱(FR-KG-001~008)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-KG-001 | FR-KG-001 | 答案图谱渲染(SVG 力导向) | mock normal 完成问答(graph 块 6 节点 4 边) | 打开工作台 Tab4 | 渲染手写 SVG 力导向图:节点圆点+标签;边为渐变线(#5E6AD2→#00D4FF)带关系名;节点与答案引用实体一致(与 graph 块节点 label 一致) | L5-D | P0 |
| TC-KG-002 | FR-KG-001 | 节点 >50 降级列表 | mock 构造 graph 块 >50 节点 | 打开 Tab4 | 自动降级为列表视图并提示;不渲染 SVG 画布 | L5-D | P1 |
| TC-KG-003 | FR-KG-002 | 节点着色与图例 | graph 块含 ≥2 种实体 type | 检查节点颜色与图例 | 按 type 着色(品牌+辅助紫+五相位色板);底部图例存在且与节点颜色一一对应;同 type 在会话内颜色稳定(两次问答同一 type 颜色相同) | L5-D | P2 |
| TC-KG-004 | FR-KG-003 | 节点详情面板 | graph 块有节点;Neo4j 不可用(mock 无 kg 或 503) | 点击一个节点 | 侧滑详情面板显示实体属性(消息内已有属性);Neo4j 不可用时仍显示(不报错、不空白) | L5-D | P1 |
| TC-KG-005 | FR-KG-003 | Neo4j 可用时拉全量属性 | Neo4j 可用(真实上游或 mock) | 点击节点 | 面板内额外数据来自 GET /api/kg/entities/{name}(发出该请求并渲染返回 properties) |
L5-D | P2 |
| TC-KG-006 | FR-KG-004 | 实体搜索(精确/前缀) | mock normal | 1. 输入「OsSPL」;2. 回车 | GET /api/kg/entities?q=OsSPL;结果显示(精确或前缀匹配项);响应 <1s(断言用时) |
L5-D + L2 | P0 |
| TC-KG-007 | FR-KG-004 | 实体搜索选中渲染邻域 | 上一步结果 | 点击第一个结果 | 渲染该实体邻域(调 neighborhood 接口或 mock 数据);画布更新为该实体为中心 | L5-D | P1 |
| TC-KG-008 | FR-KG-005 | 邻域深度切换 | mock normal | 1. 深度选 1(默认)观察请求;2. 深度选 2 观察 | 请求 depth 参数分别为 1/2;渲染节点数随之变化;深度 2 时显示「较慢」提示文案(两跳实测约 13s) | L5-D + L2 | P1 |
| TC-KG-009 | FR-KG-005 | 节点上限 200 截断 | mock 构造 >200 节点邻域 | 深度 2 展开 | 渲染节点数 ≤200;每跳按 paper_count/support_count 降序截断(L2 断言 BFF 截断逻辑);超限有提示不卡死 | L2 + L5 | P1 |
| TC-KG-010 | FR-KG-006 | 缩放平移(桌面) | 画布有图 | 滚轮缩放;拖拽平移;双击 | 缩放范围 0.3×–3×;平移生效;双击复位到初始视图 | L5-D | P1 |
| TC-KG-011 | FR-KG-006 | 触摸缩放平移(移动端) | Mobile 视口;画布有图 | 双指捏合;单指拖拽 | 双指缩放与单指拖拽均可用且流畅(缩放比例改变;拖拽后画布位移) | L5-M(touch 模拟) | P1 |
| TC-KG-012 | FR-KG-007 | Neo4j 不可用降级 | mock kg 接口返回 503(或 BFF 断开 Neo4j) | 打开 Tab4 | 搜索框与邻域功能禁用并提示离线;答案图谱照常渲染;tab 不白屏 | L5-D | P1 |
| TC-KG-013 | FR-KG-008 | 空态 | 本次回答无 graph 数据(mock empty) | 打开 Tab4 | 提示「本次检索未产生图谱关系」+ 引导使用实体搜索;不显示空画布 | L5-D(empty 场景) | P2 |
1.10 RESP 响应式(FR-RESP-001~013)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-RESP-001 | FR-RESP-001 | Desktop ≥1280 完整三栏 | Desktop 1440×900 | 检查布局 | 三栏 260/1fr/380 可见(同 TC-SHELL-001) | L5-D | P0 |
| TC-RESP-002 | FR-RESP-002 | Laptop 1024–1279 左栏自动折叠 | 视口 1200×900 | 检查布局 | 三栏保留;左栏宽=64px(自动折叠,无需点击);右栏=340px | L5-D(1200×900) | P1 |
| TC-RESP-003 | FR-RESP-003 | Tablet 左抽屉 | Tablet 768×1024 | 1. 检查布局(对话单栏铺满);2. 点顶栏汉堡 | 左栏默认隐藏;点汉堡后左抽屉 260px 滑入 + scrim 遮罩;顶栏有汉堡按钮;右栏为右抽屉(顶栏工作台按钮带来源数角标);点 scrim 或 Esc 关闭;动效 ease-out 300ms | L5-T | P0 |
| TC-RESP-004 | FR-RESP-004 | Mobile 单栏与工作台覆盖层 | Mobile 390×844 | 1. 检查布局;2. 点顶栏工作台按钮 | 顶栏=汉堡+标题+工作台按钮;对话铺满;作曲器吸底;工作台打开为全屏覆盖层+顶部 tab 条;底部状态栏隐藏(不可见);四个 agent 点合并为顶栏一枚聚合状态点;点 scrim 或 Esc 关闭 | L5-M | P0 |
| TC-RESP-005 | FR-RESP-005 | viewport 与安全区 | Mobile(iPhone 视口) | 检查 meta 与 computed 值 | <meta viewport> 含 viewport-fit=cover;作曲器 padding-bottom = env(safe-area-inset-bottom);顶栏 padding-top = env(safe-area-inset-top)(computed 值>0) |
L5-M | P1 |
| TC-RESP-006 | FR-RESP-006 | iOS 输入放大规避 | Mobile 视口(<768px) | 检查 textarea computed font-size | font-size=16px;未使用 maximum-scale=1(meta 内容断言) | L5-M | P0 |
| TC-RESP-007 | FR-RESP-007 | 悬停态触摸等价 | Mobile 视口;有来源条目与助手消息 | 检查来源外链图标、助手消息左缘线、会话条目样式 | 外链图标常驻可见;助手消息左缘线常驻;会话条目无 hover 底色依赖(点击反馈存在);@media (hover:hover) 包裹 hover 样式(L3 样式断言) |
L5-M | P1 |
| TC-RESP-008 | FR-RESP-008 | 触控目标 44px | Mobile 视口 | 检查会话条目、bench tab、模式 pill、图标按钮高度 | min-height ≥44px(computed) | L5-M | P1 |
| TC-RESP-009 | FR-RESP-009 | 100dvh 视口高度 | Mobile 视口 | 检查应用根容器高度 | 使用 100dvh(computed 解析为实际视口高度);存在 100vh 回退声明(L3 样式断言) | L5-M | P2 |
| TC-RESP-010 | FR-RESP-010 | 虚拟键盘适配 | Mobile 视口;visualViewport 可模拟 | 聚焦 textarea(模拟键盘弹出压缩 visualViewport) | 消息区高度压缩并保持贴底;作曲器始终可见(boundingBox 在视口内) | L5-M | P1 |
| TC-RESP-011 | FR-RESP-011 | 表格横向滚动 | Mobile 视口;消息含宽表格 | 检查 md-table 容器 | 表格外层有横向滚动容器;容器 scrollWidth > clientWidth 时可横滑查看完整内容;字体字号未被压缩(computed font-size ≥ 桌面值) | L5-M | P1 |
| TC-RESP-012 | FR-RESP-012 | 移动端性能降级 | Mobile 视口 | 检查 aurora 与图谱上限 | aurora 模糊半径降低或 --pa-aurora-opacity:0;图谱节点数上限=30(构造 >30 节点 graph 块时渲染 ≤30 或降级列表) |
L5-M | P2 |
| TC-RESP-013 | FR-RESP-013 | 手势(可选 N/A) | Mobile 视口 | 左缘右滑 | 若实现:右滑开会话抽屉、右滑关工作台覆盖层可用;未实现不算缺陷,本条 N/A 记录 | L5-M(标记 N/A) | P2 |
1.11 HEALTH 健康与降级(FR-HEALTH-001~005)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-HEALTH-001 | FR-HEALTH-001 | 健康轮询 30s | 打开应用 | 观察 65s 内 GET /api/health 请求 |
挂载后立即一次;此后每 30s 一次(65s 内共 3 次) | L5-D | P1 |
| TC-HEALTH-002 | FR-HEALTH-001 | 轮询失败不弹窗 | mock /api/health 持续 500 |
打开应用 | 无错误弹窗/未捕获异常;状态栏健康标记显示降级态 | L5-D | P1 |
| TC-HEALTH-003 | FR-HEALTH-001 | 上游恢复 30s 内解禁 | mock 先 503 后恢复正常(场景切换) | 1. 观察禁用态;2. 切回正常场景;3. ≤30s 内观察 | 上游恢复后 ≤30s(一个轮询周期内)对应功能自动解禁,无需手动刷新 | L5-D | P1 |
| TC-HEALTH-004 | FR-HEALTH-002 | QA 不可用降级 | mock scenario=degraded(/api/qa/* 503) | 打开应用 | 作曲器禁用并显示「知识问答服务当前不可用」;历史会话仍可浏览(点击会话可看历史消息);无错误弹窗 | L5-D(degraded 场景) | P0 |
| TC-HEALTH-005 | FR-HEALTH-002 | QA 降级信封语义 | mock degraded | 检查响应结构 | HTTP 503 + {"ok":false,"error":{"code":"UPSTREAM_DOWN","message":"…","degraded":true}};前端按 degraded 处理(横幅/离线态)而非错误弹窗 |
L2 + L5 | P0 |
| TC-HEALTH-006 | FR-HEALTH-003 | Neo4j 不可用降级 | mock kg 503 | 打开 Tab4 | 搜索/邻域禁用并提示离线;答案图谱照常渲染(同 TC-KG-012) | L5-D | P1 |
| TC-HEALTH-007 | FR-HEALTH-004 | 抽取不可用降级 | mock extraction 503 | 打开 Tab3 | 仅 Tab3 降级(离线提示+重试按钮);其他 tab 正常(同 TC-EXTRACT-011) | L5-D | P1 |
| TC-HEALTH-008 | FR-HEALTH-005 | 网络中断提示与不自动重连 | 流式中断网(同 TC-CHAT-030) | 1. 断网;2. 恢复网络观察 | 提示「连接中断」+ 重试按钮;不自动重连;无重复 LLM 调用(Network 无自动新请求) | L5-D | P0 |
1.12 非功能要求(PRD §14)对照用例
| 编号 | 对应要求 | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-NFR-001 | 首屏可交互 | 桌面;mock normal | 打开应用并计时(performance.timing / Playwright 计时) | 桌面 <2s 可交互(首屏渲染+会话列表加载完成);手机 <3s | L5-D / L5-M | P1 | |
| TC-NFR-002 | 长任务反馈 | mock slow(长流) | 提问并采样 | 240s 内无静止 >5s 状态(同 TC-CHAT-029) | L5-D | P0 | |
| TC-NFR-003 | Neo4j 凭据不下发 | 打开应用并抓取全部网络响应与 JS bundle 文本 | 浏览器侧任何响应/源码中不含 Neo4j 密码(<neo4j-password-in-.env> 等)与 bolt:// URI | L5-D + L3(bundle 扫描) | P0 | ||
| TC-NFR-004 | 零外网请求 | 打开应用并抓取全部网络请求 | 所有请求 host 均为 127.0.0.1(或部署域);无 fonts.googleapis.com / CDN 域名请求 | L5-D | P1 | ||
| TC-NFR-005 | 浏览器兼容基线 | Chrome 110+/Firefox 110+/Safari 16+ | Playwright 三浏览器各跑冒烟 2 条 | 冒烟通过(页面加载 + AppShell 存在) | L5(chromium 常驻;firefox/webkit 每轮按需) | P1 |
1.13 E2E 主线场景(TEST_PLAN §6 九条主线 × 三档视口)
编号规则 TC-E2E-<主线号>-<视口>,M=Mobile(390×844)|T=Tablet(768×1024)|D=Desktop(1440×900)。每条为一条用例,步骤与预期为该视口下的完整流程断言。全量用例在后续轮次落为 spec 文件;本波仅实现 TC-E2E-SMOKE-01/02(§1.14)。
| 编号 | 主线 | 视口 | 步骤 | 预期结果 | 优先级 |
|---|---|---|---|---|---|
| TC-E2E-01-M | 1 主流程 | M | 新建会话 → 问答模式提问 → 观察流水线五相位推进 → 等待答案揭示(含表格)→ 来源 tab 有数据 → 图谱 tab 渲染 → 刷新后历史恢复 | 五相位按序推进(waiting→running→done);答案揭示并含 md-table;Tab2 条目数=source_count;Tab4 SVG 图渲染;刷新后该会话消息完整恢复 | P0 |
| TC-E2E-01-T | 1 主流程 | T | 同 TC-E2E-01-M(左栏经抽屉进入会话) | 同 TC-E2E-01-M;另断言左/右抽屉开合正常 | P0 |
| TC-E2E-01-D | 1 主流程 | D | 同 TC-E2E-01-M | 同 TC-E2E-01-M | P0 |
| TC-E2E-02-M | 2 检索模式 | M | 检索模式提问 → 等待完成 → 检查消息块 | 无 text 答案块;仅来源数据;请求体 use_llm=false 且端点 /api/qa/search |
P0 |
| TC-E2E-02-T | 2 检索模式 | T | 同 TC-E2E-02-M | 同 TC-E2E-02-M | P0 |
| TC-E2E-02-D | 2 检索模式 | D | 同 TC-E2E-02-M | 同 TC-E2E-02-M | P0 |
| TC-E2E-03-M | 3 错误与重试 | M | scenario=error 下提问 → 观察错误;scenario=degraded 下观察作曲器 | error:错误文案展示+重试按钮可用(点击后重新发起);degraded:作曲器禁用+「知识问答服务当前不可用」提示 | P0 |
| TC-E2E-03-T | 3 错误与重试 | T | 同 TC-E2E-03-M | 同 TC-E2E-03-M | P0 |
| TC-E2E-03-D | 3 错误与重试 | D | 同 TC-E2E-03-M | 同 TC-E2E-03-M | P0 |
| TC-E2E-04-M | 4 会话管理 | M | 新建/切换/重命名/删除/搜索过滤/观察分组 | 每步按 SESSION 用例断言:新建+1、切换加载历史、重命名同步顶栏、删除需确认且列表-1、搜索实时过滤、分组标签正确 | P0 |
| TC-E2E-04-T | 4 会话管理 | T | 同 TC-E2E-04-M | 同 TC-E2E-04-M | P0 |
| TC-E2E-04-D | 4 会话管理 | D | 同 TC-E2E-04-M | 同 TC-E2E-04-M | P0 |
| TC-E2E-05-M | 5 中断 | M | 流式中途切会话 → 切回原会话 | 原会话置 error 且标注「已中断」;已收到块保留;无悬挂流 | P0 |
| TC-E2E-05-T | 5 中断 | T | 同 TC-E2E-05-M | 同 TC-E2E-05-M | P0 |
| TC-E2E-05-D | 5 中断 | D | 同 TC-E2E-05-M | 同 TC-E2E-05-M | P0 |
| TC-E2E-06-M | 6 主题 | M | 深浅切换 → 刷新 | 切换即时生效(dataset.theme 与 localStorage);刷新后保持 | P0 |
| TC-E2E-06-T | 6 主题 | T | 同 TC-E2E-06-M | 同 TC-E2E-06-M | P0 |
| TC-E2E-06-D | 6 主题 | D | 同 TC-E2E-06-M | 同 TC-E2E-06-M | P0 |
| TC-E2E-07-M | 7 图谱 | M | 实体搜索 → 选中渲染邻域 → 节点详情 → 双指缩放 + 单指拖拽 | 搜索结果渲染;邻域画布更新;详情面板打开;触摸缩放/拖拽生效 | P1 |
| TC-E2E-07-T | 7 图谱 | T | 同 TC-E2E-07-M(触摸为单指拖拽+双指捏合) | 同 TC-E2E-07-M | P1 |
| TC-E2E-07-D | 7 图谱 | D | 实体搜索 → 邻域 → 详情 → 滚轮缩放/拖拽平移/双击复位 | 同 TC-E2E-07-M(桌面交互) | P1 |
| TC-E2E-08-M | 8 抽取 | M | 任务列表 → 详情展开 → 运行日志;mock 下上传 PDF | 列表渲染+百分比正确;详情字段齐全;日志滚动;上传成功返回 job_id 并刷新列表 | P1 |
| TC-E2E-08-T | 8 抽取 | T | 同 TC-E2E-08-M | 同 TC-E2E-08-M | P1 |
| TC-E2E-08-D | 8 抽取 | D | 同 TC-E2E-08-M | 同 TC-E2E-08-M | P1 |
| TC-E2E-09-M | 9 响应式专项 | M | 布局断言(FR-RESP-004 全项)+ 移动端专项:安全区、16px 输入、44px 触控、表格横滚、键盘适配 | 顶栏=汉堡+标题+工作台按钮;作曲器吸底;工作台全屏覆盖层+tab 条;底栏隐藏;聚合状态点存在;safe-area padding 生效;textarea 16px;触控目标 ≥44px;宽表格横滚;聚焦时作曲器可见 | P0 |
| TC-E2E-09-T | 9 响应式专项 | T | 布局断言(FR-RESP-003 全项:抽屉/scrim/角标) | 单栏铺满;左右抽屉开合+scrim+Esc 关闭;汉堡与工作台按钮带来源数角标 | P0 |
| TC-E2E-09-D | 9 响应式专项 | D | 布局断言(FR-RESP-001/002:1280 边界与 1200 折叠) | 1440 完整三栏;1200 左栏自动折叠 64px 右栏 340px | P0 |
1.14 E2E 冒烟骨架用例(本波已实现)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-E2E-SMOKE-01 | FR-SHELL-007(页面加载) | 页面加载冒烟 | dev server 5180 可用;三档视口各跑一次 | 打开 / |
title 含「海古纪 PlantAI」;#app 可见且内容非空 |
L5-M/T/D | P0 |
| TC-E2E-SMOKE-02 | FR-SHELL-001/003/FR-RESP-004(壳层;移动端底栏隐藏断言) | AppShell 存在冒烟 | 同上 | 打开 / |
存在 .app-shell 时:shell/top-bar 可见且无占位符;status-bar 在 ≥768px 视口可见、移动端隐藏(FR-RESP-004);M0 占位期(无 .app-shell)回退:.app-shell-placeholder 可见 |
L5-M/T/D | P0 |
2. 追溯矩阵
2.1 统计总览
| 项 | 值 |
|---|---|
| FR 总数 | 81 |
| 已覆盖 FR | 81 |
| 未覆盖清单 | (空) |
| TC 总数 | 179 |
| 孤儿 TC(无 FR 映射) | 0 |
| 主门禁(FR→TC 且 TC→FR 双向完整) | 81/81 = 100% |
2.2 FR→TC 矩阵(每个 FR 列出其全部 TC)
| FR | 用例 |
|---|---|
| FR-SHELL-001 | TC-SHELL-001, TC-SHELL-002, TC-E2E-SMOKE-02, TC-E2E-09-D |
| FR-SHELL-002 | TC-SHELL-003, TC-SHELL-004, TC-SHELL-005 |
| FR-SHELL-003 | TC-SHELL-006, TC-SHELL-007, TC-E2E-SMOKE-02 |
| FR-SHELL-004 | TC-SHELL-008, TC-SHELL-009 |
| FR-SHELL-005 | TC-SHELL-010 |
| FR-SHELL-006 | TC-SHELL-011, TC-SHELL-012 |
| FR-SHELL-007 | TC-SHELL-013, TC-SHELL-014, TC-SHELL-015, TC-E2E-SMOKE-01 |
| FR-THEME-001 | TC-THEME-001, TC-THEME-002 |
| FR-THEME-002 | TC-THEME-003, TC-THEME-004, TC-E2E-06-M, TC-E2E-06-T, TC-E2E-06-D |
| FR-THEME-003 | TC-THEME-005 |
| FR-THEME-004 | TC-THEME-006 |
| FR-THEME-005 | TC-THEME-007, TC-THEME-008 |
| FR-THEME-006 | TC-THEME-009, TC-THEME-010 |
| FR-SESSION-001 | TC-SESSION-001, TC-SESSION-002, TC-SESSION-003, TC-E2E-04-M, TC-E2E-04-T, TC-E2E-04-D |
| FR-SESSION-002 | TC-SESSION-004 |
| FR-SESSION-003 | TC-SESSION-005, TC-SESSION-006, TC-E2E-04-M, TC-E2E-04-T, TC-E2E-04-D |
| FR-SESSION-004 | TC-SESSION-007, TC-SESSION-008, TC-E2E-04-M, TC-E2E-04-T, TC-E2E-04-D |
| FR-SESSION-005 | TC-SESSION-009, TC-E2E-04-M, TC-E2E-04-T, TC-E2E-04-D |
| FR-SESSION-006 | TC-SESSION-010, TC-SESSION-011, TC-E2E-04-M, TC-E2E-04-T, TC-E2E-04-D |
| FR-SESSION-007 | TC-SESSION-012, TC-SESSION-013, TC-SESSION-014, TC-SESSION-015, TC-E2E-04-M, TC-E2E-04-T, TC-E2E-04-D |
| FR-SESSION-008 | TC-SESSION-016, TC-SESSION-017 |
| FR-SESSION-009 | TC-SESSION-018 |
| FR-CHAT-001 | TC-CHAT-001, TC-CHAT-002 |
| FR-CHAT-002 | TC-CHAT-003 |
| FR-CHAT-003 | TC-CHAT-004, TC-CHAT-005 |
| FR-CHAT-004 | TC-CHAT-006, TC-CHAT-007 |
| FR-CHAT-005 | TC-CHAT-012 |
| FR-CHAT-006 | TC-CHAT-013, TC-CHAT-014, TC-CHAT-015, TC-CHAT-016, TC-E2E-02-M, TC-E2E-02-T, TC-E2E-02-D |
| FR-CHAT-007 | TC-CHAT-017, TC-CHAT-018, TC-CHAT-019, TC-CHAT-020 |
| FR-CHAT-008 | TC-CHAT-023, TC-CHAT-024, TC-CHAT-025, TC-CHAT-026, TC-CHAT-027, TC-CHAT-028, TC-CHAT-029, TC-CHAT-030, TC-CHAT-031, TC-CHAT-032, TC-CHAT-033, TC-E2E-01-M, TC-E2E-01-T, TC-E2E-01-D, TC-E2E-05-M, TC-E2E-05-T, TC-E2E-05-D |
| FR-CHAT-009 | TC-CHAT-034, TC-CHAT-035 |
| FR-CHAT-010 | TC-CHAT-036, TC-CHAT-037 |
| FR-CHAT-011 | TC-CHAT-021, TC-CHAT-022, TC-E2E-05-M, TC-E2E-05-T, TC-E2E-05-D |
| FR-CHAT-012 | TC-CHAT-038, TC-CHAT-039, TC-CHAT-040, TC-CHAT-041, TC-E2E-03-M, TC-E2E-03-T, TC-E2E-03-D |
| FR-CHAT-013 | TC-CHAT-042, TC-CHAT-043, TC-E2E-01-M, TC-E2E-01-T, TC-E2E-01-D |
| FR-CHAT-014 | TC-CHAT-008, TC-CHAT-009, TC-CHAT-010 |
| FR-CHAT-015 | TC-CHAT-011 |
| FR-RETRIEVAL-001 | TC-RETRIEVAL-001, TC-RETRIEVAL-002 |
| FR-RETRIEVAL-002 | TC-RETRIEVAL-003 |
| FR-RETRIEVAL-003 | TC-RETRIEVAL-004 |
| FR-RETRIEVAL-004 | TC-RETRIEVAL-005 |
| FR-RETRIEVAL-005 | TC-RETRIEVAL-006 |
| FR-RETRIEVAL-006 | TC-RETRIEVAL-007 |
| FR-SOURCE-001 | TC-SOURCE-001, TC-SOURCE-002 |
| FR-SOURCE-002 | TC-SOURCE-003 |
| FR-SOURCE-003 | TC-SOURCE-004 |
| FR-SOURCE-004 | TC-SOURCE-005 |
| FR-SOURCE-005 | TC-SOURCE-006 |
| FR-SOURCE-006 | TC-SOURCE-007 |
| FR-EXTRACT-001 | TC-EXTRACT-001, TC-E2E-08-M, TC-E2E-08-T, TC-E2E-08-D |
| FR-EXTRACT-002 | TC-EXTRACT-002, TC-EXTRACT-003, TC-E2E-08-M, TC-E2E-08-T, TC-E2E-08-D |
| FR-EXTRACT-003 | TC-EXTRACT-004, TC-E2E-08-M, TC-E2E-08-T, TC-E2E-08-D |
| FR-EXTRACT-004 | TC-EXTRACT-005, TC-EXTRACT-006, TC-EXTRACT-007, TC-EXTRACT-008, TC-E2E-08-M, TC-E2E-08-T, TC-E2E-08-D |
| FR-EXTRACT-005 | TC-EXTRACT-009, TC-EXTRACT-010 |
| FR-EXTRACT-006 | TC-EXTRACT-011 |
| FR-KG-001 | TC-KG-001, TC-KG-002 |
| FR-KG-002 | TC-KG-003 |
| FR-KG-003 | TC-KG-004, TC-KG-005 |
| FR-KG-004 | TC-KG-006, TC-KG-007, TC-E2E-07-M, TC-E2E-07-T, TC-E2E-07-D |
| FR-KG-005 | TC-KG-008, TC-KG-009, TC-E2E-07-M, TC-E2E-07-T, TC-E2E-07-D |
| FR-KG-006 | TC-KG-010, TC-KG-011, TC-E2E-07-M, TC-E2E-07-T, TC-E2E-07-D |
| FR-KG-007 | TC-KG-012 |
| FR-KG-008 | TC-KG-013 |
| FR-RESP-001 | TC-RESP-001, TC-E2E-09-D |
| FR-RESP-002 | TC-RESP-002, TC-E2E-09-D |
| FR-RESP-003 | TC-RESP-003, TC-E2E-09-T |
| FR-RESP-004 | TC-RESP-004, TC-E2E-09-M, TC-E2E-SMOKE-02 |
| FR-RESP-005 | TC-RESP-005, TC-E2E-09-M |
| FR-RESP-006 | TC-RESP-006, TC-E2E-09-M |
| FR-RESP-007 | TC-RESP-007, TC-E2E-09-M |
| FR-RESP-008 | TC-RESP-008, TC-E2E-09-M |
| FR-RESP-009 | TC-RESP-009, TC-E2E-09-M |
| FR-RESP-010 | TC-RESP-010, TC-E2E-09-M |
| FR-RESP-011 | TC-RESP-011, TC-E2E-09-M |
| FR-RESP-012 | TC-RESP-012, TC-E2E-09-M |
| FR-RESP-013 | TC-RESP-013(N/A 可选) |
| FR-HEALTH-001 | TC-HEALTH-001, TC-HEALTH-002, TC-HEALTH-003 |
| FR-HEALTH-002 | TC-HEALTH-004, TC-HEALTH-005, TC-E2E-03-M, TC-E2E-03-T, TC-E2E-03-D |
| FR-HEALTH-003 | TC-HEALTH-006, TC-KG-012 |
| FR-HEALTH-004 | TC-HEALTH-007, TC-EXTRACT-011 |
| FR-HEALTH-005 | TC-HEALTH-008, TC-CHAT-030 |
非功能要求(PRD §14,非 FR 编号)由 TC-NFR-001~005 覆盖:首屏性能(TC-NFR-001)、长任务反馈(TC-NFR-002)、凭据安全(TC-NFR-003)、零外网(TC-NFR-004)、浏览器兼容(TC-NFR-005)。
2.3 TC→FR 矩阵(每条 TC 列出其全部 FR,证明无孤儿)
| TC | FR |
|---|---|
| TC-SHELL-001 | FR-SHELL-001 |
| TC-SHELL-002 | FR-SHELL-001 |
| TC-SHELL-003 | FR-SHELL-002 |
| TC-SHELL-004 | FR-SHELL-002 |
| TC-SHELL-005 | FR-SHELL-002 |
| TC-SHELL-006 | FR-SHELL-003 |
| TC-SHELL-007 | FR-SHELL-003 |
| TC-SHELL-008 | FR-SHELL-004 |
| TC-SHELL-009 | FR-SHELL-004 |
| TC-SHELL-010 | FR-SHELL-005 |
| TC-SHELL-011 | FR-SHELL-006 |
| TC-SHELL-012 | FR-SHELL-006 |
| TC-SHELL-013 | FR-SHELL-007 |
| TC-SHELL-014 | FR-SHELL-007 |
| TC-SHELL-015 | FR-SHELL-007 |
| TC-THEME-001 | FR-THEME-001 |
| TC-THEME-002 | FR-THEME-001 |
| TC-THEME-003 | FR-THEME-002 |
| TC-THEME-004 | FR-THEME-002 |
| TC-THEME-005 | FR-THEME-003 |
| TC-THEME-006 | FR-THEME-004 |
| TC-THEME-007 | FR-THEME-005 |
| TC-THEME-008 | FR-THEME-005 |
| TC-THEME-009 | FR-THEME-006 |
| TC-THEME-010 | FR-THEME-006 |
| TC-SESSION-001 | FR-SESSION-001 |
| TC-SESSION-002 | FR-SESSION-001 |
| TC-SESSION-003 | FR-SESSION-001 |
| TC-SESSION-004 | FR-SESSION-002 |
| TC-SESSION-005 | FR-SESSION-003 |
| TC-SESSION-006 | FR-SESSION-003 |
| TC-SESSION-007 | FR-SESSION-004 |
| TC-SESSION-008 | FR-SESSION-004 |
| TC-SESSION-009 | FR-SESSION-005 |
| TC-SESSION-010 | FR-SESSION-006 |
| TC-SESSION-011 | FR-SESSION-006 |
| TC-SESSION-012 | FR-SESSION-007 |
| TC-SESSION-013 | FR-SESSION-007 |
| TC-SESSION-014 | FR-SESSION-007 |
| TC-SESSION-015 | FR-SESSION-007 |
| TC-SESSION-016 | FR-SESSION-008 |
| TC-SESSION-017 | FR-SESSION-008 |
| TC-SESSION-018 | FR-SESSION-009 |
| TC-CHAT-001 | FR-CHAT-001 |
| TC-CHAT-002 | FR-CHAT-001 |
| TC-CHAT-003 | FR-CHAT-002 |
| TC-CHAT-004 | FR-CHAT-003 |
| TC-CHAT-005 | FR-CHAT-003 |
| TC-CHAT-006 | FR-CHAT-004 |
| TC-CHAT-007 | FR-CHAT-004 |
| TC-CHAT-008 | FR-CHAT-014 |
| TC-CHAT-009 | FR-CHAT-014 |
| TC-CHAT-010 | FR-CHAT-014 |
| TC-CHAT-011 | FR-CHAT-015 |
| TC-CHAT-012 | FR-CHAT-005 |
| TC-CHAT-013 | FR-CHAT-006 |
| TC-CHAT-014 | FR-CHAT-006 |
| TC-CHAT-015 | FR-CHAT-006 |
| TC-CHAT-016 | FR-CHAT-006 |
| TC-CHAT-017 | FR-CHAT-007 |
| TC-CHAT-018 | FR-CHAT-007 |
| TC-CHAT-019 | FR-CHAT-007 |
| TC-CHAT-020 | FR-CHAT-007 |
| TC-CHAT-021 | FR-CHAT-011 |
| TC-CHAT-022 | FR-CHAT-011 |
| TC-CHAT-023 | FR-CHAT-008 |
| TC-CHAT-024 | FR-CHAT-008 |
| TC-CHAT-025 | FR-CHAT-008 |
| TC-CHAT-026 | FR-CHAT-008 |
| TC-CHAT-027 | FR-CHAT-008 |
| TC-CHAT-028 | FR-CHAT-008 |
| TC-CHAT-029 | FR-CHAT-008 |
| TC-CHAT-030 | FR-CHAT-008, FR-HEALTH-005 |
| TC-CHAT-031 | FR-CHAT-008 |
| TC-CHAT-032 | FR-CHAT-008 |
| TC-CHAT-033 | FR-CHAT-008 |
| TC-CHAT-034 | FR-CHAT-009 |
| TC-CHAT-035 | FR-CHAT-009 |
| TC-CHAT-036 | FR-CHAT-010 |
| TC-CHAT-037 | FR-CHAT-010 |
| TC-CHAT-038 | FR-CHAT-012 |
| TC-CHAT-039 | FR-CHAT-012 |
| TC-CHAT-040 | FR-CHAT-012 |
| TC-CHAT-041 | FR-CHAT-012 |
| TC-CHAT-042 | FR-CHAT-013 |
| TC-CHAT-043 | FR-CHAT-013 |
| TC-RETRIEVAL-001 | FR-RETRIEVAL-001 |
| TC-RETRIEVAL-002 | FR-RETRIEVAL-001 |
| TC-RETRIEVAL-003 | FR-RETRIEVAL-002 |
| TC-RETRIEVAL-004 | FR-RETRIEVAL-003 |
| TC-RETRIEVAL-005 | FR-RETRIEVAL-004 |
| TC-RETRIEVAL-006 | FR-RETRIEVAL-005 |
| TC-RETRIEVAL-007 | FR-RETRIEVAL-006 |
| TC-SOURCE-001 | FR-SOURCE-001 |
| TC-SOURCE-002 | FR-SOURCE-001 |
| TC-SOURCE-003 | FR-SOURCE-002 |
| TC-SOURCE-004 | FR-SOURCE-003 |
| TC-SOURCE-005 | FR-SOURCE-004 |
| TC-SOURCE-006 | FR-SOURCE-005 |
| TC-SOURCE-007 | FR-SOURCE-006 |
| TC-EXTRACT-001 | FR-EXTRACT-001 |
| TC-EXTRACT-002 | FR-EXTRACT-002 |
| TC-EXTRACT-003 | FR-EXTRACT-002 |
| TC-EXTRACT-004 | FR-EXTRACT-003 |
| TC-EXTRACT-005 | FR-EXTRACT-004 |
| TC-EXTRACT-006 | FR-EXTRACT-004 |
| TC-EXTRACT-007 | FR-EXTRACT-004 |
| TC-EXTRACT-008 | FR-EXTRACT-004 |
| TC-EXTRACT-009 | FR-EXTRACT-005 |
| TC-EXTRACT-010 | FR-EXTRACT-005 |
| TC-EXTRACT-011 | FR-EXTRACT-006, FR-HEALTH-004 |
| TC-KG-001 | FR-KG-001 |
| TC-KG-002 | FR-KG-001 |
| TC-KG-003 | FR-KG-002 |
| TC-KG-004 | FR-KG-003 |
| TC-KG-005 | FR-KG-003 |
| TC-KG-006 | FR-KG-004 |
| TC-KG-007 | FR-KG-004 |
| TC-KG-008 | FR-KG-005 |
| TC-KG-009 | FR-KG-005 |
| TC-KG-010 | FR-KG-006 |
| TC-KG-011 | FR-KG-006 |
| TC-KG-012 | FR-KG-007, FR-HEALTH-003 |
| TC-KG-013 | FR-KG-008 |
| TC-RESP-001 | FR-RESP-001 |
| TC-RESP-002 | FR-RESP-002 |
| TC-RESP-003 | FR-RESP-003 |
| TC-RESP-004 | FR-RESP-004 |
| TC-RESP-005 | FR-RESP-005 |
| TC-RESP-006 | FR-RESP-006 |
| TC-RESP-007 | FR-RESP-007 |
| TC-RESP-008 | FR-RESP-008 |
| TC-RESP-009 | FR-RESP-009 |
| TC-RESP-010 | FR-RESP-010 |
| TC-RESP-011 | FR-RESP-011 |
| TC-RESP-012 | FR-RESP-012 |
| TC-RESP-013 | FR-RESP-013(N/A 可选) |
| TC-HEALTH-001 | FR-HEALTH-001 |
| TC-HEALTH-002 | FR-HEALTH-001 |
| TC-HEALTH-003 | FR-HEALTH-001 |
| TC-HEALTH-004 | FR-HEALTH-002 |
| TC-HEALTH-005 | FR-HEALTH-002 |
| TC-HEALTH-006 | FR-HEALTH-003 |
| TC-HEALTH-007 | FR-HEALTH-004 |
| TC-HEALTH-008 | FR-HEALTH-005 |
| TC-NFR-001 | PRD §14 首屏可交互(非 FR) |
| TC-NFR-002 | PRD §14 长任务反馈(非 FR) |
| TC-NFR-003 | PRD §14 数据安全(非 FR) |
| TC-NFR-004 | PRD §14 离线容忍(非 FR) |
| TC-NFR-005 | PRD §14 浏览器支持(非 FR) |
| TC-E2E-01-M | FR-CHAT-008, FR-CHAT-013 |
| TC-E2E-01-T | FR-CHAT-008, FR-CHAT-013 |
| TC-E2E-01-D | FR-CHAT-008, FR-CHAT-013 |
| TC-E2E-02-M | FR-CHAT-006 |
| TC-E2E-02-T | FR-CHAT-006 |
| TC-E2E-02-D | FR-CHAT-006 |
| TC-E2E-03-M | FR-CHAT-012, FR-HEALTH-002 |
| TC-E2E-03-T | FR-CHAT-012, FR-HEALTH-002 |
| TC-E2E-03-D | FR-CHAT-012, FR-HEALTH-002 |
| TC-E2E-04-M | FR-SESSION-001, FR-SESSION-003, FR-SESSION-004, FR-SESSION-005, FR-SESSION-006, FR-SESSION-007 |
| TC-E2E-04-T | FR-SESSION-001, FR-SESSION-003, FR-SESSION-004, FR-SESSION-005, FR-SESSION-006, FR-SESSION-007 |
| TC-E2E-04-D | FR-SESSION-001, FR-SESSION-003, FR-SESSION-004, FR-SESSION-005, FR-SESSION-006, FR-SESSION-007 |
| TC-E2E-05-M | FR-CHAT-008, FR-CHAT-011 |
| TC-E2E-05-T | FR-CHAT-008, FR-CHAT-011 |
| TC-E2E-05-D | FR-CHAT-008, FR-CHAT-011 |
| TC-E2E-06-M | FR-THEME-002 |
| TC-E2E-06-T | FR-THEME-002 |
| TC-E2E-06-D | FR-THEME-002 |
| TC-E2E-07-M | FR-KG-004, FR-KG-005, FR-KG-006 |
| TC-E2E-07-T | FR-KG-004, FR-KG-005, FR-KG-006 |
| TC-E2E-07-D | FR-KG-004, FR-KG-005, FR-KG-006 |
| TC-E2E-08-M | FR-EXTRACT-001, FR-EXTRACT-002, FR-EXTRACT-003, FR-EXTRACT-004 |
| TC-E2E-08-T | FR-EXTRACT-001, FR-EXTRACT-002, FR-EXTRACT-003, FR-EXTRACT-004 |
| TC-E2E-08-D | FR-EXTRACT-001, FR-EXTRACT-002, FR-EXTRACT-003, FR-EXTRACT-004 |
| TC-E2E-09-M | FR-RESP-004, FR-RESP-005, FR-RESP-006, FR-RESP-007, FR-RESP-008, FR-RESP-009, FR-RESP-010, FR-RESP-011, FR-RESP-012 |
| TC-E2E-09-T | FR-RESP-003 |
| TC-E2E-09-D | FR-RESP-001, FR-RESP-002, FR-SHELL-001 |
| TC-E2E-SMOKE-01 | FR-SHELL-007 |
| TC-E2E-SMOKE-02 | FR-SHELL-001, FR-SHELL-003, FR-RESP-004 |
2.4 模块分布
| 模块 | TC 条数(含 E2E 拆分) |
|---|---|
| SHELL | 15 |
| THEME | 10 |
| SESSION | 18 |
| CHAT | 43 |
| RETRIEVAL | 7 |
| SOURCE | 7 |
| EXTRACT | 11 |
| KG | 13 |
| RESP | 13 |
| HEALTH | 8 |
| NFR(PRD §14) | 5 |
| E2E 主线/冒烟 | 29 |
| 合计 | 179 |
3. 执行说明
3.1 分层运行命令(TEST_PLAN §7)
# L1 后端单元(远端 plantai-bff conda 环境;A 组自测,T 复跑确认)
cd sdk && pytest tests -m unit -q
# L2 后端接口(respx mock 上游;用例见 L2 标注项)
cd sdk && pytest tests -m api -q
# L2s 上游 smoke(仅集成点 M2 与验收前手动各跑一次;远端本机执行)
bash tests/smoke_upstreams.sh
# L3+L4 前端(vitest;远端 ui/)
cd ui && npx vitest run
# L5 E2E(三档视口;dev server 由 playwright webServer 自动拉起或复用已启动的 5180)
cd ui && npx playwright test # playwright 未安装时:npx playwright@1.49.1 test
3.2 Mock 场景使用(ARCHITECTURE.md §6)
mock server:python sdk/mock/mock_server.py(127.0.0.1:8099),场景经查询参数或请求头 X-Mock-Scenario 切换。E2E 中由测试代码在请求头注入或 mock 路由拦截实现:
| scenario | 用途 | 使用用例示例 |
|---|---|---|
normal |
主流程(SSE 回放 12 帧真实时序) | TC-CHAT-023~033、TC-E2E-01/02 |
empty |
空结果(source_count=0、answer 为「未找到…」fallback) | TC-SOURCE-007、TC-KG-013、TC-CHAT-027(空态分支) |
slow |
慢响应/长流(持续视觉反馈断言) | TC-CHAT-021、TC-CHAT-029、TC-NFR-002 |
error |
上游故障(502 UPSTREAM_ERROR) | TC-CHAT-039、TC-E2E-03 |
degraded |
QA 不可用(503 UPSTREAM_DOWN) | TC-HEALTH-004/005、TC-EXTRACT-011、TC-KG-012、TC-E2E-03 |
注意:mock 的场景切换仅覆盖 QA 端点;extraction/kg 的 503 降级在 E2E 中用 Playwright route 拦截模拟。
3.3 真实上游注意事项(DISCOVERY.md)
- QA LLM 402 降级(最重要):上游 DeepSeek 余额不足,
degraded_execution=true,answer 为 fallback 证据列表而非自然语言答案。涉及自然语言答案内容的断言(TC-CHAT-027 等,标注「依赖充值」)在充值前执行时只验结构不断内容:answer 字段存在、text 块渲染、fallback 文案可见即可。检索/证据/来源/图谱断言(sources、chains、graph 块)不受 402 影响,照常执行。 - 耗时:单次 search ≈92s、stream ≈37–38s(DISCOVERY.md §4/§6.8)。真实上游的 L5/L6 用例需把 expect 超时调到 ≥180s(search 模式)/≥120s(chat 模式);BFF 读超时 300s。
- 上游只绑 127.0.0.1:L2s 必须在远端本机跑;Mac 本地经 SSH 隧道跑(见脚本注释)。
- Neo4j 当选实例 direct-v1-full(bolt 18788 / HTTP 18575),schema canonical;
/api/kg/*依赖 BFF 的 Bolt 直连(上游 kg 路由已死,不探测)。 - 抽取上游:8000 正常;7900 为容器(jobs 空属正常,BFF 只在 8000 不可达时回落);新上传任务可能因 MinerU 路径缺失 failed——TC-EXTRACT-008 就是断言该错误文案路径。
3.4 L5 运行环境一次性准备(已验证)
- Node 18(远端):
npx playwright@1.49.1 test首次运行自动下载 chromium 1148(≈150MB)。实测 CDN 可达(Mac 直连 2.9MB/s)。 @playwright/test模块解析:spec 文件位于tests/e2e/,在ui/node_modules之外,Node 默认解析路径找不到@playwright/test,会报ERR_MODULE_NOT_FOUND。已在 Mac 本地验证(playwright 1.61.1 实测复现;1.49.1 CJS 变换同样回退到默认 ESM 解析,机制相同)。运行处须一次性执行(不污染任何 agent 归属文件——node_modules不入库不同步):Mac 本地本次验证的等价做法(未改动# 远端,一次性 cd /home/xzq/5090/teamWorkspace/zh/PlantAI-rag-new ln -sfn ui/node_modules node_modules # 若目录已存在先确认其内容再覆盖 cd ui && npm install --save-dev @playwright/test@1.49.1 # 写入 package.json 需 PM 裁决,见 §5 未决问题 4ui/package.json):安装到/tmp/pw-test-runner后ln -sfn /tmp/pw-test-runner/node_modules/@playwright/test ui/node_modules/@playwright/test,再ln -sfn ui/node_modules <repo>/node_modules,以 playwright 1.61.1(匹配本机已缓存 chromium-1228)跑通 6/6。- 本地 Node 26 已知问题:playwright 1.49.1 的
module.register()loader 在 Node 26 + 系统高负载下启动极慢/挂起;远端 Node 18 无此问题。本地验证用 playwright 1.61.1 替代。 - 本机验证结果(M0 冒烟):
6 passed(mobile/tablet/desktop × 2 条冒烟)。冒烟断言对 B1 已交付的 AppShell 走真实分支(.app-shell/.top-bar/.status-bar,移动端.status-bar按 FR-RESP-004 断言隐藏),M0 占位期走占位回退分支。
4. E2E 骨架交付说明(本波)
| 文件 | 内容 |
|---|---|
ui/playwright.config.js |
三项目 mobile(iPhone 14 390×844,触摸+UA)/tablet(iPad 768×1024)/desktop(1440×900);chromium;baseURL http://127.0.0.1:5180;webServer npm run dev -- --strictPort(已有 dev 复用);失败保留 trace/screenshot |
tests/e2e/smoke.spec.js |
2 条冒烟(TC-E2E-SMOKE-01/02),三档视口各跑一次共 6 条结果。AppShell 断言带 M0 占位回退(B1 交付后自动走真实分支,无需改测试) |
tests/smoke_upstreams.sh |
L2s 冒烟:QA 7920 health/info、抽取 8000 health/jobs、7900 health、Neo4j(HTTP 18575 Cypher 只读查询)、mock 8099 health;PASS/FAIL 表 + 非零退出码;支持 QA_URL/EXTRACT_URL/ALT_URL/MOCK_URL/NEO4J_HTTP/TIMEOUT 环境变量覆盖 |
全量 L1–L5 执行从 M2 集成后开始(TEST_PLAN §5 轮次纪律);完整 E2E 用例(TC-E2E-01~09)按本文件在后续轮次落为 spec 文件。
5. 未决问题(提请 PM)
- 若干 UI 类断言依赖 UI_SPEC 类名(如
agent-dot-item、p-step);若 B1 实现时类名有偏差,需按 UI_SPEC §5.3 对齐(T 不自行改用例契约)。 - TC-EXTRACT-005/007(上传进度/超限)依赖 B2/B3 上传 UI 与 50MB 校验落点(前端或 BFF)——已按「前端拦截或 422」双路径写预期,无需改用例。
- TC-KG 节点详情在 Neo4j 不可用时的属性来源为「消息内 graph 块已有属性」;graph 块节点若不含属性字段,该断言在实现时需以实际块结构微调步骤(预期语义不变)。
- L5 依赖安装需 PM 裁决:
tests/e2e/的 spec 需要解析@playwright/test,而它位于ui/node_modules之外。两个方案二选一:(a) 远端一次性npm install --save-dev @playwright/test@1.49.1(写入 B1 归属的ui/package.json,需 PM 批准);(b) 保持npx playwright@1.49.1并在远端建node_modules根符号链接 +@playwright/test符号链接(不改 package.json,M2 前由 T/PM 在远端一次性执行)。本波按 (b) 在 Mac 本地验证通过(6/6 pass),建议远端集成点采用 (b)。 - task 验证命令差异:任务书给的验证命令
npx playwright test(无版本)在本机无已安装 playwright 时会从 npm 拉最新版;远端 Node 18 +npx playwright@1.49.1仍会拉 1.49.1 的 chromium 1148(≈150MB,CDN 实测可达)。已在本文件 §3.4 记录完整步骤。
6. 生信流程编排(FR-BIO-001~032)
本节由 T1 编制(阶段 0,2026-09-05)。需求唯一来源:PRD.md §16;组件规格:UI_SPEC.md §8;分层与门禁:TEST_PLAN.md §9-12;端点事实:实施计划 §六。意图分流词典唯一事实源:docs/team/cases_bioflow_intent.md(前后端同表双跑)。 编号 TC-BIO-<模块>-<序号>;E2E 视口后缀 M/T/D(390×844 / 768×1024 / 1440×900)。分层:L1 生信服务单元(pytest -m bioflow_unit)|L2 生信接口(pytest -m bioflow_api,mock LLM/vstore/docker)|L2s 生信冒烟(bash bioflow_kernel/tests/smoke_golden.sh,仅集成点手动)|L3 前端单元(vitest)|L4 前端组件(vitest + @vue/test-utils)|L5(Playwright 三档视口)。 可断言性:预期列均为可观察断言(HTTP 状态/请求体字段/存储值/元素存在/计算样式值/事件序列),无「检查是否正确」类断言。 模块缩写:INTENT 意图分流 | API 生信服务端点 | RUN runner 状态机 | KERN 内核执行与 manifest | SSE 事件流 | DB 三表迁移 | FLOW 上下游集成 | STORE 前端 store | PATH 路径卡 | FORM 参数表单卡 | FILE 文件引导卡 | PROG 进度卡 | ARCH 存档卡 | JOB 生信任务面板 | PANE 生信档案面板 | ACT UI 动作矩阵 | DEPLOY 三形态部署 | REG 回归 | GOLD 金标与发布 | E2E 端到端主线。
6.1 用例清单
6.1.1 INTENT 意图分流(FR-BIO-001/FR-BIO-023/FR-BIO-026,词典唯一事实源 docs/team/cases_bioflow_intent.md)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-BIO-INTENT-001 | FR-BIO-001 | 命中「帮我跑水稻 SPL 家族鉴定」 | 无附件、无活动文档 | route("帮我跑水稻 SPL 家族鉴定") | 返回 bioflow(词典用例表第 1 条) | L3 | P0 |
| TC-BIO-INTENT-002 | FR-BIO-001 | 命中「跑一下拟南芥 MADS-box 家族分析」 | 无附件、无活动文档 | route("跑一下拟南芥 MADS-box 家族分析") | 返回 bioflow | L3 | P0 |
| TC-BIO-INTENT-003 | FR-BIO-001 | 命中「请帮我鉴定水稻 SPL 家族」 | 无附件 | route("请帮我鉴定水稻 SPL 家族") | 返回 bioflow | L3 | P0 |
| TC-BIO-INTENT-004 | FR-BIO-001 | 命中「识别玉米 bZIP 家族成员」 | 无附件 | route("识别玉米 bZIP 家族成员") | 返回 bioflow | L3 | P0 |
| TC-BIO-INTENT-005 | FR-BIO-001 | 命中「帮我研究一下水稻 SPL 基因家族」 | 无附件 | route("帮我研究一下水稻 SPL 基因家族") | 返回 bioflow | L3 | P0 |
| TC-BIO-INTENT-006 | FR-BIO-001 | 命中「分析小麦 WRKY 转录因子家族」 | 无附件 | route("分析小麦 WRKY 转录因子家族") | 返回 bioflow | L3 | P0 |
| TC-BIO-INTENT-007 | FR-BIO-001 | 命中「做个大豆 NAC 家族分析」 | 无附件 | route("做个大豆 NAC 家族分析") | 返回 bioflow | L3 | P0 |
| TC-BIO-INTENT-008 | FR-BIO-001 | 命中「跑 SPL 家族」 | 无附件 | route("跑 SPL 家族") | 返回 bioflow | L3 | P0 |
| TC-BIO-INTENT-009 | FR-BIO-001 | 命中「水稻 SPL 家族,帮我跑」 | 无附件 | route("水稻 SPL 家族,帮我跑") | 返回 bioflow | L3 | P0 |
| TC-BIO-INTENT-010 | FR-BIO-001 | 命中「基因家族鉴定:水稻 SPL」 | 无附件 | route("基因家族鉴定:水稻 SPL") | 返回 bioflow | L3 | P0 |
| TC-BIO-INTENT-011 | FR-BIO-001 | 漏判安全:知识问答 | 无附件 | route("什么是基因家族?") | 返回 qa | L3 | P0 |
| TC-BIO-INTENT-012 | FR-BIO-001 | 漏判安全:光有动词 | 无附件 | route("帮我跑一下") | 返回 qa | L3 | P0 |
| TC-BIO-INTENT-013 | FR-BIO-001 | 漏判安全:光有家族名 | 无附件 | route("SPL 家族") | 返回 qa | L3 | P0 |
| TC-BIO-INTENT-014 | FR-BIO-001 | 漏判安全:无动词无家族 | 无附件 | route("今天天气不错") | 返回 qa | L3 | P1 |
| TC-BIO-INTENT-015 | FR-BIO-001 | 漏判安全:问方法 | 无附件 | route("跑 SPL 家族鉴定需要准备什么输入?") | 返回 qa | L3 | P0 |
| TC-BIO-INTENT-016 | FR-BIO-001 | 漏判安全:非生信对象 | 无附件 | route("帮我跑一个数据分析") | 返回 qa | L3 | P1 |
| TC-BIO-INTENT-017 | FR-BIO-001 | 漏判安全:闲聊 | 无附件 | route("你好呀") | 返回 qa | L3 | P1 |
| TC-BIO-INTENT-018 | FR-BIO-001 | 漏判安全:空字符串 | 无附件 | route("") | 返回 qa | L3 | P1 |
| TC-BIO-INTENT-019 | FR-BIO-001 | 漏判安全:纯空白 | 无附件 | route(" ") | 返回 qa | L3 | P1 |
| TC-BIO-INTENT-020 | FR-BIO-001 | 漏判安全:乱码 | 无附件 | route("⚡☂☄ hmm") | 返回 qa(非 bioflow) | L3 | P2 |
| TC-BIO-INTENT-021 | FR-BIO-001 | 漏判安全:未在词典的家族名 | 无附件 | route("帮我跑香蕉 XYK 家族鉴定") | 返回 qa(XYK 不在家族词典) | L3 | P1 |
| TC-BIO-INTENT-022 | FR-BIO-001 | 边界:大小写家族名 | 无附件 | route("跑水稻 spl 家族鉴定") | 返回 bioflow(家族名大小写不敏感) | L3 | P1 |
| TC-BIO-INTENT-023 | FR-BIO-001 | 边界:英文整句 | 无附件 | route("Please run rice SPL family identification") | 返回 bioflow | L3 | P1 |
| TC-BIO-INTENT-024 | FR-BIO-001 | 边界:标点夹杂 | 无附件 | route("帮我跑(水稻 SPL 家族)鉴定!") | 返回 bioflow | L3 | P1 |
| TC-BIO-INTENT-025 | FR-BIO-001 | 边界:超长文本(>200 字) | 无附件 | route(200 字长文含「跑水稻 SPL 家族鉴定」在末尾) | 返回 bioflow | L3 | P2 |
| TC-BIO-INTENT-026 | FR-BIO-001 | 边界:家族名跨词干扰 | 无附件 | route("这个 SPL 会议帮我跑一下流程") | 返回 qa(SPL 后无家族/分析对象词) | L3 | P2 |
| TC-BIO-INTENT-027 | FR-BIO-001 | 附件存在不改判定 | has_attachments=true | route("帮我跑水稻 SPL 家族鉴定") | 返回 bioflow | L3 | P1 |
| TC-BIO-INTENT-028 | FR-BIO-001 | 活动文档存在不改判定 | has_active_artifact=true | route("帮我跑水稻 SPL 家族鉴定") | 返回 bioflow | L3 | P1 |
| TC-BIO-INTENT-029 | FR-BIO-001 | docgen 优先:写报告 | 无附件、无活动文档 | route("帮我生成一份水稻 SPL 家族分析报告") | 返回 docgen(既有 docgen 路由在 bioflow 之前判定) | L3 | P0 |
| TC-BIO-INTENT-030 | FR-BIO-001 | docgen 优先:撰写论文 | 无附件 | route("帮我写一篇水稻基因家族研究论文") | 返回 docgen | L3 | P1 |
| TC-BIO-INTENT-031 | FR-BIO-001 | export 优先 | has_active_artifact=true | route("导出成 PDF") | 返回 export | L3 | P1 |
| TC-BIO-INTENT-032 | FR-BIO-001 | edit 优先:文档打开时改文字 | has_active_artifact=true | route("把这句话改成红色") | 返回 edit | L3 | P1 |
| TC-BIO-INTENT-033 | FR-BIO-019 | 图表调整走 bioflow:文档打开时 | has_active_artifact=true | route("xxx 图表颜色换成红色") | 返回 bioflow(图表类词命中生信,不进 edit) | L3 | P0 |
| TC-BIO-INTENT-034 | FR-BIO-023 | 存档复用命中:标准句式 | 无附件 | route("用 XXX 存档任务的方法帮我跑水稻 SPL 家族鉴定") | 返回 bioflow 且解析出复用意图(方法名=XXX) | L3 | P0 |
| TC-BIO-INTENT-035 | FR-BIO-023 | 存档复用命中:根据句式 | 无附件 | route("根据 XXX 存档任务的方法帮我跑一下玉米 bZIP") | 返回 bioflow 且复用意图成立 | L3 | P1 |
| TC-BIO-INTENT-036 | FR-BIO-023 | 存档复用命中:参考句式 | 无附件 | route("参考 XXX 存档的方法再跑一个水稻 SPL") | 返回 bioflow 且复用意图成立 | L3 | P1 |
| TC-BIO-INTENT-037 | FR-BIO-023 | 存档复用命中:按句式中文括号 | 无附件 | route("用《XXX》存档任务的方法帮我跑小麦 WRKY 家族") | 返回 bioflow 且方法名=XXX | L3 | P1 |
| TC-BIO-INTENT-038 | FR-BIO-023 | 存档复用边界:只有复用词无任务词 | 无附件 | route("用 XXX 存档任务的方法") | 返回 qa(无「帮我跑 xxxx」目标) | L3 | P1 |
| TC-BIO-INTENT-039 | FR-BIO-023 | 存档复用边界:无家族对象 | 无附件 | route("用 XXX 存档任务的方法帮我跑 yyy") | 返回 qa(yyy 无家族名匹配,漏判安全) | L3 | P1 |
| TC-BIO-INTENT-040 | FR-BIO-001 | 标点与空白容错 | 无附件 | route("帮我跑 水稻 SPL 家族 鉴定") | 返回 bioflow | L3 | P2 |
| TC-BIO-INTENT-041 | FR-BIO-001 | 命中 RNA-seq | 无附件 | route("帮我跑水稻叶片 RNA-seq 差异表达分析") | 返回 bioflow | L3 | P0 |
| TC-BIO-INTENT-042 | FR-BIO-001 | 命中 WGS | 无附件 | route("帮我做水稻全基因组变异检测") | 返回 bioflow | L3 | P1 |
| TC-BIO-INTENT-043 | FR-BIO-001 | 命中 GWAS | 无附件 | route("帮我跑水稻产量性状 GWAS 关联分析") | 返回 bioflow | L3 | P1 |
| TC-BIO-INTENT-044 | FR-BIO-001 | 交互式补充未命中(词典无此规则,漏判安全) | 会话上文为「帮我跑水稻 SPL 家族鉴定」已开任务 | route("换玉米,重跑") | 返回 qa(TL 2026-09-06 修订:与冻结词典一致;「换物种重跑」交互式补充转 P7 增强项) | L3 | P2 |
| TC-BIO-INTENT-045 | FR-BIO-026 | 流程咨询在生信流内 | 会话已有生信任务 | route("identify 需要什么输入") | 返回 bioflow 内 flow_qa 路径(不新建任务) | L3 | P1 |
| TC-BIO-INTENT-046 | FR-BIO-001 | 命中句不打乱 QA 流 | 无生信上下文 | 先 route("什么是 SPL 家族") 再 route("帮我跑水稻 SPL 家族鉴定") | 第 1 条=qa、第 2 条=bioflow,两者互不影响 | L3 | P2 |
| TC-BIO-INTENT-047 | FR-BIO-001 | 词典同表后端一致性 | 后端 bioflow_service 已部署 | 后端对词典用例表 40+ 条输入逐一分流 | 后端判定结果与词典期望逐条一致(同表双跑) | L2 | P0 |
6.1.2 API 生信服务端点(实施计划 §六 20 端点;mock LLM/vstore/docker)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-BIO-API-001 | FR-BIO-001 | chat/stream 入口建立 SSE | mock LLM/vstore | POST /api/bioflow/chat/stream {"session_id":"s1","message":"帮我跑水稻 SPL 家族鉴定"} 流式读首个事件 | 响应 200;Content-Type=text/event-stream;首个事件类型=job_created(或 plan_ready),data 为 JSON | L2 | P0 |
| TC-BIO-API-002 | FR-BIO-002 | 候选路径随 plan_ready 下发 | mock LLM 返回 3 条候选路径 | 读流至 plan_ready 事件 | plan_ready.data.candidates 为数组,length 在 2~3;每条含 stages[](非空)与 purpose(非空字符串) | L2 | P0 |
| TC-BIO-API-003 | FR-BIO-003 | 伪造阶段被拒 | mock LLM 候选含未知阶段「fake_stage_xyz」 | 读流至第 1 个 plan/error 事件 | 事件 data 含 code=UNKNOWN_STAGE 且 fake_stage_xyz 被点名;该候选不进入候选集 | L2 | P0 |
| TC-BIO-API-004 | FR-BIO-003 | 前置阶段自动补全 | 候选链缺 identify 前置 | 读流至 plan_ready | 事件 data.candidates[*].stages 已含前置;data 或后续事件文本含「已自动补全」明示字段 auto_filled[]=前置阶段名 | L2 | P0 |
| TC-BIO-API-005 | FR-BIO-001 | 非生信消息不建任务 | mock LLM 分流 | POST 消息「什么是基因家族」读流 | 响应 200;事件含 message_done 且不含 job_created;data 不含 job_id | L2 | P0 |
| TC-BIO-API-006 | FR-BIO-001 | 空 message 422 | 无 | POST {"session_id":"s1","message":""} | 422;detail 含 message 字段错误 | L2 | P1 |
| TC-BIO-API-007 | FR-BIO-001 | 缺 message 字段 422 | 无 | POST {"session_id":"s1"} | 422;detail 含 message | L2 | P1 |
| TC-BIO-API-008 | FR-BIO-001 | 缺 session_id 422 | 无 | POST {"message":"帮我跑水稻 SPL 家族鉴定"} | 422;detail 含 session_id | L2 | P1 |
| TC-BIO-API-009 | FR-BIO-001 | LLM 超时降级 | mock LLM 延迟超过上限 | 读流至第 1 个事件 | 事件 data 含 code=PLAN_LLM_TIMEOUT 的降级提示;SSE 正常关闭 | L2 | P1 |
| TC-BIO-API-010 | FR-BIO-001 | vstore 不可用降级 | mock vstore 返回 500 | 读流至 plan_ready | plan_ready 正常返回(LLM 直接候选);data.source 标记=llm_only;无 5xx 中断 | L2 | P1 |
| TC-BIO-API-011 | FR-BIO-023 | 存档复用句式接口路径 | 归档「XXX」存在且含参数 | POST message「用 XXX 存档任务的方法帮我跑玉米 bZIP」读流至 job_created | job_created.data.reused_archive=XXX;bio_jobs 行参数=存档参数 | L2 | P0 |
| TC-BIO-API-012 | FR-BIO-026 | 流程咨询接口路径 | 任务已存在 | POST message「identify 需要什么输入」读流 | 事件含 message_done;data.citations[] 含来源文件+章节;不产生新 job_created | L2 | P0 |
| TC-BIO-API-013 | FR-BIO-014 | 断流时任务不回滚 | mock docker 慢 | 流中途关闭客户端 | 任务在 DB 仍 in-flight;重连 events 接口可回放 | L2 | P1 |
| TC-BIO-API-014 | FR-BIO-001 | 客户端断开清理 | 任务尚未创建 | 收到首个字节后立即断开 | 服务端无未捕获异常;资源释放(无连接泄漏,服务存活) | L2 | P2 |
| TC-BIO-API-015 | FR-BIO-001 | 超长消息拒绝 | 无 | POST message=100001 字符 | 422(max_length 超限)或 400;不触发 LLM 调用 | L2 | P1 |
| TC-BIO-API-016 | FR-BIO-031 | 并发 chat 上限 | 已有 3 个 in-flight 任务 | 再发起第 4 个任务型消息 | 第 4 个任务不立即执行;事件 data 含 queued=true 或状态=queued | L2 | P0 |
| TC-BIO-API-017 | FR-BIO-014 | 断线重连回放快照 | 任务含 3 阶段(1 done 1 running 1 waiting) | GET /api/bioflow/jobs/{id}/events 首帧 | 首帧 data 为任务快照:stages 数组=3、每阶段含 status;无 stage_* 事件丢失 | L2 | P0 |
| TC-BIO-API-018 | FR-BIO-001 | 事件包含 plan_ready 后必有确认点 | 候选路径选定 | 读事件序列 | 序列中出现 stage_await_confirm(或 plan_ready);事件顺序由 seq 严格递增 | L2 | P1 |
| TC-BIO-API-019 | FR-BIO-001 | chat/stream 400 请求体非 JSON | 无 | POST body="not-json" Content-Type: application/json | 400 或 422 | L2 | P2 |
| TC-BIO-API-020 | FR-BIO-001 | LLM 完全不可用 | mock LLM 连接拒绝 | 读流至第 1 个事件 | 事件 data 含 code=PLAN_UNAVAILABLE;SSE 关闭;无 job 落库 | L2 | P1 |
| TC-BIO-API-021 | FR-BIO-002 | catalog 返回全部阶段(与权威数据一致) | 服务正常 | GET /api/bioflow/catalog | 200;data.stages 数组 length 与 bioflow_kernel/stage_image_map.json v2.0.0 的 stages 数一致(TL 2026-09-06 修订:当前 75,原 73 为 dev 旧树口径);每项含 name/description/params/inputs/outputs | L2 | P0 |
| TC-BIO-API-022 | FR-BIO-002 | catalog 基因家族链全部阶段(与权威数据一致) | 无 | GET /api/bioflow/catalog?chain=gene_family | 200;返回项数与 stage_image_map.json 的 family_chain 一致(TL 2026-09-06 修订:当前 21,原 18 为 dev 旧树口径);name 集合与 family_chain 一致 | L2 | P0 |
| TC-BIO-API-023 | FR-BIO-002 | catalog 参数 schema | 无 | GET /api/bioflow/catalog?stage=identify | 返回 identify 项;params[] 每项含 name/type/default/source/help;inputs 含 fasta/hmm 类 | L2 | P0 |
| TC-BIO-API-024 | FR-BIO-002 | catalog 未知阶段 404 | 无 | GET /api/bioflow/catalog?stage=nope | 404 信封 code=NOT_FOUND | L2 | P1 |
| TC-BIO-API-025 | FR-BIO-002 | catalog 镜像映射字段 | 无 | GET /api/bioflow/catalog?stage=identify | 该项 image 字段=bioflow-gf(与 stage_image_map.json 一致) | L2 | P1 |
| TC-BIO-API-026 | FR-BIO-002 | catalog 缓存无效时重载 | 修改 catalog 源后 | GET /api/bioflow/catalog | 返回新数据(无服务重启);ETag 或 Last-Modified 变化 | L2 | P2 |
| TC-BIO-API-027 | FR-BIO-004 | POST jobs 创建任务 | 候选链已选定 | POST /api/bioflow/jobs {"session_id":"s1","title":"SPL 鉴定","stages":["identify","align","phylogeny"],"params":{}} | 201;body 含 id/uuid、title、status=created、stages 数组 3 项(status=waiting) | L2 | P0 |
| TC-BIO-API-028 | FR-BIO-004 | POST jobs 缺 stages 422 | 无 | POST {"session_id":"s1","title":"t"} | 422;detail 含 stages | L2 | P1 |
| TC-BIO-API-029 | FR-BIO-023 | POST jobs 复用归档 | 归档 a1 含阶段链+参数 | POST {"session_id":"s1","archive_id":"a1"} | 201;body.stages=归档阶段链;params=归档参数;bio_archives 行 reused_count+1 | L2 | P0 |
| TC-BIO-API-030 | FR-BIO-004 | POST jobs 未知 stage 拒绝 | 无 | POST {"stages":["ghost_stage"]} | 422/400;detail 点名 ghost_stage 不在 catalog | L2 | P1 |
| TC-BIO-API-031 | FR-BIO-004 | POST jobs 缺 session_id 422 | 无 | POST {"title":"t","stages":["identify"]} | 422;detail 含 session_id | L2 | P1 |
| TC-BIO-API-032 | FR-BIO-024 | GET jobs 列表 | 库中 3 个任务 | GET /api/bioflow/jobs | 200;data.items length=3;按 created_at 倒序;每项含 id/title/status/progress | L2 | P0 |
| TC-BIO-API-033 | FR-BIO-024 | GET jobs 分页 | 25 个任务 | GET /api/bioflow/jobs?page=2&page_size=10 | 200;items length=10;total=25 | L2 | P1 |
| TC-BIO-API-034 | FR-BIO-024 | GET job 详情 | 任务含 3 阶段 | GET /api/bioflow/jobs/{id} | 200;body.stages length=3 且各含 stage/status/params;progress 为数字 0-100 | L2 | P0 |
| TC-BIO-API-035 | FR-BIO-024 | GET job 404 | 无 | GET /api/bioflow/jobs/not-exist | 404 信封 code=NOT_FOUND | L2 | P1 |
| TC-BIO-API-036 | FR-BIO-024 | 任务阶段子资源 | 任务 j1 | GET /api/bioflow/jobs/{j1}/stages | 200;数组与任务阶段一致,含每阶段开始/结束时间 | L2 | P1 |
| TC-BIO-API-037 | FR-BIO-024 | DELETE job | 任务 j1 | DELETE /api/bioflow/jobs/{j1} | 204;GET 后 404;bio_stages 级联删除 | L2 | P1 |
| TC-BIO-API-038 | FR-BIO-024 | DELETE 进行中任务 | 任务 running | DELETE /api/bioflow/jobs/{id} | 409 信封 code=JOB_RUNNING(拒绝) | L2 | P1 |
| TC-BIO-API-039 | FR-BIO-006 | POST files 上传 | 任务 j1 起始阶段 await_files | POST /api/bioflow/jobs/{j1}/files multipart file=test.fa | 200;body 含 file_id/name/size=测试文件字节数/path 以 /job/{j1}/input/ 开头 | L2 | P0 |
| TC-BIO-API-040 | FR-BIO-006 | 上传写入任务目录 | 同上 | 上传后读服务器文件系统 | 文件存在于任务 input 目录;内容字节与上传一致 | L2 | P0 |
| TC-BIO-API-041 | FR-BIO-006 | 大文件流式上传 | 456MB fixture | 上传并统计内存峰值 | 200;服务端内存峰值 < 200MB(流式不整读) | L2 | P0 |
| TC-BIO-API-042 | FR-BIO-007 | 路径登记合法 | 任务 j1 | POST /api/bioflow/jobs/{j1}/files {"server_path":"/home/xzq/5090/teamWorkspace/zh/bioflow-data/examples/SPL.fa"} | 200;body 含登记记录 path;GET files 列表可见;无文件复制(path 指向原位) | L2 | P0 |
| TC-BIO-API-043 | FR-BIO-007 | 路径登记不存在文件 | 无 | POST files {"server_path":"/nonexistent/x.fa"} | 400 信封 code=PATH_NOT_EXIST;无登记记录 | L2 | P0 |
| TC-BIO-API-044 | FR-BIO-007 | 路径登记目录而非文件 | 无 | POST files {"server_path":"/tmp"} | 400 信封 code=NOT_A_FILE | L2 | P1 |
| TC-BIO-API-045 | FR-BIO-007 | 路径登记非白名单根 | 无 | POST files {"server_path":"/etc/passwd"} | 403 信封 code=PATH_NOT_ALLOWED(限 BIOFLOW_DATA_ROOT/任务目录内) | L2 | P0 |
| TC-BIO-API-046 | FR-BIO-006 | 上传类型限制 | 任务 j1 | 上传 file.exe(扩展名不在白名单) | 422;detail 指明扩展名不允 | L2 | P1 |
| TC-BIO-API-047 | FR-BIO-006 | 上传大小上限 | 任务 j1 | 上传超过上限的 fixture | 413;detail 含 max_size 与实到字节数 | L2 | P1 |
| TC-BIO-API-048 | FR-BIO-006 | GET files 列表 | 任务 j1 已登记 2 文件 | GET /api/bioflow/jobs/{j1}/files | 200;items length=2;每项含 name/path/size/registered_at;含服务器路径登记项 source=server_path | L2 | P0 |
| TC-BIO-API-049 | FR-BIO-006 | 上传完成事件 | 任务 j1 await_files | 上传满足阶段输入 | 后续事件流出现 stage_started(该阶段不再 await_files);bio_stages 状态=waiting_confirm 或 running | L2 | P0 |
| TC-BIO-API-050 | FR-BIO-006 | 上传失败不登记 | mock 磁盘写失败 | 上传 | 500 信封;files 列表不含该文件 | L2 | P2 |
| TC-BIO-API-051 | FR-BIO-006 | 同文件重复上传 | 已上传 a.fa | 再次上传同名 a.fa | 200;新 file_id;input 目录 a.fa 被覆盖(或 409 按实现断言其一,二选一固定) | L2 | P1 |
| TC-BIO-API-052 | FR-BIO-006 | 多文件并发上传 | 任务 j1 | 并发 3 个 multipart 上传 | 3 个均 200;files 列表 length=3;无文件交错损坏(各 size 与源一致) | L2 | P1 |
| TC-BIO-API-053 | FR-BIO-006 | 中文文件名 | 任务 j1 | 上传「水稻基因组.fa」 | 200;files 列表 name=水稻基因组.fa 且 URL 编码取回正确 | L2 | P2 |
| TC-BIO-API-054 | FR-BIO-006 | 空文件上传 | 任务 j1 | 上传 0 字节文件 | 200 且 size=0(或 422 按实现断言其一,二选一固定) | L2 | P2 |
| TC-BIO-API-055 | FR-BIO-006 | GET files 单文件内容 | 已上传 a.fa | GET /api/bioflow/jobs/{j1}/files/{file_id}/content | 200;Content-Type 与文件一致;body 字节与源一致 | L2 | P1 |
| TC-BIO-API-056 | FR-BIO-008 | confirm 发起执行 | 阶段 identify 状态 waiting_confirm | POST /api/bioflow/jobs/{j1}/stages/identify/confirm {"params":{"cpu":8}} | 200;body.status=running;bio_stages 参数已存 cpu=8 | L2 | P0 |
| TC-BIO-API-057 | FR-BIO-009 | confirm 参数覆盖 | 默认参数 cpu=4 | POST confirm {"params":{"cpu":16}} | 后续 mock docker 命令含 --cpu 16(非 4);stage 执行用新值 | L2 | P0 |
| TC-BIO-API-058 | FR-BIO-008 | confirm 拒绝非 schema 参数 | 无 | POST confirm {"params":{"magic":"x"}} | 422;detail 含 magic 未知参数 | L2 | P1 |
| TC-BIO-API-059 | FR-BIO-009 | 重复 confirm 幂等 | 阶段已 running | 再次 POST confirm | 409 信封 code=STAGE_NOT_CONFIRMABLE | L2 | P1 |
| TC-BIO-API-060 | FR-BIO-009 | confirm 未知阶段 | 无 | POST /stages/nope/confirm | 404 信封 | L2 | P1 |
| TC-BIO-API-061 | FR-BIO-009 | confirm 非等待态 | 阶段 done | POST confirm | 409 信封 code=INVALID_STAGE_TRANSITION | L2 | P1 |
| TC-BIO-API-062 | FR-BIO-012 | rerun 失败阶段 | 阶段 failed | POST /api/bioflow/jobs/{j1}/stages/{st}/rerun | 200;状态=running 或 waiting_confirm(rerun_with_params);bio_stages 新增 attempt 记录 | L2 | P0 |
| TC-BIO-API-063 | FR-BIO-012 | rerun 带新参数 | 阶段 failed | POST rerun {"params":{"cpu":2}} | mock docker 命令含 --cpu 2;成功后状态=done | L2 | P0 |
| TC-BIO-API-064 | FR-BIO-012 | rerun 非 failed 409 | 阶段 done | POST rerun | 409 信封 code=STAGE_NOT_FAILED | L2 | P1 |
| TC-BIO-API-065 | FR-BIO-012 | skip 失败阶段 | 阶段 failed | POST /api/bioflow/jobs/{j1}/stages/{st}/skip | 200;状态=skipped;事件流出现 stage_skipped | L2 | P0 |
| TC-BIO-API-066 | FR-BIO-012 | skip 非 failed 409 | 阶段 running | POST skip | 409 信封 | L2 | P1 |
| TC-BIO-API-067 | FR-BIO-010 | pause 生效 | 任务 2/5 阶段 running | POST /api/bioflow/jobs/{j1}/pause | 200;状态=paused;事件 job_paused;当前阶段不启新 docker | L2 | P0 |
| TC-BIO-API-068 | FR-BIO-010 | pause 已完成任务 409 | 任务 done | POST pause | 409 信封 code=JOB_NOT_RUNNING | L2 | P1 |
| TC-BIO-API-069 | FR-BIO-010 | resume 继续 | 任务 paused | POST /api/bioflow/jobs/{j1}/resume | 200;状态=running;等待确认的阶段回到 waiting_confirm(不跳过确认) | L2 | P0 |
| TC-BIO-API-070 | FR-BIO-010 | resume 非 paused 409 | 任务 created | POST resume | 409 信封 | L2 | P1 |
| TC-BIO-API-071 | FR-BIO-011 | manifest+日志尾 | 阶段 identify done | GET /api/bioflow/jobs/{j1}/stages/identify/manifest | 200;body 含 manifest 对象与 log_tail 字符串;log_tail 行数≤80 | L2 | P0 |
| TC-BIO-API-072 | FR-BIO-011 | manifest 日志恰好 80 行边界 | 日志 80 行 fixture | GET manifest | log_tail 行数=80 且含第 1 行与第 80 行 | L2 | P1 |
| TC-BIO-API-073 | FR-BIO-011 | 日志超 80 行截尾 | 日志 200 行 fixture | GET manifest | log_tail 行数=80 且为最后 80 行(第 1 行=原第 121 行) | L2 | P1 |
| TC-BIO-API-074 | FR-BIO-011 | manifest 404 | 未执行阶段 | GET .../stages/nope/manifest | 404 信封 | L2 | P1 |
| TC-BIO-API-075 | FR-BIO-011 | manifest 判成败字段 | 阶段失败 fixture | GET manifest | body.manifest.status 存在且为 failed;log_tail 含报错行 | L2 | P0 |
| TC-BIO-API-076 | FR-BIO-011 | 日志尾含 ANSI 色码清洗 | 日志含 \x1b[31m | GET manifest | log_tail 不含原始转义序列(已清洗或原样两态断言其一) | L2 | P2 |
| TC-BIO-API-077 | FR-BIO-014 | events SSE 全事件序列 | mock 任务跑通 3 阶段 | GET /api/bioflow/jobs/{j1}/events 收集全部事件 | 事件序列=job_created→plan_ready→stage_started→stage_log(≥1)→stage_await_confirm→stage_done(×3 阶段)→job_done;seq 严格递增 | L2 | P0 |
| TC-BIO-API-078 | FR-BIO-014 | events 断线重连回放 | 任务 3 阶段(1 done 1 running 1 waiting) | GET events | 首帧快照后按事件序补齐历史:stage_done(第 1 阶段)必回放;不含重复 stage_done | L2 | P0 |
| TC-BIO-API-079 | FR-BIO-014 | events 单阶段过滤 | 任务多阶段 | GET /api/bioflow/jobs/{j1}/events?stage=identify | 仅 identify 的事件;不含其他阶段事件 | L2 | P1 |
| TC-BIO-API-080 | FR-BIO-014 | events 心跳保活 | 任务运行中无新事件 | 等待 2×心跳间隔 | 收到至少 1 条 :keepalive 注释行;连接未断 | L2 | P1 |
| TC-BIO-API-081 | FR-BIO-014 | events job_done 后关闭 | 任务 done | 读流至 job_done | 收到 job_done 后服务端正常关闭连接 | L2 | P1 |
| TC-BIO-API-082 | FR-BIO-014 | events 客户端断开清理 | 任务运行中 | 断开 events 连接 | 订阅者计数回落;服务无泄漏(再连正常) | L2 | P2 |
| TC-BIO-API-083 | FR-BIO-014 | events 事件 id 递增 | 任务运行中 | 读全部事件 | 每个事件 data.seq 比前一事件 +1,无重复 seq | L2 | P1 |
| TC-BIO-API-084 | FR-BIO-019 | revise 重跑绘图阶段 | 报告任务含绘图阶段 plot_heatmap | POST /api/bioflow/report/{job_id}/revise {"target":"图1 颜色","instruction":"红色","params":{"color":"red"}} | 200;body 含 rerun_stage=plot_heatmap;该阶段 attempt+1 且状态=running | L2 | P0 |
| TC-BIO-API-085 | FR-BIO-019 | revise 后新图回填 | 绘图阶段重跑完成 | 轮询 job 状态至 done;GET report | 报告 HTML 中对应图 fig://id 的 base64 内容变化(与 revise 前不同) | L2 | P0 |
| TC-BIO-API-086 | FR-BIO-019 | revise 纯文字指令走 docgen | 报告已登记 | POST revise {"instruction":"首段字号加大"}(无图表目标) | 不触发绘图阶段重跑;调用报告编辑链路(docgen);报告文字更新 | L2 | P1 |
| TC-BIO-API-087 | FR-BIO-020 | 存档 POST | 任务 done 含报告 | POST /api/bioflow/archives {"job_id":"j1","name":"SPL 水稻鉴定","description":"...","include_intermediate":true} | 201;body 含 id/name/disk_path/size_bytes>0;磁盘路径目录存在且含 report.html | L2 | P0 |
| TC-BIO-API-088 | FR-BIO-020 | 存档名称缺失 422 | 任务 done | POST {"job_id":"j1"} | 422;detail 含 name | L2 | P1 |
| TC-BIO-API-089 | FR-BIO-020 | 放弃存档不调接口 | 前端已出提示 | 点击放弃后观察网络 | 无 POST /api/bioflow/archives 请求 | L4 | P1 |
| TC-BIO-API-090 | FR-BIO-022 | GET archives 列表 | 3 个归档 | GET /api/bioflow/archives | 200;items length=3 按 created_at 倒序;每项含 name/description/size/disk_path | L2 | P0 |
| TC-BIO-API-091 | FR-BIO-022 | GET archive 详情 | 归档 a1 | GET /api/bioflow/archives/{a1} | 200;含 stages 链、params、report_artifact、文件清单 | L2 | P0 |
| TC-BIO-API-092 | FR-BIO-022 | DELETE archive | 归档 a1 | DELETE /api/bioflow/archives/{a1} | 204;磁盘目录删除;GET 后 404 | L2 | P1 |
| TC-BIO-API-093 | FR-BIO-022 | DELETE archive 404 | 无 | DELETE /api/bioflow/archives/nope | 404 信封 | L2 | P1 |
| TC-BIO-API-094 | FR-BIO-023 | archive run 复用发起 | 归档 a1 | POST /api/bioflow/archives/{a1}/run {"session_id":"s1","target":"玉米 bZIP"} | 201;新任务 job_id 返回;stages=归档链;params 预填归档值 | L2 | P0 |
| TC-BIO-API-095 | FR-BIO-023 | 名称精确匹配优先 | 归档「SPL」与「SPL2」 | POST archives/run {"name":"SPL"} | 命中 SPL(精确优先) | L2 | P1 |
| TC-BIO-API-096 | FR-BIO-023 | 名称模糊候选 | 归档「水稻SPL」 | POST archives/run {"name":"SPL 水稻"} | 返回候选列表(≥1)且不含无关归档 | L2 | P1 |
| TC-BIO-API-097 | FR-BIO-023 | 复用无匹配 404 | 无 | POST archives/run {"name":"不存在"} | 404 信封 code=ARCHIVE_NOT_FOUND | L2 | P1 |
| TC-BIO-API-098 | FR-BIO-020 | 重名归档 409 | 已有归档名「X」 | POST archives {"name":"X"} | 409 信封(或 201 自动去重两态断言其一) | L2 | P2 |
| TC-BIO-API-099 | FR-BIO-025 | health 探活 | 服务运行 | GET /api/bioflow/health | 200;body 含 status=ok 与 db 连通状态字段 | L2 | P0 |
| TC-BIO-API-100 | FR-BIO-028 | BFF 反代开关开启态 | BIOFLOW_ENABLED=true | GET http://BFF/api/bioflow/health | 200 且响应体=直连 8098 响应体 | L2 | P0 |
| TC-BIO-API-101 | FR-BIO-028 | BFF 反代开关关闭态 | BIOFLOW_ENABLED=false | GET http://BFF/api/bioflow/health | 404(路由未注册) | L2 | P0 |
| TC-BIO-API-102 | FR-BIO-028 | 反代 SSE 透传不缓冲 | BFF 反代开启;任务运行 | 经 BFF 连 events 测首字节延迟 | 首帧到达延迟与直连差 <500ms;流连续无缓冲合并 | L2 | P0 |
| TC-BIO-API-103 | FR-BIO-028 | BFF 停而生信服务直连可用 | BFF 停止(mock) | 直连 GET :8098/api/bioflow/health | 200;任务可继续(GET jobs 正常) | L2 | P0 |
| TC-BIO-API-104 | FR-BIO-015 | 报告登记端点 | 任务 done 报告在任务目录 | BFF 调用报告登记(字段 job_id/标题/md/图清单) | doc_artifacts 表出现新行;字段与 docgen 报告表对齐 | L2 | P0 |
| TC-BIO-API-105 | FR-BIO-006 | 反代上传超时单独调大 | BFF 反代开启 | 经 BFF 上传 456MB fixture | 200;无 502/504;服务端统计耗时正常 | L2 | P1 |
| TC-BIO-API-106 | FR-BIO-007 | 路径登记经 BFF 反代 | 反代开启 | 经 BFF POST files {"server_path": 合法} | 200 且直连与反代结果一致 | L2 | P2 |
| TC-BIO-API-107 | FR-BIO-004 | jobs 创建后进度字段 | 新任务 | GET job | progress=0;stages 全部 waiting | L2 | P1 |
| TC-BIO-API-108 | FR-BIO-011 | 日志尾非 running 阶段也可见 | 阶段 done | GET manifest | 200;log_tail 非空(保留最后执行日志) | L2 | P1 |
| TC-BIO-API-109 | FR-BIO-031 | 第 4 并发任务排队 | 3 任务 running(mock) | 创建第 4 任务并 confirm | 第 4 任务不立即出 stage_started;前 3 任一完成后方出现 | L2 | P0 |
| TC-BIO-API-110 | FR-BIO-031 | 并发信号量可配 | BIOFLOW_CONCURRENCY=1 重启 | 2 任务并发 | 始终只有 1 个 docker 在跑(mock 计数=1) | L2 | P1 |
| TC-BIO-API-111 | FR-BIO-031 | 重启续跑不重跑已完成 | 任务 3 阶段(1 done 1 running);重启服务 | 观察 | 重启后第 1 阶段保持 done(无新 attempt);第 2 阶段从断点续跑 | L2 | P0 |
| TC-BIO-API-112 | FR-BIO-024 | 任务列表过滤状态 | 库中 done/failed 各一 | GET /api/bioflow/jobs?status=failed | items 仅 failed 任务 | L2 | P1 |
| TC-BIO-API-113 | FR-BIO-024 | 任务列表按会话过滤 | 会话 s1 2 任务 | GET /api/bioflow/jobs?session_id=s1 | items length=2 | L2 | P1 |
| TC-BIO-API-114 | FR-BIO-002 | catalog 阶段用途文案 | 无 | GET catalog?stage=identify | description 非空中文文案(含输入输出描述) | L2 | P1 |
| TC-BIO-API-115 | FR-BIO-029 | 执行日志含资源参数 | 阶段 running(mock docker 记录命令) | 读 stage_log | 日志或 mock 记录含 --cpus 与 --memory 数值 | L2 | P0 |
| TC-BIO-API-116 | FR-BIO-029 | 镜像按阶段映射 | identify 阶段 | mock 记录 docker 命令 | 命令镜像=bioflow-gf(stage_image_map 映射) | L2 | P0 |
| TC-BIO-API-117 | FR-BIO-029 | 容器 --user 宿主机 uid | 阶段执行 | mock 记录命令 | 含 --user 且值=服务进程 uid | L2 | P0 |
| TC-BIO-API-118 | FR-BIO-029 | BIOFLOW_DATA 只读挂载 | 阶段执行 | mock 记录命令 | 含 -v {BIOFLOW_DATA_ROOT}:/bioflow-data:ro | L2 | P0 |
| TC-BIO-API-119 | FR-BIO-029 | 容器退出即清理 | 阶段完成 | mock 记录 | 含 --rm 标志 | L2 | P1 |
| TC-BIO-API-120 | FR-BIO-006 | 上传无任务 404 | 无 | POST /api/bioflow/jobs/nope/files | 404 信封 | L2 | P1 |
| TC-BIO-API-121 | FR-BIO-008 | confirm 空参数体 | 阶段 waiting_confirm | POST confirm {} | 200;按默认参数执行 | L2 | P1 |
| TC-BIO-API-122 | FR-BIO-010 | 暂停含排队任务 | 任务 queued | POST pause | 200;队列移除且状态=paused | L2 | P1 |
| TC-BIO-API-123 | FR-BIO-016 | 报告登记含图清单 | 报告含 2 图 | 登记 | doc_artifacts 行图清单字段含 2 个 fig id | L2 | P1 |
| TC-BIO-API-124 | FR-BIO-015 | 报告 HTML 单文件 | 任务 done | 读任务目录报告文件 | 单 .html 文件;图以 data:image/...;base64 内嵌(无外部图文件引用) | L2 | P0 |
| TC-BIO-API-125 | FR-BIO-015 | 报告含各阶段 manifest 事实 | 任务 done | 解析报告 HTML | 含 identify 阶段输出数量等 manifest 事实数据 | L2 | P1 |
| TC-BIO-API-126 | FR-BIO-014 | events 未知 job 404 | 无 | GET /api/bioflow/jobs/nope/events | 404 信封 | L2 | P1 |
| TC-BIO-API-127 | FR-BIO-011 | stage_log 事件日志尾推送 | 阶段 running | 读 events | stage_log 事件 data.log 字段非空且随执行追加 | L2 | P0 |
| TC-BIO-API-128 | FR-BIO-014 | 断线期间事件不丢 | 任务 running;断开 5s 重连 | 重连读事件 | 断开期间产生的 stage_log 全部回放 | L2 | P0 |
| TC-BIO-API-129 | FR-BIO-020 | 存档含中间文件开关 | 任务 done 含中间文件 | POST archives include_intermediate=true | 磁盘目录含中间产物;size 更大 | L2 | P1 |
| TC-BIO-API-130 | FR-BIO-020 | 存档不含中间文件 | 同上 | POST archives include_intermediate=false | 磁盘目录不含中间产物目录 | L2 | P1 |
| TC-BIO-API-131 | FR-BIO-021 | 存档状态回复字段 | 存档完成 | 读对话消息 | 消息含名称/位置/大小三要素字段 | L2 | P0 |
| TC-BIO-API-132 | FR-BIO-023 | run 后新任务入列表 | POST archives/run | GET jobs | 新任务出现在列表(title 含 target) | L2 | P1 |
| TC-BIO-API-133 | FR-BIO-025 | health 失败 503 | 服务 db 损坏(mock) | GET health | 503 或 200 带 db:error 字段(两态断言其一) | L2 | P1 |
| TC-BIO-API-134 | FR-BIO-028 | 生信服务独立进程 | 无 | 检查进程表 | 8098 进程独立于 BFF;BFF 重启后 8098 存活 | L2s | P0 |
| TC-BIO-API-135 | FR-BIO-028 | 独立 SQLite | 无 | 检查文件 | bioflow.db 存在于生信数据根;BFF 无同表 | L2s | P1 |
| TC-BIO-API-136 | FR-BIO-001 | chat 流错误信封 | mock LLM 500 | 读流 | SSE data 含 code/msg 错误信封结构 | L2 | P1 |
| TC-BIO-API-137 | FR-BIO-002 | plan_ready 用途字段非空 | mock LLM | 读 plan_ready | 每条 candidate.purpose 非空 | L2 | P1 |
| TC-BIO-API-138 | FR-BIO-004 | 确认创建任务后 SSE 建库 | 前端确认 | 读事件 | job_created 后 GET job 200 且状态=created | L2 | P0 |
| TC-BIO-API-139 | FR-BIO-031 | 任务失败不占并发 | 任务失败 | 创建新任务 confirm | 新任务立即执行(信号量已释放) | L2 | P1 |
| TC-BIO-API-140 | FR-BIO-012 | 改参数重跑走 confirm | 阶段 failed | POST rerun {"params":{...}} | 状态=waiting_confirm(表单再确认)或直接 running(两态断言其一) | L2 | P1 |
| TC-BIO-API-141 | FR-BIO-022 | 归档文件下载 | 归档 a1 | GET /api/bioflow/archives/{a1}/download | 200 zip/目录打包流;可解压 | L2 | P1 |
| TC-BIO-API-142 | FR-BIO-022 | 归档报告单独取 | 归档 a1 含报告 | GET /api/bioflow/archives/{a1}/report | 200;text/html 内容含 <html | L2 | P1 |
| TC-BIO-API-143 | FR-BIO-017 | 报告编辑落盘 | 报告已登记 | PATCH 报告文字 | 200;磁盘 HTML 内容更新 | L2 | P1 |
| TC-BIO-API-144 | FR-BIO-019 | revise 无绘图目标 422 | 报告任务 | POST revise {"instruction":"不明确"} | 422 或转 docgen(两态断言其一) | L2 | P2 |
| TC-BIO-API-145 | FR-BIO-002 | chat/stream 多候选单选 | 3 候选 | 用户选第 2 条(消息或 API 选) | 任务 stages=第 2 候选链 | L2 | P1 |
| TC-BIO-API-146 | FR-BIO-031 | 队列顺序 FIFO | 并发满 | 3 任务排队 | 完成 1 个后先入队者先执行 | L2 | P1 |
| TC-BIO-API-147 | FR-BIO-010 | 自动连续模式接口字段 | 任务开启 auto_continue | 读任务详情 | job.auto_continue=true;阶段间跳过 confirm | L2 | P0 |
| TC-BIO-API-148 | FR-BIO-010 | 自动连续暂停停在下一阶段前 | auto_continue 任务暂停 | 读任务 | 当前阶段等待且未 confirm;无跳过 | L2 | P1 |
| TC-BIO-API-149 | FR-BIO-004 | 创建任务重复 id 幂等 | POST jobs 两次相同 payload | 两次 | 产生 2 个不同 job id(或 409 二选一固定) | L2 | P2 |
| TC-BIO-API-150 | FR-BIO-009 | confirm 参数类型校验 | 无 | confirm {"params":{"cpu":"abc"}} | 422;detail 含 cpu 类型错误 | L2 | P1 |
6.1.3 RUN runner 状态机(L1 单元,mock docker 执行)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-BIO-RUN-001 | FR-BIO-031 | 全链成功推进 | 3 阶段任务 mock docker 全 0 退出 | run | 阶段状态依次 running→done;任务=done;事件序 stage_started/stage_done 成对 | L1 | P0 |
| TC-BIO-RUN-002 | FR-BIO-012 | 阶段失败转 failed | mock docker 退出码 1 | run | 状态=failed;事件 stage_failed;后续阶段不执行(任务停在 failed 阶段) | L1 | P0 |
| TC-BIO-RUN-003 | FR-BIO-012 | 失败后 rerun 成功 | 同上 | rerun | attempt=2;状态 done;继续后续阶段 | L1 | P0 |
| TC-BIO-RUN-004 | FR-BIO-012 | 失败后 skip | 阶段 failed | skip | 状态=skipped;事件 stage_skipped;后续阶段可执行 | L1 | P0 |
| TC-BIO-RUN-005 | FR-BIO-012 | 失败后改参数重跑 | 阶段 failed | rerun_with_params {"cpu":8} | 新执行命令含 cpu=8;成功 | L1 | P0 |
| TC-BIO-RUN-006 | FR-BIO-010 | 暂停在阶段边界 | 阶段 2 running 完成时 pause | 观察 | 阶段 2 done 后阶段 3 不启动;任务=paused;事件 job_paused | L1 | P0 |
| TC-BIO-RUN-007 | FR-BIO-010 | 暂停后恢复续跑 | 任务 paused | resume | 从下一阶段继续;不重跑已完成 | L1 | P0 |
| TC-BIO-RUN-008 | FR-BIO-031 | 重启续跑不重跑 | 任务 2/5 阶段 done;模拟重启加载 DB | 重启恢复 | 已 done 阶段 attempt 不变;从第 3 阶段续跑 | L1 | P0 |
| TC-BIO-RUN-009 | FR-BIO-031 | 重启恢复 in-flight | running 阶段无完成标记;重启 | 恢复 | 该阶段按 manifest 判成败:有 manifest 且成功→done;否则重跑 | L1 | P0 |
| TC-BIO-RUN-010 | FR-BIO-031 | 并发上限排队 | BIOFLOW_CONCURRENCY=3;4 任务 | run | 同时 running 的 docker ≤3;第 4 任务 queued | L1 | P0 |
| TC-BIO-RUN-011 | FR-BIO-031 | 并发槽释放 | 任务 1 完成 | 观察 | 队列头立即启动 | L1 | P1 |
| TC-BIO-RUN-012 | FR-BIO-029 | 阶段超时 | mock docker 不退出;timeout=1s | run | 阶段=failed(reason=timeout);容器被 kill;日志含超时记录 | L1 | P0 |
| TC-BIO-RUN-013 | FR-BIO-031 | 日志截断只留尾 | mock 输出 500 行 | run | bio_stages.log_tail 行数=80 且为末 80 行 | L1 | P0 |
| TC-BIO-RUN-014 | FR-BIO-029 | 退出码非 0 判失败 | mock 退出码 3 | run | 状态=failed;log_tail 含 stderr | L1 | P0 |
| TC-BIO-RUN-015 | FR-BIO-031 | 退出码 0 但 manifest 缺 | 无 manifest 产出 | run | 阶段=failed(reason=no_manifest) | L1 | P0 |
| TC-BIO-RUN-016 | FR-BIO-029 | manifest 失败标记判败 | manifest status=failed | run | 阶段=failed(不因退出码 0 误判成功) | L1 | P0 |
| TC-BIO-RUN-017 | FR-BIO-005 | 输入缺失等待文件 | 阶段 input 文件不存在 | run 至该阶段 | 状态=await_files;事件 stage_await_files;不启动 docker | L1 | P0 |
| TC-BIO-RUN-018 | FR-BIO-005 | 文件补齐自动推进 | await_files 后登记文件 | 触发 | 状态转 waiting_confirm(手动)或 running(自动连续);事件 stage_started | L1 | P0 |
| TC-BIO-RUN-019 | FR-BIO-008 | 阶段前等待确认 | 手动模式 | run 至阶段 | 状态=waiting_confirm;事件 stage_await_confirm;不执行 docker | L1 | P0 |
| TC-BIO-RUN-020 | FR-BIO-008 | 确认后执行 | waiting_confirm | confirm | docker 命令以表单参数构造;状态=running | L1 | P0 |
| TC-BIO-RUN-021 | FR-BIO-010 | 自动连续跳过确认 | auto_continue=true | run | 阶段间无 waiting_confirm;全程自动推进 | L1 | P0 |
| TC-BIO-RUN-022 | FR-BIO-010 | 自动连续可暂停 | auto_continue 任务 | pause | 停在当前阶段边界;恢复后仍自动连续 | L1 | P0 |
| TC-BIO-RUN-023 | FR-BIO-031 | 暂停恢复重入安全 | 任务 paused | resume 两次 | 第二次 resume 409/幂等无副作用 | L1 | P1 |
| TC-BIO-RUN-024 | FR-BIO-012 | 三选一状态校验 | 阶段 done | rerun/skip | 拒绝(状态机不越迁) | L1 | P1 |
| TC-BIO-RUN-025 | FR-BIO-031 | 并发信号量释放异常安全 | docker 执行抛异常 | 观察 | 信号量释放;任务转 failed;服务不挂 | L1 | P1 |
| TC-BIO-RUN-026 | FR-BIO-031 | 阶段间输入传递 | 上游 manifest 含 artifacts 路径 | run 下游 | 下游 docker 命令的 input 路径=上游 artifacts | L1 | P0 |
| TC-BIO-RUN-027 | FR-BIO-031 | 全部完成后归档提示事件 | 任务 done | 观察 | 事件 job_done 后紧跟 archive_suggest(或前端判 done 出提示,两态断言其一) | L1 | P1 |
| TC-BIO-RUN-028 | FR-BIO-024 | 多任务互不串扰 | 2 任务并发 | run | 各自状态/参数独立;无共享状态污染 | L1 | P1 |
| TC-BIO-RUN-029 | FR-BIO-024 | 任务进度数值 | 3 阶段任务完成 1 | 读进度 | progress=33(按完成阶段数/总阶段数) | L1 | P1 |
| TC-BIO-RUN-030 | FR-BIO-031 | 恢复时跳过已归档任务 | 已归档任务 in-flight 残留 | 重启 | 不重复执行(含 archive 状态检查) | L1 | P2 |
| TC-BIO-RUN-031 | FR-BIO-029 | docker 失败重试策略 | mock docker 偶发失败 | run | 按配置重试 N 次;最终 failed;attempt 数=N+1 | L1 | P1 |
| TC-BIO-RUN-032 | FR-BIO-005 | 多输入文件部分缺失 | 阶段需 2 文件缺 1 | run | await_files;事件 data 指明缺哪个文件 | L1 | P0 |
| TC-BIO-RUN-033 | FR-BIO-031 | 暂停时运行中阶段完成才停 | 阶段 running 且即将完成 | pause | 当前阶段完成→done 后任务才 paused(不杀容器) | L1 | P1 |
| TC-BIO-RUN-034 | FR-BIO-003 | 前置补全后链完整性 | 候选链缺前置 | 规划校验 | 补全后链包含前置;job.stages 完整 | L1 | P0 |
| TC-BIO-RUN-035 | FR-BIO-029 | 容器环境变量 BBA_* 注入 | 阶段执行 | mock 记录命令 | 含 -e BBA_*(至少 BBA_PFAM_DIR/BBA_RAG_MAPPING_FILE 其一) | L1 | P0 |
| TC-BIO-RUN-036 | FR-BIO-029 | 任务目录挂载 | 阶段执行 | mock 记录命令 | 含 -v {job_dir}/input:/job/input 与 -v {job_dir}/workspace:/job/workspace | L1 | P0 |
| TC-BIO-RUN-037 | FR-BIO-029 | 容器内命令形态 | 阶段执行 | mock 记录命令 | python -B -m cli.run_identify --input-dir /job/input --workspace /job/workspace(前缀两元素 python -B) | L1 | P0 |
| TC-BIO-RUN-038 | FR-BIO-031 | 阶段状态机非法迁移拒绝 | 任意状态 | 调用非法迁移 | 抛状态机错误/忽略(不写脏状态) | L1 | P1 |
| TC-BIO-RUN-039 | FR-BIO-031 | runner 无阶段空任务 | stages=[] | run | 直接 done;无 docker 调用 | L1 | P2 |
| TC-BIO-RUN-040 | FR-BIO-031 | 并发计数含 running 阶段 | 3 任务各 1 running | 观察 | 计数=3;新任务排队 | L1 | P1 |
| TC-BIO-RUN-041 | FR-BIO-031 | 阶段等待确认不占并发 | 任务 waiting_confirm | 观察 | 并发计数不含该任务 | L1 | P1 |
| TC-BIO-RUN-042 | FR-BIO-031 | 事件总线订阅多者广播 | 2 个 events 连接 | run 1 阶段 | 两连接收到相同事件序列 | L1 | P1 |
| TC-BIO-RUN-043 | FR-BIO-031 | 心跳期无事件不空转 | 任务 paused | 观察 CPU | 无 busy-loop(等待用事件/队列阻塞) | L1 | P2 |
| TC-BIO-RUN-044 | FR-BIO-024 | manifest 路径登记 | 阶段 done | 读 bio_stages | manifest_path 指向任务目录内真实文件 | L1 | P0 |
| TC-BIO-RUN-045 | FR-BIO-012 | 跳过事件携带阶段名 | skip | 读事件 | stage_skipped.data.stage=阶段名 | L1 | P1 |
| TC-BIO-RUN-046 | FR-BIO-031 | 长时间任务状态可查 | mock 慢执行 | 执行中 GET job | 状态=running;无阻塞(独立线程/协程) | L1 | P1 |
6.1.4 KERN 内核执行与 manifest(L1 单元 mock 命令拼装 + L2s 真实冒烟)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-BIO-KERN-001 | FR-BIO-029 | docker 命令拼装基元 | mock | 拼装 identify 阶段命令 | 数组元素依次:docker,run,--rm,--user,uid,-v×3,--cpus,--memory,-e×N,镜像,python,-B,-m,cli.run_identify,参数… | L1 | P0 |
| TC-BIO-KERN-002 | FR-BIO-029 | 挂载三目录 | mock | 拼装 | -v 含 input/workspace/BIOFLOW_DATA 三处;BIOFLOW_DATA 后带 :ro | L1 | P0 |
| TC-BIO-KERN-003 | FR-BIO-029 | --cpus 注入 | mock | 拼装 | 含 --cpus 且值来自阶段配置 | L1 | P0 |
| TC-BIO-KERN-004 | FR-BIO-029 | --memory 注入 | mock | 拼装 | 含 --memory 且格式如 64g | L1 | P0 |
| TC-BIO-KERN-005 | FR-BIO-029 | 环境变量拼装 | mock | 拼装 | 每项 env 输出为两个元素:-e 与 KEY=value | L1 | P0 |
| TC-BIO-KERN-006 | FR-BIO-029 | 容器命令转义安全 | 参数含空格 | 拼装 | 参数作为独立 argv 元素(subprocess list 传参,无 shell 注入) | L1 | P0 |
| TC-BIO-KERN-007 | FR-BIO-029 | 镜像映射查表 | mock | 查 align 阶段镜像 | 返回 bioflow-gf(stage_image_map.json) | L1 | P0 |
| TC-BIO-KERN-008 | FR-BIO-029 | 未知阶段镜像映射 | mock | 查未知阶段 | 返回 None 且执行前置拦截(不拼命令) | L1 | P1 |
| TC-BIO-KERN-009 | FR-BIO-029 | 超时 kill | mock docker 超时 | 观察 | 调用 kill/terminate;阶段 failed | L1 | P0 |
| TC-BIO-KERN-010 | FR-BIO-030 | 金标 24 成员 ID 全等 | bioflow-gf 镜像;金标输入 Ft.SPL | 镜像内跑 identify | 输出 ID 集合与 dev 预期 24 成员集合 diff 为空 | L2s | P0 |
| TC-BIO-KERN-011 | FR-BIO-030 | 金标 diff 命令空输出 | 同上 | 执行 diff 脚本 | stdout 为空;脚本退出码 0 | L2s | P0 |
| TC-BIO-KERN-012 | FR-BIO-032 | 18 入口 --help 冒烟 | 4 镜像齐 | 对 18 个 cli.run_* 逐条 python -B -m cli.run_x --help | 18/18 退出码 0;无 traceback | L2s | P0 |
| TC-BIO-KERN-013 | FR-BIO-032 | 镜像内 import 编译产物 | bioflow-gf 镜像 | python -c "import gfa_core.mas" | 成功(.so 加载无 ImportError) | L2s | P0 |
| TC-BIO-KERN-014 | FR-BIO-030 | manifest 解析成功路径 | 金标 manifest fixture | 解析 | 字段齐:status/artifacts/outputs/params/耗时 | L1 | P0 |
| TC-BIO-KERN-015 | FR-BIO-030 | manifest 缺失文件 | 无 manifest 文件 | 解析 | 返回错误(判失败 reason=no_manifest) | L1 | P0 |
| TC-BIO-KERN-016 | FR-BIO-030 | manifest 非法 JSON | 损坏内容 | 解析 | 返回解析错误;阶段 failed | L1 | P1 |
| TC-BIO-KERN-017 | FR-BIO-030 | manifest status 缺失 | JSON 无 status 键 | 解析 | 按退出码兜底判成败 | L1 | P1 |
| TC-BIO-KERN-018 | FR-BIO-030 | artifacts 路径提取 | manifest 含 artifacts | 解析 | 提取为下游输入(跨阶段输入定位) | L1 | P0 |
| TC-BIO-KERN-019 | FR-BIO-030 | 路径不存在时报错 | artifacts 指向缺失文件 | 解析 | 报错含具体路径(阶段失败) | L1 | P1 |
| TC-BIO-KERN-020 | FR-BIO-030 | 24 ID 去重与排序无关 | 金标输出乱序 | 比对 | 集合比对全等(顺序无关) | L2s | P1 |
| TC-BIO-KERN-021 | FR-BIO-032 | 4 镜像构建产物 | build_all.sh 完成 | 检查 | 4 镜像 tag 均存在(docker images 可见) | L2s | P0 |
| TC-BIO-KERN-022 | FR-BIO-032 | SHA256SUMS 产出 | 构建完成 | 检查 | 产物目录存在 SHA256SUMS 且含 4 条目 | L2s | P0 |
| TC-BIO-KERN-023 | FR-BIO-032 | 泄露门禁(明文凭据扫描) | 构建产物 | 扫描 .so/明文 | 无 ACCESS_KEY/SECRET 类凭据命中 | L2s | P0 |
| TC-BIO-KERN-024 | FR-BIO-029 | 数据不进镜像 | 构建产物 | 检查镜像层 | 镜像内无金标/用户数据文件 | L2s | P1 |
6.1.5 SSE 事件流与断线回放(L1 单元帧解析 + L2 序列)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-BIO-SSE-001 | FR-BIO-014 | 事件类型全集 | mock 全链 | 收集事件 | 出现类型 ∈ {job_created, plan_ready, stage_started, stage_log, stage_done, stage_failed, stage_skipped, stage_await_confirm, stage_await_files, job_done, job_paused, job_archived} 且无未知类型 | L1 | P0 |
| TC-BIO-SSE-002 | FR-BIO-014 | job_created 字段 | 创建任务 | 读事件 | data 含 job_id/title/stages | L1 | P0 |
| TC-BIO-SSE-003 | FR-BIO-014 | stage_started 字段 | 阶段启动 | 读事件 | data 含 stage/attempt/ts | L1 | P0 |
| TC-BIO-SSE-004 | FR-BIO-014 | stage_log 追加 | 阶段运行 | 读事件 | data.log 非空;多帧顺序=日志顺序 | L1 | P0 |
| TC-BIO-SSE-005 | FR-BIO-014 | stage_done 字段 | 阶段完成 | 读事件 | data 含 stage/exit_code=0/manifest_ref | L1 | P0 |
| TC-BIO-SSE-006 | FR-BIO-014 | stage_failed 字段 | 阶段失败 | 读事件 | data 含 stage/exit_code 非 0/reason | L1 | P0 |
| TC-BIO-SSE-007 | FR-BIO-014 | stage_skipped 字段 | 跳过 | 读事件 | data 含 stage | L1 | P0 |
| TC-BIO-SSE-008 | FR-BIO-014 | stage_await_confirm 字段 | 阶段待确认 | 读事件 | data 含 stage/form_defaults(参数默认值) | L1 | P0 |
| TC-BIO-SSE-009 | FR-BIO-014 | stage_await_files 字段 | 阶段待文件 | 读事件 | data 含 stage/required_files[](含缺失文件名) | L1 | P0 |
| TC-BIO-SSE-010 | FR-BIO-014 | job_done 收尾 | 任务完成 | 读事件 | data 含 job_id/耗时;为最后事件 | L1 | P0 |
| TC-BIO-SSE-011 | FR-BIO-014 | job_paused 字段 | 暂停 | 读事件 | data 含 job_id/当前阶段 | L1 | P0 |
| TC-BIO-SSE-012 | FR-BIO-014 | job_archived 字段 | 存档 | 读事件 | data 含 archive_id | L1 | P1 |
| TC-BIO-SSE-013 | FR-BIO-014 | seq 严格递增 | mock 帧序列 | 解析 seq | 后帧 seq=前帧 seq+1 | L1 | P0 |
| TC-BIO-SSE-014 | FR-BIO-014 | 帧解析空行容错 | 帧含多余空行 | 解析 | 正常解析不报错 | L1 | P1 |
| TC-BIO-SSE-015 | FR-BIO-014 | 多行 data 合并 | data 分行发送 | 解析 | 事件 data 按 \n 合并 | L1 | P1 |
| TC-BIO-SSE-016 | FR-BIO-014 | 心跳注释忽略 | 帧含 :keepalive | 解析 | 不产业务事件 | L1 | P1 |
| TC-BIO-SSE-017 | FR-BIO-014 | 坏帧不中断流 | 含未命名 data 帧 | 解析 | 跳过坏帧继续后续事件 | L1 | P1 |
| TC-BIO-SSE-018 | FR-BIO-014 | 前端 parser 兼容既有帧 | 既有 sse/parser.js 输出格式 | 解析 bioflow 帧 | 复用 parser 无改动可解析(红线零改动验证) | L3 | P0 |
| TC-BIO-SSE-019 | FR-BIO-014 | 事件序列全链顺序 | mock 3 阶段 | 收集序列 | 相对序:job_created<plan_ready<首 stage_started<末 stage_done<job_done | L2 | P0 |
| TC-BIO-SSE-020 | FR-BIO-014 | 失败序列 | mock 阶段 2 失败 | 收集 | 出现 stage_failed;无该阶段 stage_done;后续阶段无 stage_started | L2 | P0 |
| TC-BIO-SSE-021 | FR-BIO-014 | 跳过序列 | mock skip | 收集 | stage_skipped 出现在 stage_failed 之后 | L2 | P0 |
| TC-BIO-SSE-022 | FR-BIO-014 | 断线回放快照结构 | 任务 3 阶段中途 | 重连首帧 | 首帧 data.type=snapshot;data.job.status 与 DB 一致;data.stages 逐阶段含 status | L2 | P0 |
| TC-BIO-SSE-023 | FR-BIO-014 | 回放补齐事件序 | 断开 5s 期间 2 条 stage_log | 重连 | 快照后回放这 2 条;seq 连续 | L2 | P0 |
| TC-BIO-SSE-024 | FR-BIO-014 | 回放不重复已见事件 | 客户端带 last_seq 重连 | 重连 | 不重发 ≤last_seq 事件 | L2 | P0 |
| TC-BIO-SSE-025 | FR-BIO-014 | 前端重连机制 | 断网 30s | 观察前端 | 自动重连(重试/退避);进度卡整体刷新 | L3 | P0 |
| TC-BIO-SSE-026 | FR-BIO-014 | 前端回放刷新进度卡 | 快照 1 done 1 running 1 waiting | 应用快照 | 卡片三阶段状态与快照一致;日志尾区显示 | L3 | P0 |
| TC-BIO-SSE-027 | FR-BIO-014 | 重连失败提示 | 服务不可达 | 观察 | 进度卡显示断线态;有重连按钮/文案 | L3 | P1 |
| TC-BIO-SSE-028 | FR-BIO-014 | events 与 chat/stream 事件同源 | 同任务 | 对比两流 | 事件类型与 seq 一致 | L2 | P1 |
| TC-BIO-SSE-029 | FR-BIO-014 | 事件延迟心跳期间无重复 job_done | 任务 done | 读流 | job_done 仅 1 次 | L2 | P1 |
| TC-BIO-SSE-030 | FR-BIO-014 | 快照含日志尾 | 阶段 running 有日志 | 重连快照 | snapshot.stages[*].log_tail 非空 | L2 | P0 |
| TC-BIO-SSE-031 | FR-BIO-014 | Last-Event-ID 续传 | 断连时记录 id | 重连带 Last-Event-ID | 服务从该 id 后补发 | L2 | P1 |
| TC-BIO-SSE-032 | FR-BIO-014 | 前端事件更新器幂等 | 重复 stage_done 帧 | 应用两次 | 阶段状态仍 done;无异常 | L3 | P1 |
6.1.6 DB 三表迁移与持久化(L1)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-BIO-DB-001 | FR-BIO-028 | 三表创建 | 空库 | 初始化 | bio_jobs/bio_stages/bio_archives 三表存在;schema 含任务书字段 | L1 | P0 |
| TC-BIO-DB-002 | FR-BIO-028 | 迁移幂等 | 已初始化 | 重复跑迁移 | 无异常;schema_version 不变;表数不增 | L1 | P0 |
| TC-BIO-DB-003 | FR-BIO-028 | 版本升级迁移 | v1 库 fixture | 迁移至 v2 | 新列存在;旧数据保留 | L1 | P1 |
| TC-BIO-DB-004 | FR-BIO-028 | 阶段链 JSON 存取 | 任务 3 阶段 | 写入读回 | stages 数组完整还原 | L1 | P0 |
| TC-BIO-DB-005 | FR-BIO-028 | 参数 JSON 存取 | 参数嵌套 | 写入读回 | 参数对象完整还原(含嵌套) | L1 | P0 |
| TC-BIO-DB-006 | FR-BIO-024 | 任务级联删除阶段 | 任务含 5 阶段 | 删任务 | bio_stages 对应行=0 | L1 | P0 |
| TC-BIO-DB-007 | FR-BIO-022 | 归档外键任务 | 任务 j1 归档 | 删任务(若实现允许) | 归档保留或级联(两态断言其一,按实现固定) | L1 | P1 |
| TC-BIO-DB-008 | FR-BIO-028 | 时间戳字段 | 创建任务 | 读行 | created_at/updated_at 非空且 ISO 格式 | L1 | P1 |
| TC-BIO-DB-009 | FR-BIO-028 | 状态枚举约束 | 写入 | 写非法状态值 | 拒绝或枚举约束错误 | L1 | P1 |
| TC-BIO-DB-010 | FR-BIO-031 | 并发写安全 | 2 协程更新同任务 | 并发写 | 无死锁;最终状态一致 | L1 | P1 |
| TC-BIO-DB-011 | FR-BIO-024 | log_tail 持久化 | 阶段运行 | 更新 log_tail | 读回与内存一致 | L1 | P0 |
| TC-BIO-DB-012 | FR-BIO-021 | 归档大小与路径字段 | 存档 | 读 bio_archives 行 | size_bytes>0;disk_path 非空且目录存在 | L1 | P0 |
6.1.7 FLOW 上下游集成(接口级)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-BIO-FLOW-001 | FR-BIO-028 | BFF 反代开启注册 | BIOFLOW_ENABLED=true 启动 BFF | 检查路由表 | /api/bioflow/* 路由已注册(FastAPI routes 可见) | L2 | P0 |
| TC-BIO-FLOW-002 | FR-BIO-028 | BFF 反代关闭不注册 | BIOFLOW_ENABLED=false | 检查路由表 | 无 /api/bioflow/* 路由 | L2 | P0 |
| TC-BIO-FLOW-003 | FR-BIO-016 | 报告登记进 doc_artifacts | 生信任务 done | 登记 | doc_artifacts 新行;kind=bioflow_report 或等价字段 | L2 | P0 |
| TC-BIO-FLOW-004 | FR-BIO-016 | 报告登记字段对齐 | 登记 | 读行 | job_id/标题/md/图清单与 docgen 表字段对齐(缺字段报错) | L2 | P0 |
| TC-BIO-FLOW-005 | FR-BIO-015 | fig:// 图引用渲染 | 报告含 fig://fig1 | 渲染报告 | img src 变为 data:image/...base64;无 fig:// 残留 | L3 | P0 |
| TC-BIO-FLOW-006 | FR-BIO-015 | fig:// 未知 id 降级 | fig://nope | 渲染 | 图位置显示占位/跳过且不报错 | L3 | P1 |
| TC-BIO-FLOW-007 | FR-BIO-016 | DocPane 白底预览 | 报告登记 | 打开 DocPane | 容器 computed background=#FFFFFF(白底);图文正常 | L4 | P0 |
| TC-BIO-FLOW-008 | FR-BIO-019 | revise 触发预览刷新 | 图表调整后 | 观察 DocPane | 预览重新加载;新图可见 | L3 | P0 |
| TC-BIO-FLOW-009 | FR-BIO-026 | vstore flow_docs 检索 | flow_docs 集合已入库 | 检索「identify 需要什么输入」 | 返回块含源文件+章节;top1 相关 | L2 | P0 |
| TC-BIO-FLOW-010 | FR-BIO-023 | 存档复用端到端接口链 | 归档 a1 | POST archives/{a1}/run | 新任务→表单预填→confirm→执行,参数=归档值(全链) | L2 | P0 |
6.1.8 STORE 前端 store(L3 vitest)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-BIO-STORE-001 | FR-BIO-001 | sendBioflow 动作存在 | store 挂载 | 调用 sendBioflow(msg) | 消息进入 messages 数组且 blocks 含 bioflow 类块 | L3 | P0 |
| TC-BIO-STORE-002 | FR-BIO-001 | 分流未命中不触发生信 | mock 词典 | 发送「什么是基因家族」 | 走原 send() 路径;不产生 bioflow 请求 | L3 | P0 |
| TC-BIO-STORE-003 | FR-BIO-002 | 候选路径写入消息 | mock plan_ready | 应用事件 | 消息 blocks 含 path 块且 candidates.length 2~3 | L3 | P0 |
| TC-BIO-STORE-004 | FR-BIO-004 | 确认后创建任务状态 | mock job_created | 应用事件 | bioflowJob 状态写入 store(jobId 非空) | L3 | P0 |
| TC-BIO-STORE-005 | FR-BIO-011 | 阶段状态更新 | mock stage 事件序列 | 逐帧应用 | store 中阶段状态 waiting→running→done 逐帧一致 | L3 | P0 |
| TC-BIO-STORE-006 | FR-BIO-012 | 失败事件置 failed | mock stage_failed | 应用 | store 阶段 status=failed 且 error 文案存在 | L3 | P0 |
| TC-BIO-STORE-007 | FR-BIO-011 | 日志尾追加 | mock stage_log×3 | 应用 | store logTail 追加为整体,长度=三帧之和 | L3 | P0 |
| TC-BIO-STORE-008 | FR-BIO-014 | 快照整体替换 | mock snapshot | 应用 | store 阶段数组被快照整体替换(引用变化) | L3 | P0 |
| TC-BIO-STORE-009 | FR-BIO-014 | 断线重连触发 | SSE 断开(mock) | 等待 | store 触发 reconnect;成功后应用快照 | L3 | P0 |
| TC-BIO-STORE-010 | FR-BIO-006 | 上传进度状态 | mock XHR 进度 45% | 上传 | store uploadProgress=45 | L3 | P0 |
| TC-BIO-STORE-011 | FR-BIO-009 | 表单值提交 | mock | dispatch confirmStage(stage, params) | 请求体 params 与表单一致 | L3 | P0 |
| TC-BIO-STORE-012 | FR-BIO-010 | 自动连续开关状态 | mock | 切换 autoContinue | store.autoContinue=true 且随任务持久化字段下发 | L3 | P0 |
| TC-BIO-STORE-013 | FR-BIO-010 | 暂停/恢复动作 | mock | dispatch pauseJob/resumeJob | store 状态 paused/running;发出对应 POST | L3 | P0 |
| TC-BIO-STORE-014 | FR-BIO-012 | 三选一动作 | mock | dispatch rerunStage/skipStage/rerunWithParams | 分别发出 rerun/skip/rerun 请求;请求体正确 | L3 | P0 |
| TC-BIO-STORE-015 | FR-BIO-023 | 存档复用预填 | mock archive_loaded | 应用 | store.formDefaults=存档参数;来源标记=archive | L3 | P0 |
| TC-BIO-STORE-016 | FR-BIO-025 | 探活结果 | mock health 200/500 | 初始化 | 200→bioflowAvailable=true;500/超时→false | L3 | P0 |
| TC-BIO-STORE-017 | FR-BIO-021 | 存档状态回复写入 | mock archive_done | 应用 | 消息块含名称/位置/大小三字段 | L3 | P0 |
| TC-BIO-STORE-018 | FR-BIO-024 | 面板任务列表 | mock jobs | loadJobs | store.jobs 数组与接口一致(排序) | L3 | P0 |
| TC-BIO-STORE-019 | FR-BIO-022 | 档案列表 | mock archives | loadArchives | store.archives 数组与接口一致 | L3 | P0 |
| TC-BIO-STORE-020 | FR-BIO-014 | 事件乱序容错 | mock 乱序帧 | 应用 | 不崩溃;状态不回退(done 不再变 running) | L3 | P1 |
| TC-BIO-STORE-021 | FR-BIO-014 | 会话切换隔离 | 2 会话各 1 任务 | 切换 | store 当前任务随会话切换;互不污染 | L3 | P1 |
| TC-BIO-STORE-022 | FR-BIO-001 | 红线文件零改动校验 | 仓库 checkout 状态 | 对比 modes.js/labels.js/bench.js/qa.js/parser.js | 与分支基线一致(无 diff) | L3 | P0 |
6.1.9 PATH 路径选择卡(flow-path-card,L4)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-BIO-PATH-001 | FR-BIO-002 | 引导 UI 显示:卡片标题 | mock 候选 2 条 | 挂载 | 标题文本=「🧬 分析路径选择」;卡体有 .flow-path-card 类 | L4 | P0 |
| TC-BIO-PATH-002 | FR-BIO-002 | 引导操作:候选行渲染 | 2-3 条候选 | 挂载 | 渲染 2-3 个候选行;每行含阶段序列文本(首阶段加粗)与用途文本 | L4 | P0 |
| TC-BIO-PATH-003 | FR-BIO-002 | 候选行阶段序列显示 | 候选 [identify,align,phylogeny] | 挂载 | 行文本含「identify → align → phylogeny」;首阶段字重 600 | L4 | P0 |
| TC-BIO-PATH-004 | FR-BIO-002 | 引导操作:点选候选行 | 未选中 | 点击第 2 行 | 该行获得选中态(border 1.5px --pa-g-from;背景=gradient 8% 混色) | L4 | P0 |
| TC-BIO-PATH-005 | FR-BIO-002 | 引导 UI 显示:选中态边框 | 已选中 | 检查 computed style | border-width=1.5px 且 border-color=var(--pa-g-from) | L4 | P0 |
| TC-BIO-PATH-006 | FR-BIO-002 | 确认按钮选中后可点 | 已选中 | 检查「确认此路径」按钮 | disabled=false;背景为 --pa-gradient;文字白色 12.5px/600 | L4 | P0 |
| TC-BIO-PATH-007 | FR-BIO-002 | 确认按钮无选中禁用 | 未选中 | 检查 | disabled=true;opacity=0.45 | L4 | P0 |
| TC-BIO-PATH-008 | FR-BIO-002 | 引导操作:确认发出选择 | 已选中候选 2 | 点击确认 | 触发 select 回调/请求,参数=候选 2 的 stages | L4 | P0 |
| TC-BIO-PATH-009 | FR-BIO-002 | 自然语言改选 | 候选 3 条 | 用户输入「换第二条」 | 回调携带选中索引 2(或经 LLM 解析) | L4 | P1 |
| TC-BIO-PATH-010 | FR-BIO-002 | 空候选不渲染 | candidates=[] | 挂载 | 卡体不渲染(或空态文案);不报错 | L4 | P1 |
| TC-BIO-PATH-011 | FR-BIO-002 | 单候选自动不强制 | candidates=1 | 挂载 | 渲染 1 行;确认仍可用 | L4 | P2 |
| TC-BIO-PATH-012 | FR-BIO-003 | 前置补全明示 | 候选含 auto_filled | 挂载 | 行内或提示区显示「已自动补全」标记与前置阶段名 | L4 | P0 |
| TC-BIO-PATH-013 | FR-BIO-004 | 确认卡逐阶段可读 | path 确认态 | 挂载确认视图 | 逐阶段显示名称/用途/预计耗时三要素 | L4 | P0 |
| TC-BIO-PATH-014 | FR-BIO-004 | 确认后任务创建请求 | 确认卡 | 点击确认 | 发出 POST /api/bioflow/jobs;body.stages=选中链 | L4 | P0 |
| TC-BIO-PATH-015 | FR-BIO-002 | 路径卡主题令牌 | 深/浅主题 | 检查 computed | 背景=surface-1;边框=hairline;圆角=r-lg | L4 | P1 |
| TC-BIO-PATH-016 | FR-BIO-002 | 移动端不溢出 | 390×844 | 挂载 | 卡片宽≤容器宽;无横向滚动 | L5-M | P1 |
| TC-BIO-PATH-017 | FR-BIO-004 | 阶段链超长显示 | 15 阶段候选 | 挂载 | 行内序列文本可换行/省略;行不撑破卡片 | L4 | P2 |
| TC-BIO-PATH-018 | FR-BIO-002 | 用途文本渲染 | candidate.purpose | 挂载 | 每行显示用途文本(非空) | L4 | P1 |
| TC-BIO-PATH-019 | FR-BIO-002 | 卡体尺寸 | 挂载 | 检查 computed | padding=14px 16px;margin=14px 0 | L4 | P2 |
| TC-BIO-PATH-020 | FR-BIO-002 | 行 hover 态 | 未选中 | hover 候选行 | 背景=surface-3(--pa-s3) | L4 | P1 |
| TC-BIO-PATH-021 | FR-BIO-002 | 键盘 Enter 确认 | 已选中;确认按钮聚焦 | 按 Enter | 触发确认回调(同点击) | L4 | P1 |
| TC-BIO-PATH-022 | FR-BIO-002 | 选中后再点同行走自然语言修改 | 已选中行 1 | 再次点击行 1 | 无选中态抖动;回调幂等(保持选中) | L4 | P2 |
6.1.10 FORM 参数表单卡(flow-form-card,L4)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-BIO-FORM-001 | FR-BIO-008 | 引导 UI 显示:表单卡标题 | 阶段 identify 待确认 | 挂载 | 标题=「⚙ identify 步骤 · 可调整参数」;.flow-form-card 存在 | L4 | P0 |
| TC-BIO-FORM-002 | FR-BIO-008 | 引导 UI 显示:前置文案 | 同上 | 挂载 | 对话区显示「XXXX 步骤,可调整参数如下,可按需调整,调整完毕后继续」文案 | L4 | P0 |
| TC-BIO-FORM-003 | FR-BIO-008 | 引导操作:字段渲染 | 参数 schema 3 字段 | 挂载 | 渲染 3 个字段行:label 12px ink-muted、宽 96px;input 存在 | L4 | P0 |
| TC-BIO-FORM-004 | FR-BIO-008 | 默认值显示 | 默认 cpu=4 | 挂载 | input value=4 | L4 | P0 |
| TC-BIO-FORM-005 | FR-BIO-008 | 引导 UI 显示:来源标注 | 字段含 source | 挂载 | 每字段下方 11px ink-subtle 文案含「默认值来源:阶段契约文档」 | L4 | P0 |
| TC-BIO-FORM-006 | FR-BIO-008 | 来源标注多类型 | 来源=参数预填值 | 挂载 | 标注文案区分「契约文档」与「参数预填」两来源 | L4 | P1 |
| TC-BIO-FORM-007 | FR-BIO-009 | 引导操作:编辑参数 | input cpu | 输入 8 | v-model 值=8;无校验拦截 | L4 | P0 |
| TC-BIO-FORM-008 | FR-BIO-009 | 继续按钮执行 | 已改 cpu=8 | 点击「继续」 | 发出 confirm 请求 body.params.cpu=8 | L4 | P0 |
| TC-BIO-FORM-009 | FR-BIO-009 | 继续按钮样式 | 挂载 | 检查 | 「继续」--pa-gradient 白字 12.5px/600;r-md;padding 7px 16px | L4 | P1 |
| TC-BIO-FORM-010 | FR-BIO-010 | 自动连续开关存在 | 挂载 | 检查 | 「自动连续执行」标签 12px ink-muted + switch(mode-pill 同款) | L4 | P0 |
| TC-BIO-FORM-011 | FR-BIO-010 | 引导操作:开启自动连续 | 开关关 | 点击开关 | switch 状态=开;随表单提交 auto_continue=true;后续阶段不再出表单卡 | L4 | P0 |
| TC-BIO-FORM-012 | FR-BIO-010 | 自动连续可关闭 | 开关开 | 点击 | 状态=关;切回手动(下一阶段仍出表单) | L4 | P0 |
| TC-BIO-FORM-013 | FR-BIO-008 | input 聚焦态 | 未聚焦 | 聚焦 input | border-color=var(--pa-g-from)(focus 态) | L4 | P1 |
| TC-BIO-FORM-014 | FR-BIO-008 | 数字参数类型校验 | cpu 字段 | 输入非数字「abc」 | 提交被拦截/请求不发出;显示类型错误提示 | L4 | P0 |
| TC-BIO-FORM-015 | FR-BIO-008 | 必填参数空值 | 必填字段清空 | 点继续 | 不发出请求;该字段标错 | L4 | P1 |
| TC-BIO-FORM-016 | FR-BIO-008 | 范围校验 | 字段 min=1 max=64 | 输入 999 | 校验提示(1-64);不提交 | L4 | P1 |
| TC-BIO-FORM-017 | FR-BIO-008 | 可选参数留空 | 可选字段 | 留空提交 | 请求体不含该字段(或 null);后端按默认 | L4 | P1 |
| TC-BIO-FORM-018 | FR-BIO-009 | 提交中继续按钮禁用 | mock 慢响应 | 点击继续 | 按钮 disabled+加载中态(spinner);不重复提交 | L4 | P0 |
| TC-BIO-FORM-019 | FR-BIO-009 | 提交失败可重试 | mock confirm 500 | 点击继续 | 显示错误;按钮恢复可点;可再次提交 | L4 | P1 |
| TC-BIO-FORM-020 | FR-BIO-023 | 复用预填显示 | 归档预填 cpu=16 标注来源=存档 | 挂载 | input=16;来源标注=存档名称 | L4 | P0 |
| TC-BIO-FORM-021 | FR-BIO-008 | 多阶段表单逐阶段出现 | 手动模式 3 阶段 | 推进 | 每阶段执行前都渲染该阶段表单(标题阶段名更新) | L4 | P0 |
| TC-BIO-FORM-022 | FR-BIO-008 | 表单关闭时机 | 阶段已 running | 事件应用 | 表单卡消失/折叠(不再可编辑) | L4 | P1 |
| TC-BIO-FORM-023 | FR-BIO-008 | 键盘 Enter 提交 | input 聚焦 | 按 Enter | 触发继续(同点击) | L4 | P1 |
| TC-BIO-FORM-024 | FR-BIO-008 | Esc 放弃编辑 | 已改未提交 | 按 Esc | 恢复默认值(或提示放弃,两态断言其一) | L4 | P2 |
6.1.11 FILE 文件引导卡(flow-file-card,L4)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-BIO-FILE-001 | FR-BIO-005 | 引导 UI 显示:缺失提示文案 | 阶段 await_files | 挂载 | 对话出现「请将 xxx 数据文件拖入窗口上传至服务器,或在聊天窗口中指定数据文件的具体路径」文案且点名 xxx 文件名 | L4 | P0 |
| TC-BIO-FILE-002 | FR-BIO-005 | 引导 UI 显示:文件引导卡 | 同上 | 挂载 | .flow-file-card 存在;内含拖放区与路径输入行 | L4 | P0 |
| TC-BIO-FILE-003 | FR-BIO-006 | 引导操作:拖拽上传 | 本地测试文件 | 拖入拖放区 | 发出 POST /api/bioflow/jobs/{id}/files(multipart);文件名正确 | L4 | P0 |
| TC-BIO-FILE-004 | FR-BIO-006 | XHR 进度百分比 | mock XHR 分片 | 上传 | 进度条 fill 宽度变化且旁注百分比 11px mono(如 45%)逐级上升至 100% | L4 | P0 |
| TC-BIO-FILE-005 | FR-BIO-006 | 进度条令牌复用 | 上传中 | 检查类名 | 使用 prog-track/prog-fill(track surface-2 r-pill 高 4px;fill --pa-gradient) | L4 | P1 |
| TC-BIO-FILE-006 | FR-BIO-006 | 点击上传 | 未拖入 | 点击拖放区 | 打开文件选择框;选择后上传 | L4 | P0 |
| TC-BIO-FILE-007 | FR-BIO-006 | 大文件不断流 | 456MB fixture(L5 mock) | 上传 | 进度连续更新至 100%;无超时错误 | L5-D | P0 |
| TC-BIO-FILE-008 | FR-BIO-007 | 路径输入行存在 | 挂载 | 检查 | input(同 8.2 规格)+「登记路径」pane-btn 同款按钮 | L4 | P0 |
| TC-BIO-FILE-009 | FR-BIO-007 | 引导操作:登记合法路径 | 输入合法服务器路径 | 点「登记路径」 | 发出 POST files {"server_path":路径};成功后显示登记项(含路径与状态) | L4 | P0 |
| TC-BIO-FILE-010 | FR-BIO-007 | 非法路径报错 | 输入 /nonexistent | 登记 | 显示后端 400 错误文案(PATH_NOT_EXIST) | L4 | P0 |
| TC-BIO-FILE-011 | FR-BIO-006 | 上传成功状态 | 上传完成 | 观察 | 进度 100%;文件登记入列表(name/size 显示) | L4 | P0 |
| TC-BIO-FILE-012 | FR-BIO-006 | 上传失败可重试 | mock 500 | 上传 | 错误文案显示;拖放区可再次上传 | L4 | P1 |
| TC-BIO-FILE-013 | FR-BIO-006 | 上传中拖放区禁用重复 | 上传进行中 | 再拖入 | 忽略/禁用(不发起第二个上传) | L4 | P1 |
| TC-BIO-FILE-014 | FR-BIO-006 | 文件满足后卡收起 | 阶段转 running | 观察 | 文件卡消失或标记已完成 | L4 | P1 |
| TC-BIO-FILE-015 | FR-BIO-005 | 缺多文件点名列表 | 缺 fasta+cds | 挂载 | 提示列出两个文件名 | L4 | P1 |
| TC-BIO-FILE-016 | FR-BIO-006 | 拖放区视觉规格 | 挂载 | 检查 computed | border 2px dashed --pa-hairline-strong;r-lg;padding 24px;提示 12px ink-subtle 居中 | L4 | P1 |
| TC-BIO-FILE-017 | FR-BIO-006 | 拖入态高亮 | 拖入悬停 | 检查 | border-color=gradient 45% 混色;背景=gradient 8% 混色 | L4 | P0 |
| TC-BIO-FILE-018 | FR-BIO-006 | 移动端触控上传 | 390×844 触摸 | 点击/长按上传 | 文件选择可用(触控目标≥44px) | L5-M | P1 |
| TC-BIO-FILE-019 | FR-BIO-007 | 路径输入聚焦态 | 未聚焦 | 聚焦 | border=--pa-g-from | L4 | P2 |
| TC-BIO-FILE-020 | FR-BIO-007 | 路径输入 Enter 提交 | 输入合法路径 | 按 Enter | 同点「登记路径」 | L4 | P1 |
| TC-BIO-FILE-021 | FR-BIO-006 | 类型不符文件 | 选择 .exe | 上传 | 前端拦截或后端 422 文案显示 | L4 | P1 |
| TC-BIO-FILE-022 | FR-BIO-006 | 空文件提示 | 0 字节 | 上传 | 按实现断言:提示空文件或成功后 size=0 显示 | L4 | P2 |
6.1.12 PROG 阶段进度卡(bioflow-progress-card,L4)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-BIO-PROG-001 | FR-BIO-011 | 引导 UI 显示:进度卡渲染 | 阶段链确定 | 挂载 | .bioflow-progress-card 存在;复用 pipeline-card 结构(状态点/连接线/相位色令牌) | L4 | P0 |
| TC-BIO-PROG-002 | FR-BIO-011 | 引导操作:逐阶段点亮 | 3 阶段推进 | 应用事件 | 状态点顺序变化:done=--pa-t-done 底白 ✓;running=相位色底●+pulse;waiting=surface-3 底◌ | L4 | P0 |
| TC-BIO-PROG-003 | FR-BIO-011 | 引导 UI 显示:日志尾区 | 阶段 running | 观察 | 仅 running/failed 阶段展开日志区:--pa-code-bg 底、mono 11px、padding 8px 10px、max-height 96px 滚动 | L4 | P0 |
| TC-BIO-PROG-004 | FR-BIO-011 | 日志尾随 SSE 追加 | stage_log×3 | 应用 | 日志文本追加增长;滚动至底部 | L4 | P0 |
| TC-BIO-PROG-005 | FR-BIO-011 | done 阶段日志收起 | 阶段 done | 观察 | 该阶段日志区不展开(仅 running/failed 展开) | L4 | P1 |
| TC-BIO-PROG-006 | FR-BIO-012 | 失败标红 | 阶段 failed | 观察 | 状态点=--pa-error 底 ✕;状态文字 error 色 12px/600 | L4 | P0 |
| TC-BIO-PROG-007 | FR-BIO-012 | 失败三选一按钮出现 | 阶段 failed | 观察 | 重跑/跳过/改参数重跑三按钮(pane-btn 同款 12px,gap 8px)仅 failed 阶段显示 | L4 | P0 |
| TC-BIO-PROG-008 | FR-BIO-012 | 重跑生效 | failed | 点重跑 | 发出 rerun 请求;状态点转 running | L4 | P0 |
| TC-BIO-PROG-009 | FR-BIO-012 | 跳过生效 | failed | 点跳过 | 发出 skip 请求;状态=skipped(--pa-ink-subtle 底◌;文字 ink-subtle) | L4 | P0 |
| TC-BIO-PROG-010 | FR-BIO-012 | 改参数重跑生效 | failed | 点改参数重跑 | 出现参数表单(该阶段);提交后重跑 | L4 | P0 |
| TC-BIO-PROG-011 | FR-BIO-012 | skipped 态视觉 | 阶段 skipped | 检查 | 状态点=--pa-ink-subtle 底◌;文字 ink-subtle | L4 | P1 |
| TC-BIO-PROG-012 | FR-BIO-013 | 折叠分组 | 15 阶段链 | 挂载 | 阶段>10 自动分组折叠;组头 12px/600+展开箭头;默认展开运行中所在组 | L4 | P0 |
| TC-BIO-PROG-013 | FR-BIO-013 | 展开可见全部 | 折叠组 | 点组头 | 展开显示该组全部阶段 | L4 | P0 |
| TC-BIO-PROG-014 | FR-BIO-013 | ≤10 阶段不折叠 | 10 阶段 | 挂载 | 无折叠组头(平铺 10 状态点) | L4 | P1 |
| TC-BIO-PROG-015 | FR-BIO-014 | 断线回放刷新进度卡 | 快照到达 | 应用 | 卡片整体刷新为快照状态(1 done 1 running 1 waiting 精确对应) | L4 | P0 |
| TC-BIO-PROG-016 | FR-BIO-014 | 回放后日志尾恢复 | 快照含 log_tail | 应用 | running 阶段日志区显示快照日志尾 | L4 | P1 |
| TC-BIO-PROG-017 | FR-BIO-010 | 暂停态视觉 | 任务 paused | 观察 | 运行中状态点停止 pulse;显示「已暂停」徽章/文案 | L4 | P0 |
| TC-BIO-PROG-018 | FR-BIO-010 | 恢复后继续 | 任务 paused | 点恢复 | 下一阶段启动(running 状态推进) | L4 | P0 |
| TC-BIO-PROG-019 | FR-BIO-011 | 进度卡与流水线卡同款视觉 | 对比 PipelineCard | 检查 | 结构/状态点/连接线/相位色与 §4.4 pipeline-card 令牌一致(同款) | L4 | P1 |
| TC-BIO-PROG-020 | FR-BIO-012 | 失败后后续阶段 waiting | 阶段 2 failed | 观察 | 阶段 3+ 保持 waiting 不高亮 | L4 | P1 |
| TC-BIO-PROG-021 | FR-BIO-024 | 任务面板进度视图复用 | 面板内 | 观察 | 面板 DAG 与进度卡状态一致 | L4 | P1 |
| TC-BIO-PROG-022 | FR-BIO-012 | 三选一按钮键盘可达 | failed | Tab 至重跑按钮按 Enter | 触发重跑 | L4 | P1 |
| TC-BIO-PROG-023 | FR-BIO-011 | 日志尾 max-height 滚动 | 日志 >6 行 | 检查 computed | max-height=96px;overflow-y=auto | L4 | P2 |
| TC-BIO-PROG-024 | FR-BIO-011 | 移动端不溢出 | 390×844 | 挂载 | 卡片/日志区宽度≤容器;无横向滚动 | L5-M | P1 |
6.1.13 ARCH 存档提示卡(flow-archive-card,L4)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-BIO-ARCH-001 | FR-BIO-020 | 引导 UI 显示:存档提示 | 任务 job_done | 观察 | 对话出现「本次生信任务已完成,是否存档?可按你的要求命名并描述」12.5px | L4 | P0 |
| TC-BIO-ARCH-002 | FR-BIO-020 | 引导操作:命名输入 | 提示卡存在 | 输入名称 | input 接受文本;无长度异常 | L4 | P0 |
| TC-BIO-ARCH-003 | FR-BIO-020 | 引导操作:描述输入 | 同上 | 输入描述 | 描述值随提交发送 | L4 | P0 |
| TC-BIO-ARCH-004 | FR-BIO-020 | 引导操作:点存档 | 已命名 | 点「存档」 | 发出 POST /api/bioflow/archives;body 含 job_id/name/description | L4 | P0 |
| TC-BIO-ARCH-005 | FR-BIO-020 | 存档按钮样式 | 挂载 | 检查 | 「存档」--pa-gradient 12.5px/600;「放弃」pane-btn 同款 12px | L4 | P1 |
| TC-BIO-ARCH-006 | FR-BIO-020 | 引导操作:放弃 | 提示卡存在 | 点「放弃」 | 卡片消失;无 POST /api/bioflow/archives 请求;任务无副作用 | L4 | P0 |
| TC-BIO-ARCH-007 | FR-BIO-021 | 引导 UI 显示:存档状态回复 | 存档完成事件 | 观察 | 消息显示存档状态:名称/位置/大小三要素 | L4 | P0 |
| TC-BIO-ARCH-008 | FR-BIO-021 | 名称缺省提交拦截 | 名称空 | 点存档 | 按钮禁用或提交被拦截(不发出空 name 请求) | L4 | P1 |
| TC-BIO-ARCH-009 | FR-BIO-021 | 存档中加载态 | mock 慢 | 点存档 | 「存档」按钮 disabled+spinner;完成后恢复 | L4 | P1 |
| TC-BIO-ARCH-010 | FR-BIO-021 | 存档失败提示 | mock 500 | 点存档 | 错误文案;按钮恢复可重试 | L4 | P1 |
| TC-BIO-ARCH-011 | FR-BIO-020 | 放弃后不重复提示 | 已放弃 | 观察 | 同一任务不再弹存档提示(或仅一次) | L4 | P2 |
| TC-BIO-ARCH-012 | FR-BIO-020 | 任务未完成无提示 | 任务 running | 观察 | 无存档提示卡 | L4 | P1 |
6.1.14 JOB 生信任务面板(biojobs-pane,L4)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-BIO-JOB-001 | FR-BIO-024 | 面板容器与 TAB | 服务可达 | 打开 | .biojobs-pane 存在;TAB 走 bench-tab 样式 | L4 | P0 |
| TC-BIO-JOB-002 | FR-BIO-024 | 任务列表渲染 | 3 任务 | 打开 | 3 个 session-item 形态列表项:标题 13px+状态徽章 | L4 | P0 |
| TC-BIO-JOB-003 | FR-BIO-024 | 多任务浏览流畅 | 25 任务 | 滚动列表 | 列表渲染流畅(虚拟滚动或分页);无卡顿崩溃 | L5-D | P1 |
| TC-BIO-JOB-004 | FR-BIO-024 | 阶段 DAG 渲染 | 选中任务 | 查看 | 纵向 2px hairline 连接线;节点 8px 圆点按阶段状态取色 | L4 | P0 |
| TC-BIO-JOB-005 | FR-BIO-024 | DAG 状态取色 | 1 done 1 failed 1 running | 查看 | 三节点颜色分别=done/error/相位色 | L4 | P1 |
| TC-BIO-JOB-006 | FR-BIO-024 | manifest/日志浏览 | 阶段 done | 打开 | code-block 渲染(mono 12px,code-bg,滚动);manifest 与日志尾均可读 | L4 | P0 |
| TC-BIO-JOB-007 | FR-BIO-024 | 重跑按钮 | 任务 failed | 点重跑 | 发出 rerun 请求;面板状态更新 | L4 | P0 |
| TC-BIO-JOB-008 | FR-BIO-024 | 删除任务 | 任务存在 | 点删除+确认 | 发出 DELETE;列表移除 | L4 | P1 |
| TC-BIO-JOB-009 | FR-BIO-024 | 运行中删除禁用 | 任务 running | 检查 | 删除按钮禁用(409 预期) | L4 | P1 |
| TC-BIO-JOB-010 | FR-BIO-024 | 空任务列表 | 无任务 | 打开 | 空态文案显示 | L4 | P2 |
| TC-BIO-JOB-011 | FR-BIO-024 | 任务详情实时更新 | 任务 running | 观察 | 面板状态随 SSE 事件实时刷新 | L4 | P0 |
| TC-BIO-JOB-012 | FR-BIO-025 | 探活失败隐藏 TAB | health 不可达 | 初始化 | 「生信任务」TAB 不渲染 | L4 | P0 |
| TC-BIO-JOB-013 | FR-BIO-025 | 探活恢复显示 TAB | health 恢复 | 刷新 | TAB 出现 | L4 | P0 |
| TC-BIO-JOB-014 | FR-BIO-024 | 移动端 TAB 条接入 | 390×844 | 打开 | 生信 TAB 出现在移动端 tab 条;TAB 数断言更新 | L5-M | P1 |
| TC-BIO-JOB-015 | FR-BIO-024 | 进度数字显示 | 任务 33% | 查看 | 列表/详情显示进度 33% | L4 | P1 |
| TC-BIO-JOB-016 | FR-BIO-024 | 日志尾 80 行上限显示 | 日志 200 行 | 查看 | 面板显示 80 行(后端截断后原样展示) | L4 | P1 |
6.1.15 PANE 生信档案面板(bioarchive-pane,L4)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-BIO-PANE-001 | FR-BIO-022 | 面板容器与 TAB | 服务可达 | 打开 | .bioarchive-pane 存在;TAB 走 bench-tab | L4 | P0 |
| TC-BIO-PANE-002 | FR-BIO-022 | 档案列表 | 3 归档 | 打开 | 3 个列表项(标题+状态徽章/时间)按时间倒序 | L4 | P0 |
| TC-BIO-PANE-003 | FR-BIO-022 | 档案详情回看 | 选中归档 | 点开 | 显示详情:阶段链/参数/产物文件清单/报告 | L4 | P0 |
| TC-BIO-PANE-004 | FR-BIO-022 | 报告产物查看 | 归档含报告 | 详情内 | 报告可预览(HTML 渲染或打开) | L4 | P0 |
| TC-BIO-PANE-005 | FR-BIO-022 | 中间文件清单 | 归档含中间文件 | 详情 | 产物清单含中间文件条目 | L4 | P1 |
| TC-BIO-PANE-006 | FR-BIO-022 | 删除归档 | 选中归档 | 点删除+确认 | 发出 DELETE;列表移除;磁盘目录删除 | L4 | P0 |
| TC-BIO-PANE-007 | FR-BIO-022 | 删除二次确认 | 归档存在 | 点删除→取消 | 无 DELETE 请求 | L4 | P1 |
| TC-BIO-PANE-008 | FR-BIO-023 | 复用发起按钮 | 选中归档 | 点「复用发起」 | 发出 POST archives/{id}/run 或打开复用表单 | L4 | P0 |
| TC-BIO-PANE-009 | FR-BIO-023 | 复用预填表单 | 复用发起后 | 观察 | 参数表单出现且预填=存档参数 | L4 | P0 |
| TC-BIO-PANE-010 | FR-BIO-023 | 复用发起新任务 | 预填确认 | 确认 | 新任务出现在生信任务面板 | L4 | P0 |
| TC-BIO-PANE-011 | FR-BIO-022 | 空档案列表 | 无归档 | 打开 | 空态文案显示 | L4 | P2 |
| TC-BIO-PANE-012 | FR-BIO-022 | 归档大小显示 | 归档 1.2GB | 列表 | 大小显示(人类可读格式) | L4 | P2 |
| TC-BIO-PANE-013 | FR-BIO-025 | 探活失败隐藏档案 TAB | health 不可达 | 初始化 | 「生信档案」TAB 不渲染 | L4 | P0 |
| TC-BIO-PANE-014 | FR-BIO-025 | 探活恢复显示档案 TAB | health 恢复 | 刷新 | TAB 出现 | L4 | P0 |
| TC-BIO-PANE-015 | FR-BIO-022 | 移动端面板可切换 | 390×844 | 切到档案 TAB | 面板正常显示;列表可滚动 | L5-M | P1 |
| TC-BIO-PANE-016 | FR-BIO-023 | 复用按钮键盘可达 | 选中归档 | Tab+Enter | 触发复用发起 | L4 | P2 |
6.1.16 ACT UI 动作矩阵(每条 TC = 一个可交互元素 × 一个动作;TEST_PLAN §10.3)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-BIO-ACT-001 | FR-BIO-002 | 路径卡候选行·点击 | 候选 2 条 | 点击候选行 | 选中态样式生效(border/背景变化);回调参数=该行索引 | L4 | P0 |
| TC-BIO-ACT-002 | FR-BIO-002 | 路径卡候选行·双击 | 未选中 | 双击候选行 | 视为两次点击:状态保持选中;不产生重复回调 | L4 | P1 |
| TC-BIO-ACT-003 | FR-BIO-002 | 路径卡候选行·悬停 | 未选中 | hover 行 | 背景=surface-3 | L4 | P0 |
| TC-BIO-ACT-004 | FR-BIO-002 | 路径卡候选行·悬停移出 | 悬停中 | mouseleave | 背景恢复 surface-1;选中态不丢 | L4 | P1 |
| TC-BIO-ACT-005 | FR-BIO-002 | 路径卡候选行·键盘 Enter | 行聚焦 | 按 Enter | 选中该行(同点击) | L4 | P0 |
| TC-BIO-ACT-006 | FR-BIO-002 | 路径卡候选行·键盘 Esc | 弹层/聚焦态 | 按 Esc | 关闭弹层或取消聚焦,不改变已确认状态 | L4 | P2 |
| TC-BIO-ACT-007 | FR-BIO-002 | 确认按钮·点击 | 已选中 | 点击 | 触发确认回调一次 | L4 | P0 |
| TC-BIO-ACT-008 | FR-BIO-002 | 确认按钮·双击 | 已选中 | 双击 | 只触发一次回调(防抖) | L4 | P1 |
| TC-BIO-ACT-009 | FR-BIO-002 | 确认按钮·悬停 | 未选中 | hover | 视觉反馈(渐变增亮);功能仍禁用 | L4 | P2 |
| TC-BIO-ACT-010 | FR-BIO-002 | 确认按钮·键盘 Enter | 按钮聚焦且已选中 | 按 Enter | 触发确认 | L4 | P0 |
| TC-BIO-ACT-011 | FR-BIO-002 | 确认按钮·键盘 Esc | 按钮聚焦 | 按 Esc | 取消聚焦;无确认 | L4 | P2 |
| TC-BIO-ACT-012 | FR-BIO-002 | 确认按钮·禁用态 | 未选中 | 检查 | disabled;opacity=0.45;点击无回调 | L4 | P0 |
| TC-BIO-ACT-013 | FR-BIO-002 | 确认按钮·加载中态 | 确认请求中(mock 慢) | 检查 | disabled;spinner 显示;再次点击无重复请求 | L4 | P0 |
| TC-BIO-ACT-014 | FR-BIO-008 | 表单输入框·点击聚焦 | input | 点击 | input 获得焦点;focus border=--pa-g-from | L4 | P0 |
| TC-BIO-ACT-015 | FR-BIO-008 | 表单输入框·失焦 | 聚焦中 | 点击别处 | blur 触发;边框恢复;若有校验立即提示 | L4 | P0 |
| TC-BIO-ACT-016 | FR-BIO-008 | 表单输入框·键盘 Enter | input 聚焦 | 按 Enter | 触发继续(提交) | L4 | P0 |
| TC-BIO-ACT-017 | FR-BIO-008 | 表单输入框·键盘 Esc | input 聚焦已改 | 按 Esc | 撤销本次编辑恢复原值或放弃(两态断言其一) | L4 | P1 |
| TC-BIO-ACT-018 | FR-BIO-008 | 表单输入框·禁用态 | 阶段已 running | 检查 | input disabled | L4 | P0 |
| TC-BIO-ACT-019 | FR-BIO-008 | 表单输入框·悬停 | 未聚焦 | hover | 边框 hairline 不变(仅 focus 变渐变) | L4 | P2 |
| TC-BIO-ACT-020 | FR-BIO-009 | 继续按钮·点击 | 已编辑 | 点击 | 发出 confirm;参数=表单值 | L4 | P0 |
| TC-BIO-ACT-021 | FR-BIO-009 | 继续按钮·双击 | 可提交 | 双击 | 仅一次请求(提交中禁用) | L4 | P1 |
| TC-BIO-ACT-022 | FR-BIO-009 | 继续按钮·悬停 | 可提交 | hover | 渐变增亮反馈 | L4 | P2 |
| TC-BIO-ACT-023 | FR-BIO-009 | 继续按钮·键盘 Enter | 按钮聚焦 | 按 Enter | 提交 | L4 | P0 |
| TC-BIO-ACT-024 | FR-BIO-009 | 继续按钮·键盘 Esc | 按钮聚焦 | 按 Esc | 取消聚焦;不提交 | L4 | P2 |
| TC-BIO-ACT-025 | FR-BIO-009 | 继续按钮·禁用态 | 校验不通过 | 检查 | disabled;点击无请求 | L4 | P0 |
| TC-BIO-ACT-026 | FR-BIO-009 | 继续按钮·加载中态 | 提交中 | 检查 | disabled+spinner | L4 | P0 |
| TC-BIO-ACT-027 | FR-BIO-010 | 自动连续开关·点击开 | 开关关 | 点击 | switch 状态=开;auto_continue=true 提交 | L4 | P0 |
| TC-BIO-ACT-028 | FR-BIO-010 | 自动连续开关·点击关 | 开关开 | 点击 | 状态=关;切回手动 | L4 | P0 |
| TC-BIO-ACT-029 | FR-BIO-010 | 自动连续开关·双击 | 关 | 双击 | 最终状态=开(两次切换);无异常 | L4 | P2 |
| TC-BIO-ACT-030 | FR-BIO-010 | 自动连续开关·悬停 | 任意 | hover | 光标指针/背景反馈;不切换状态 | L4 | P2 |
| TC-BIO-ACT-031 | FR-BIO-010 | 自动连续开关·键盘 Enter | 开关聚焦 | 按 Enter | 切换状态 | L4 | P1 |
| TC-BIO-ACT-032 | FR-BIO-010 | 自动连续开关·键盘 Esc | 开关聚焦 | 按 Esc | 取消聚焦;状态不变 | L4 | P2 |
| TC-BIO-ACT-033 | FR-BIO-010 | 自动连续开关·禁用态 | 任务已暂停/未开始 | 检查 | disabled(按实现两态断言其一) | L4 | P1 |
| TC-BIO-ACT-034 | FR-BIO-006 | 拖放区·点击 | 未选择 | 点击 | 打开文件选择框(file input 触发) | L4 | P0 |
| TC-BIO-ACT-035 | FR-BIO-006 | 拖放区·悬停 | 未拖入 | hover | 样式不变(非拖入态) | L4 | P1 |
| TC-BIO-ACT-036 | FR-BIO-006 | 拖放区·拖入悬停 | 拖拽悬停中 | dragover | 拖入态:border=gradient 45%;背景=gradient 8% | L4 | P0 |
| TC-BIO-ACT-037 | FR-BIO-006 | 拖放区·离开 | 拖入中 | dragleave | 拖入态移除,恢复 dashed hairline-strong | L4 | P0 |
| TC-BIO-ACT-038 | FR-BIO-006 | 拖放区·拖入释放 | 拖入文件 | drop | 触发上传(POST multipart);进度出现 | L4 | P0 |
| TC-BIO-ACT-039 | FR-BIO-006 | 拖放区·禁用态 | 上传进行中 | 检查 | 再拖入不触发(忽略/禁用) | L4 | P0 |
| TC-BIO-ACT-040 | FR-BIO-006 | 拖放区·加载中态 | 上传中 | 检查 | 进度条可见;拖放区提示变化(百分比) | L4 | P0 |
| TC-BIO-ACT-041 | FR-BIO-007 | 路径输入行·点击聚焦 | input | 点击 | 焦点获得;边框渐变 | L4 | P0 |
| TC-BIO-ACT-042 | FR-BIO-007 | 路径输入行·失焦 | 聚焦中 | 移开 | 边框恢复 | L4 | P1 |
| TC-BIO-ACT-043 | FR-BIO-007 | 路径输入行·键盘 Enter | 已输入路径 | 按 Enter | 触发登记(同点按钮) | L4 | P0 |
| TC-BIO-ACT-044 | FR-BIO-007 | 路径输入行·键盘 Esc | 聚焦已输入 | 按 Esc | 清空输入或取消(两态断言其一) | L4 | P2 |
| TC-BIO-ACT-045 | FR-BIO-007 | 登记路径按钮·点击 | 合法路径 | 点击 | 发出登记请求 | L4 | P0 |
| TC-BIO-ACT-046 | FR-BIO-007 | 登记路径按钮·悬停 | 任意 | hover | pane-btn 悬停反馈;不触发请求 | L4 | P2 |
| TC-BIO-ACT-047 | FR-BIO-007 | 登记路径按钮·键盘 Enter | 按钮聚焦 | 按 Enter | 触发登记 | L4 | P1 |
| TC-BIO-ACT-048 | FR-BIO-007 | 登记路径按钮·禁用态 | input 空 | 检查 | disabled;点击无请求 | L4 | P0 |
| TC-BIO-ACT-049 | FR-BIO-007 | 登记路径按钮·加载中态 | 登记请求中 | 检查 | disabled+spinner | L4 | P1 |
| TC-BIO-ACT-050 | FR-BIO-012 | 重跑按钮·点击 | 阶段 failed | 点击 | 发出 rerun 请求 | L4 | P0 |
| TC-BIO-ACT-051 | FR-BIO-012 | 跳过按钮·点击 | 阶段 failed | 点击 | 发出 skip 请求;状态=skipped | L4 | P0 |
| TC-BIO-ACT-052 | FR-BIO-012 | 改参数重跑按钮·点击 | 阶段 failed | 点击 | 弹出该阶段参数表单 | L4 | P0 |
| TC-BIO-ACT-053 | FR-BIO-012 | 三选一按钮·悬停 | 阶段 failed | hover 每个按钮 | pane-btn 悬停反馈 | L4 | P2 |
| TC-BIO-ACT-054 | FR-BIO-012 | 三选一按钮·键盘 Enter | 重跑按钮聚焦 | 按 Enter | 触发重跑 | L4 | P0 |
| TC-BIO-ACT-055 | FR-BIO-012 | 三选一按钮·键盘 Esc | 改参数表单弹出 | 按 Esc | 表单关闭,不提交 | L4 | P1 |
| TC-BIO-ACT-056 | FR-BIO-012 | 三选一按钮·加载中态 | 重跑请求中 | 检查 | 三按钮 disabled | L4 | P1 |
| TC-BIO-ACT-057 | FR-BIO-012 | 三选一按钮·禁用态 | 阶段非 failed | 检查 | 按钮不渲染(仅 failed 显示) | L4 | P0 |
| TC-BIO-ACT-058 | FR-BIO-013 | 折叠组头·点击 | 15 阶段链折叠组 | 点击组头 | 展开/收起切换;箭头方向变化 | L4 | P0 |
| TC-BIO-ACT-059 | FR-BIO-013 | 折叠组头·双击 | 折叠组 | 双击 | 最终状态=与初始相反(两次切换) | L4 | P2 |
| TC-BIO-ACT-060 | FR-BIO-013 | 折叠组头·悬停 | 折叠组 | hover | 组头悬停反馈 | L4 | P2 |
| TC-BIO-ACT-061 | FR-BIO-013 | 折叠组头·键盘 Enter | 组头聚焦 | 按 Enter | 切换展开/收起 | L4 | P1 |
| TC-BIO-ACT-062 | FR-BIO-013 | 折叠组头·键盘 Esc | 展开中 | 按 Esc | 收起(或保持,两态断言其一) | L4 | P2 |
| TC-BIO-ACT-063 | FR-BIO-024 | 面板操作按钮(重跑)·点击 | 任务 failed | 点击 | 发出 rerun | L4 | P0 |
| TC-BIO-ACT-064 | FR-BIO-024 | 面板操作按钮(删除)·点击 | 任务存在 | 点击 | 弹确认层 | L4 | P0 |
| TC-BIO-ACT-065 | FR-BIO-024 | 面板操作按钮·悬停 | 任务行 | hover | pane-btn 悬停反馈 | L4 | P2 |
| TC-BIO-ACT-066 | FR-BIO-024 | 面板操作按钮·键盘 Enter | 删除按钮聚焦 | 按 Enter | 弹确认层 | L4 | P1 |
| TC-BIO-ACT-067 | FR-BIO-024 | 面板操作按钮·键盘 Esc | 确认层弹出 | 按 Esc | 关闭确认层不删除 | L4 | P1 |
| TC-BIO-ACT-068 | FR-BIO-024 | 面板操作按钮·禁用态 | 任务 running | 检查删除按钮 | disabled | L4 | P0 |
| TC-BIO-ACT-069 | FR-BIO-024 | 面板操作按钮·加载中态 | 重跑请求中 | 检查 | disabled+spinner | L4 | P1 |
| TC-BIO-ACT-070 | FR-BIO-023 | 面板复用发起按钮·点击 | 选中归档 | 点击 | 打开复用表单(预填) | L4 | P0 |
| TC-BIO-ACT-071 | FR-BIO-023 | 面板复用发起按钮·悬停 | 选中归档 | hover | 悬停反馈 | L4 | P2 |
| TC-BIO-ACT-072 | FR-BIO-023 | 面板复用发起按钮·键盘 Enter | 按钮聚焦 | 按 Enter | 打开复用表单 | L4 | P1 |
| TC-BIO-ACT-073 | FR-BIO-023 | 面板复用发起按钮·加载中态 | 表单加载中 | 检查 | disabled+spinner | L4 | P1 |
| TC-BIO-ACT-074 | FR-BIO-020 | 存档名称输入·点击聚焦 | 存档提示卡 | 点击 | 焦点;边框渐变 | L4 | P0 |
| TC-BIO-ACT-075 | FR-BIO-020 | 存档名称输入·失焦 | 聚焦中 | 移开 | 边框恢复 | L4 | P1 |
| TC-BIO-ACT-076 | FR-BIO-020 | 存档名称输入·键盘 Enter | 已输入名称 | 按 Enter | 触发存档 | L4 | P0 |
| TC-BIO-ACT-077 | FR-BIO-020 | 存档名称输入·键盘 Esc | 聚焦中 | 按 Esc | 清空或取消(两态断言其一) | L4 | P2 |
| TC-BIO-ACT-078 | FR-BIO-020 | 存档名称输入·禁用态 | 存档请求中 | 检查 | disabled | L4 | P0 |
| TC-BIO-ACT-079 | FR-BIO-020 | 存档按钮·点击 | 已命名 | 点击 | 发出 POST archives | L4 | P0 |
| TC-BIO-ACT-080 | FR-BIO-020 | 存档按钮·双击 | 可提交 | 双击 | 仅一次请求 | L4 | P1 |
| TC-BIO-ACT-081 | FR-BIO-020 | 存档按钮·悬停 | 可提交 | hover | 渐变增亮 | L4 | P2 |
| TC-BIO-ACT-082 | FR-BIO-020 | 存档按钮·键盘 Enter | 按钮聚焦 | 按 Enter | 触发存档 | L4 | P1 |
| TC-BIO-ACT-083 | FR-BIO-020 | 存档按钮·禁用态 | 名称空 | 检查 | disabled | L4 | P0 |
| TC-BIO-ACT-084 | FR-BIO-020 | 存档按钮·加载中态 | 存档中 | 检查 | disabled+spinner | L4 | P0 |
| TC-BIO-ACT-085 | FR-BIO-020 | 放弃按钮·点击 | 存档提示卡 | 点击 | 卡片消失;无请求 | L4 | P0 |
| TC-BIO-ACT-086 | FR-BIO-020 | 放弃按钮·悬停 | 提示卡 | hover | pane-btn 悬停反馈 | L4 | P2 |
| TC-BIO-ACT-087 | FR-BIO-020 | 放弃按钮·键盘 Enter | ���钮聚焦 | 按 Enter | 放弃(卡片消失) | L4 | P1 |
| TC-BIO-ACT-088 | FR-BIO-020 | 放弃按钮·键盘 Esc | 按钮聚焦 | 按 Esc | 取消聚焦;卡片保留 | L4 | P2 |
| TC-BIO-ACT-089 | FR-BIO-020 | 放弃按钮·加载中态 | 存档请求中 | 检查 | 放弃按钮 disabled(防误操作) | L4 | P1 |
| TC-BIO-ACT-090 | FR-BIO-024 | 面板列表项·点击 | 任务列表 | 点击任务项 | 选中并展开详情(DAG 显示) | L4 | P0 |
| TC-BIO-ACT-091 | FR-BIO-024 | 面板列表项·悬停 | 列表 | hover | session-item 悬停反馈 | L4 | P1 |
| TC-BIO-ACT-092 | FR-BIO-022 | 档案列表项·点击 | 档案列表 | 点击 | 选中并显示详情 | L4 | P0 |
| TC-BIO-ACT-093 | FR-BIO-022 | 档案列表项·悬停 | 列表 | hover | 悬停反馈 | L4 | P1 |
| TC-BIO-ACT-094 | FR-BIO-011 | 进度卡日志区·点击滚动 | 日志溢出 | 点击日志区 | 区域获得焦点可滚动;不触发其他动作 | L4 | P2 |
| TC-BIO-ACT-095 | FR-BIO-011 | 进度卡日志区·悬停 | 日志溢出 | hover | 显示滚动条/悬停反馈 | L4 | P2 |
6.1.17 E2E 端到端主线(TEST_PLAN §11 九条 × 三档视口 M/T/D)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-BIO-E2E-001-M | FR-BIO-002/004 | E2E-01 主流程·移动端:候选路径卡出现 | mock LLM 正常;390×844 | 发送「帮我跑水稻 SPL 家族鉴定」 | 对话出现 .flow-path-card;候选行数量∈[2,3];每行含阶段序列文本 | L5-M | P0 |
| TC-BIO-E2E-002-M | FR-BIO-004 | E2E-01 主流程·移动端:点选与确认 | 候选卡已出现 | 点击第 1 候选行→点「确认此路径」 | 路径确认卡出现(逐阶段名称/用途/预计耗时);发出 POST /api/bioflow/jobs | L5-M | P0 |
| TC-BIO-E2E-003-M | FR-BIO-004 | E2E-01 主流程·移动端:任务面板出现新任务 | 任务已创建 | 切到「生信任务」TAB | 列表含新任务;状态=created | L5-M | P0 |
| TC-BIO-E2E-004-M | FR-BIO-005 | E2E-01 主流程·移动端:文件引导卡 | 起始阶段缺 fasta | 等待推进 | 对话出现缺文件提示(点名 fasta)+ .flow-file-card | L5-M | P0 |
| TC-BIO-E2E-005-M | FR-BIO-006 | E2E-01 主流程·移动端:拖拽上传金标数据 | 本地金标输入可用 | 拖入 Ft.SPL pep 文件 | 进度条百分比逐级推进至 100%;POST files 发出 | L5-M | P0 |
| TC-BIO-E2E-006-M | FR-BIO-008/009 | E2E-01 主流程·移动端:参数表单改一个参数 | 阶段待确认 | 表单卡出现后改 cpu=8→点「继续」 | 发出 confirm;请求体 params.cpu=8;阶段 running | L5-M | P0 |
| TC-BIO-E2E-007-M | FR-BIO-011 | E2E-01 主流程·移动端:进度卡逐阶段流转 | mock 全链 | 观察 | 状态点逐阶段点亮(waiting→running→done);运行中日志尾滚动更新 | L5-M | P0 |
| TC-BIO-E2E-008-M | FR-BIO-016 | E2E-01 主流程·移动端:报告预览 | 任务完成报告登记 | 切文档 TAB 打开 DocPane | 报告出现;预览白底(background=#FFFFFF);图可见 | L5-M | P0 |
| TC-BIO-E2E-009-M | FR-BIO-018 | E2E-01 主流程·移动端:导出 PDF | 报告已打开 | 点导出 PDF | 下载事件触发;文件落盘且可打开(非 0 字节) | L5-M | P1 |
| TC-BIO-E2E-010-M | FR-BIO-020/021 | E2E-01 主流程·移动端:存档提示→存档→状态回复 | 任务完成 | 观察提示卡→输入名称→点存档 | POST archives 发出;回复消息含名称/位置/大小三要素 | L5-M | P0 |
| TC-BIO-E2E-011-M | FR-BIO-024 | E2E-01 主流程·移动端:档案面板出现 | 已存档 | 切「生信档案」TAB | 列表含新档案(名称正确) | L5-M | P0 |
| TC-BIO-E2E-012-M | FR-BIO-027 | E2E-01 主流程·移动端:布局不溢出 | 全程 | 观察各步骤 | .flow-path-card/.flow-form-card/.flow-file-card/.bioflow-progress-card 宽≤容器;无横向滚动 | L5-M | P1 |
| TC-BIO-E2E-001-T | FR-BIO-002/004 | E2E-01 主流程·平板:候选路径卡出现 | mock LLM 正常;768×1024 | 发送「帮我跑水稻 SPL 家族鉴定」 | 对话出现 .flow-path-card;候选行数量∈[2,3];每行含阶段序列文本 | L5-T | P0 |
| TC-BIO-E2E-002-T | FR-BIO-004 | E2E-01 主流程·平板:点选与确认 | 候选卡已出现 | 点击第 1 候选行→点「确认此路径」 | 路径确认卡出现(逐阶段名称/用途/预计耗时);发出 POST /api/bioflow/jobs | L5-T | P0 |
| TC-BIO-E2E-003-T | FR-BIO-004 | E2E-01 主流程·平板:任务面板出现新任务 | 任务已创建 | 切到「生信任务」TAB | 列表含新任务;状态=created | L5-T | P0 |
| TC-BIO-E2E-004-T | FR-BIO-005 | E2E-01 主流程·平板:文件引导卡 | 起始阶段缺 fasta | 等待推进 | 对话出现缺文件提示(点名 fasta)+ .flow-file-card | L5-T | P0 |
| TC-BIO-E2E-005-T | FR-BIO-006 | E2E-01 主流程·平板:拖拽上传金标数据 | 本地金标输入可用 | 拖入 Ft.SPL pep 文件 | 进度条百分比逐级推进至 100%;POST files 发出 | L5-T | P0 |
| TC-BIO-E2E-006-T | FR-BIO-008/009 | E2E-01 主流程·平板:参数表单改一个参数 | 阶段待确认 | 表单卡出现后改 cpu=8→点「继续」 | 发出 confirm;请求体 params.cpu=8;阶段 running | L5-T | P0 |
| TC-BIO-E2E-007-T | FR-BIO-011 | E2E-01 主流程·平板:进度卡逐阶段流转 | mock 全链 | 观察 | 状态点逐阶段点亮(waiting→running→done);运行中日志尾滚动更新 | L5-T | P0 |
| TC-BIO-E2E-008-T | FR-BIO-016 | E2E-01 主流程·平板:报告预览 | 任务完成报告登记 | 切文档 TAB 打开 DocPane | 报告出现;预览白底(background=#FFFFFF);图可见 | L5-T | P0 |
| TC-BIO-E2E-009-T | FR-BIO-018 | E2E-01 主流程·平板:导出 PDF | 报告已打开 | 点导出 PDF | 下载事件触发;文件落盘且可打开(非 0 字节) | L5-T | P1 |
| TC-BIO-E2E-010-T | FR-BIO-020/021 | E2E-01 主流程·平板:存档提示→存档→状态回复 | 任务完成 | 观察提示卡→输入名称→点存档 | POST archives 发出;回复消息含名称/位置/大小三要素 | L5-T | P0 |
| TC-BIO-E2E-011-T | FR-BIO-024 | E2E-01 主流程·平板:档案面板出现 | 已存档 | 切「生信档案」TAB | 列表含新档案(名称正确) | L5-T | P0 |
| TC-BIO-E2E-012-T | FR-BIO-027 | E2E-01 主流程·平板:布局不溢出 | 全程 | 观察各步骤 | .flow-path-card/.flow-form-card/.flow-file-card/.bioflow-progress-card 宽≤容器;无横向滚动 | L5-T | P1 |
| TC-BIO-E2E-001-D | FR-BIO-002/004 | E2E-01 主流程·桌面:候选路径卡出现 | mock LLM 正常;1440×900 | 发送「帮我跑水稻 SPL 家族鉴定」 | 对话出现 .flow-path-card;候选行数量∈[2,3];每行含阶段序列文本 | L5-D | P0 |
| TC-BIO-E2E-002-D | FR-BIO-004 | E2E-01 主流程·桌面:点选与确认 | 候选卡已出现 | 点击第 1 候选行→点「确认此路径」 | 路径确认卡出现(逐阶段名称/用途/预计耗时);发出 POST /api/bioflow/jobs | L5-D | P0 |
| TC-BIO-E2E-003-D | FR-BIO-004 | E2E-01 主流程·桌面:任务面板出现新任务 | 任务已创建 | 切到「生信任务」TAB | 列表含新任务;状态=created | L5-D | P0 |
| TC-BIO-E2E-004-D | FR-BIO-005 | E2E-01 主流程·桌面:文件引导卡 | 起始阶段缺 fasta | 等待推进 | 对话出现缺文件提示(点名 fasta)+ .flow-file-card | L5-D | P0 |
| TC-BIO-E2E-005-D | FR-BIO-006 | E2E-01 主流程·桌面:拖拽上传金标数据 | 本地金标输入可用 | 拖入 Ft.SPL pep 文件 | 进度条百分比逐级推进至 100%;POST files 发出 | L5-D | P0 |
| TC-BIO-E2E-006-D | FR-BIO-008/009 | E2E-01 主流程·桌面:参数表单改一个参数 | 阶段待确认 | 表单卡出现后改 cpu=8→点「继续」 | 发出 confirm;请求体 params.cpu=8;阶段 running | L5-D | P0 |
| TC-BIO-E2E-007-D | FR-BIO-011 | E2E-01 主流程·桌面:进度卡逐阶段流转 | mock 全链 | 观察 | 状态点逐阶段点亮(waiting→running→done);运行中日志尾滚动更新 | L5-D | P0 |
| TC-BIO-E2E-008-D | FR-BIO-016 | E2E-01 主流程·桌面:报告预览 | 任务完成报告登记 | 切文档 TAB 打开 DocPane | 报告出现;预览白底(background=#FFFFFF);图可见 | L5-D | P0 |
| TC-BIO-E2E-009-D | FR-BIO-018 | E2E-01 主流程·桌面:导出 PDF | 报告已打开 | 点导出 PDF | 下载事件触发;文件落盘且可打开(非 0 字节) | L5-D | P1 |
| TC-BIO-E2E-010-D | FR-BIO-020/021 | E2E-01 主流程·桌面:存档提示→存档→状态回复 | 任务完成 | 观察提示卡→输入名称→点存档 | POST archives 发出;回复消息含名称/位置/大小三要素 | L5-D | P0 |
| TC-BIO-E2E-011-D | FR-BIO-024 | E2E-01 主流程·桌面:档案面板出现 | 已存档 | 切「生信档案」TAB | 列表含新档案(名称正确) | L5-D | P0 |
| TC-BIO-E2E-012-D | FR-BIO-027 | E2E-01 主流程·桌面:布局不溢出 | 全程 | 观察各步骤 | .flow-path-card/.flow-form-card/.flow-file-card/.bioflow-progress-card 宽≤容器;无横向滚动 | L5-D | P1 |
| TC-BIO-E2E-013-M | FR-BIO-010 | E2E-02 自动连续·移动端 | mock 全链 | 开启自动连续开关→发起任务→中途暂停 | 阶段间无表单卡自动推进;暂停后停在下一阶段前(该阶段 waiting_confirm) | L5-M | P0 |
| TC-BIO-E2E-013-T | FR-BIO-010 | E2E-02 自动连续·平板 | mock 全链 | 同上 | 同上断言 | L5-T | P0 |
| TC-BIO-E2E-013-D | FR-BIO-010 | E2E-02 自动连续·桌面 | mock 全链 | 同上 | 同上断言 | L5-D | P0 |
| TC-BIO-E2E-014-M | FR-BIO-012 | E2E-03 失败注入·移动端:三选一 | mock 阶段 2 失败 | 推进至失败 | 进度卡标红(--pa-error ✕);三按钮出现 | L5-M | P0 |
| TC-BIO-E2E-015-M | FR-BIO-012 | E2E-03 失败注入·移动端:重跑成功 | 阶段 failed | 点重跑(mock 转成功) | 状态转 running→done | L5-M | P0 |
| TC-BIO-E2E-016-M | FR-BIO-012 | E2E-03 失败注入·移动端:跳过生效 | 阶段 failed | 点跳过 | 状态=skipped;后续阶段推进 | L5-M | P0 |
| TC-BIO-E2E-017-M | FR-BIO-012 | E2E-03 失败注入·移动端:改参数重跑 | 阶段 failed | 点改参数重跑→改参数→继续 | 表单出现;按新参数重跑成功 | L5-M | P0 |
| TC-BIO-E2E-014-T | FR-BIO-012 | E2E-03 失败注入·平板:三选一 | mock 阶段 2 失败 | 推进至失败 | 进度卡标红(--pa-error ✕);三按钮出现 | L5-T | P0 |
| TC-BIO-E2E-015-T | FR-BIO-012 | E2E-03 失败注入·平板:重跑成功 | 阶段 failed | 点重跑(mock 转成功) | 状态转 running→done | L5-T | P0 |
| TC-BIO-E2E-016-T | FR-BIO-012 | E2E-03 失败注入·平板:跳过生效 | 阶段 failed | 点跳过 | 状态=skipped;后续阶段推进 | L5-T | P0 |
| TC-BIO-E2E-017-T | FR-BIO-012 | E2E-03 失败注入·平板:改参数重跑 | 阶段 failed | 点改参数重跑→改参数→继续 | 表单出现;按新参数重跑成功 | L5-T | P0 |
| TC-BIO-E2E-014-D | FR-BIO-012 | E2E-03 失败注入·桌面:三选一 | mock 阶段 2 失败 | 推进至失败 | 进度卡标红(--pa-error ✕);三按钮出现 | L5-D | P0 |
| TC-BIO-E2E-015-D | FR-BIO-012 | E2E-03 失败注入·桌面:重跑成功 | 阶段 failed | 点重跑(mock 转成功) | 状态转 running→done | L5-D | P0 |
| TC-BIO-E2E-016-D | FR-BIO-012 | E2E-03 失败注入·桌面:跳过生效 | 阶段 failed | 点跳过 | 状态=skipped;后续阶段推进 | L5-D | P0 |
| TC-BIO-E2E-017-D | FR-BIO-012 | E2E-03 失败注入·桌面:改参数重跑 | 阶段 failed | 点改参数重跑→改参数→继续 | 表单出现;按新参数重跑成功 | L5-D | P0 |
| TC-BIO-E2E-018-M | FR-BIO-014 | E2E-04 断线回放·移动端 | 任务 3 阶段执行中 | 切断 SSE 30s→重连 | 进度卡恢复断线前状态;无进度丢失;日志尾恢复 | L5-M | P0 |
| TC-BIO-E2E-018-T | FR-BIO-014 | E2E-04 断线回放·平板 | 任务 3 阶段执行中 | 切断 SSE 30s→重连 | 进度卡恢复断线前状态;无进度丢失;日志尾恢复 | L5-T | P0 |
| TC-BIO-E2E-018-D | FR-BIO-014 | E2E-04 断线回放·桌面 | 任务 3 阶段执行中 | 切断 SSE 30s→重连 | 进度卡恢复断线前状态;无进度丢失;日志尾恢复 | L5-D | P0 |
| TC-BIO-E2E-019-M | FR-BIO-023 | E2E-05 存档复用·移动端 | 归档 XXX 存在 | 发送「用 XXX 存档任务的方法帮我跑玉米 bZIP」→确认预填表单→执行 | 表单预填=XXX 参数(来源标注 XXX);新任务按此参数执行 | L5-M | P0 |
| TC-BIO-E2E-019-T | FR-BIO-023 | E2E-05 存档复用·平板 | 归档 XXX 存在 | 同上 | 同上断言 | L5-T | P0 |
| TC-BIO-E2E-019-D | FR-BIO-023 | E2E-05 存档复用·桌面 | 归档 XXX 存在 | 同上 | 同上断言 | L5-D | P0 |
| TC-BIO-E2E-020-M | FR-BIO-025 | E2E-06 探活显隐·移动端 | 同部署 mock | 停 8098→刷新 | 「生信任务/生信档案」TAB 与生信块分支消失;恢复 8098→刷新→出现 | L5-M | P0 |
| TC-BIO-E2E-020-T | FR-BIO-025 | E2E-06 探活显隐·平板 | 同部署 mock | 停 8098→刷新 | 「生信任务/生信档案」TAB 与生信块分支消失;恢复 8098→刷新→出现 | L5-T | P0 |
| TC-BIO-E2E-020-D | FR-BIO-025 | E2E-06 探活显隐·桌面 | 同部署 mock | 停 8098→刷新 | 「生信任务/生信档案」TAB 与生信块分支消失;恢复 8098→刷新→出现 | L5-D | P0 |
| TC-BIO-E2E-021-M | FR-BIO-019 | E2E-07 图表调整·移动端 | 报告含图1 | 发送「图1 颜色换成红色」 | 触发绘图阶段重跑;新图回填报告;预览刷新(颜色变化) | L5-M | P0 |
| TC-BIO-E2E-021-T | FR-BIO-019 | E2E-07 图表调整·平板 | 报告含图1 | 发送「图1 颜色换成红色」 | 触发绘图阶段重跑;新图回填报告;预览刷新(颜色变化) | L5-T | P0 |
| TC-BIO-E2E-021-D | FR-BIO-019 | E2E-07 图表调整·桌面 | 报告含图1 | 发送「图1 颜色换成红色」 | 触发绘图阶段重跑;新图回填报告;预览刷新(颜色变化) | L5-D | P0 |
| TC-BIO-E2E-022-M | FR-BIO-026 | E2E-08 知识库问答·移动端 | flow_docs 已入库;生信会话 | 发送「identify 需要什么输入」 | 答案含引用块(源文件+章节);点引用跳转原文 | L5-M | P0 |
| TC-BIO-E2E-022-T | FR-BIO-026 | E2E-08 知识库问答·平板 | flow_docs 已入库;生信会话 | 发送「identify 需要什么输入」 | 答案含引用块(源文件+章节);点引用跳转原文 | L5-T | P0 |
| TC-BIO-E2E-022-D | FR-BIO-026 | E2E-08 知识库问答·桌面 | flow_docs 已入库;生信会话 | 发送「identify 需要什么输入」 | 答案含引用块(源文件+章节);点引用跳转原文 | L5-D | P0 |
| TC-BIO-E2E-023-M | FR-BIO-027 | E2E-09 三档视口·移动端布局 | 390×844;进度卡/面板可见 | 观察五卡片+两面板 | 卡片/面板/进度卡不溢出;触控目标≥44px(按钮/候选行命中区) | L5-M | P0 |
| TC-BIO-E2E-023-T | FR-BIO-027 | E2E-09 三档视口·平板布局 | 768×1024;进度卡/面板可见 | 观察五卡片+两面板 | 卡片/面板/进度卡不溢出;面板可切换 | L5-T | P0 |
| TC-BIO-E2E-023-D | FR-BIO-027 | E2E-09 三档视口·桌面布局 | 1440×900;进度卡/面板可见 | 观察五卡片+两面板 | 卡片/面板/进度卡不溢出;面板可切换 | L5-D | P0 |
| TC-BIO-E2E-024-M | FR-BIO-018 | E2E-01 主流程·移动端:导出 DOCX | 报告已打开 | 点导出 DOCX | 下载事件触发;文件落盘且可打开(非 0 字节) | L5-M | P1 |
| TC-BIO-E2E-024-T | FR-BIO-018 | E2E-01 主流程·平板:导出 DOCX | 报告已打开 | 点导出 DOCX | 下载事件触发;文件落盘且可打开(非 0 字节) | L5-T | P1 |
| TC-BIO-E2E-024-D | FR-BIO-018 | E2E-01 主流程·桌面:导出 DOCX | 报告已打开 | 点导出 DOCX | 下载事件触发;文件落盘且可打开(非 0 字节) | L5-D | P1 |
| TC-BIO-E2E-025-M | FR-BIO-001 | E2E 漏判安全·移动端 | mock | 发送「什么是基因家族」 | 走 qa 流;无 .flow-path-card;无 bioflow 请求 | L5-M | P0 |
| TC-BIO-E2E-025-T | FR-BIO-001 | E2E 漏判安全·平板 | mock | 发送「什么是基因家族」 | 走 qa 流;无 .flow-path-card;无 bioflow 请求 | L5-T | P0 |
| TC-BIO-E2E-025-D | FR-BIO-001 | E2E 漏判安全·桌面 | mock | 发送「什么是基因家族」 | 走 qa 流;无 .flow-path-card;无 bioflow 请求 | L5-D | P0 |
| TC-BIO-E2E-026-M | FR-BIO-007 | E2E 服务器路径登记·移动端 | 任务待文件 | 文件卡路径输入行输入合法路径→点登记 | 登记成功显示登记项;阶段推进 | L5-M | P1 |
| TC-BIO-E2E-026-T | FR-BIO-007 | E2E 服务器路径登记·平板 | 任务待文件 | 文件卡路径输入行输入合法路径→点登记 | 登记成功显示登记项;阶段推进 | L5-T | P1 |
| TC-BIO-E2E-026-D | FR-BIO-007 | E2E 服务器路径登记·桌面 | 任务待文件 | 文件卡路径输入行输入合法路径→点登记 | 登记成功显示登记项;阶段推进 | L5-D | P1 |
| TC-BIO-E2E-027-M | FR-BIO-010 | E2E-02 暂停恢复·移动端 | 任务暂停中 | 点恢复 | 从下一阶段继续执行 | L5-M | P0 |
| TC-BIO-E2E-027-T | FR-BIO-010 | E2E-02 暂停恢复·平板 | 任务暂停中 | 点恢复 | 从下一阶段继续执行 | L5-T | P0 |
| TC-BIO-E2E-027-D | FR-BIO-010 | E2E-02 暂停恢复·桌面 | 任务暂停中 | 点恢复 | 从下一阶段继续执行 | L5-D | P0 |
| TC-BIO-E2E-028-M | FR-BIO-017 | E2E 报告编辑·移动端 | 报告已打开 | 就地改文字→保存 | 文字更新落盘(刷新后仍在);走既有编辑链路 | L5-M | P1 |
| TC-BIO-E2E-028-T | FR-BIO-017 | E2E 报告编辑·平板 | 报告已打开 | 就地改文字→保存 | 文字更新落盘(刷新后仍在);走既有编辑链路 | L5-T | P1 |
| TC-BIO-E2E-028-D | FR-BIO-017 | E2E 报告编辑·桌面 | 报告已打开 | 就地改文字→保存 | 文字更新落盘(刷新后仍在);走既有编辑链路 | L5-D | P1 |
| TC-BIO-E2E-029-M | FR-BIO-024 | E2E 任务面板 DAG·移动端 | 任务 3 阶段 | 打开任务详情 | 纵向连接线渲染;3 节点圆点按状态取色 | L5-M | P1 |
| TC-BIO-E2E-029-T | FR-BIO-024 | E2E 任务面板 DAG·平板 | 任务 3 阶段 | 打开任务详情 | 纵向连接线渲染;3 节点圆点按状态取色 | L5-T | P1 |
| TC-BIO-E2E-029-D | FR-BIO-024 | E2E 任务面板 DAG·桌面 | 任务 3 阶段 | 打开任务详情 | 纵向连接线渲染;3 节点圆点按状态取色 | L5-D | P1 |
| TC-BIO-E2E-030-M | FR-BIO-022 | E2E 档案回看·移动端 | 归档存在 | 档案面板打开归档详情 | 详情显示阶段链/参数/产物/报告 | L5-M | P1 |
| TC-BIO-E2E-030-T | FR-BIO-022 | E2E 档案回看·平板 | 归档存在 | 档案面板打开归档详情 | 详情显示阶段链/参数/产物/报告 | L5-T | P1 |
| TC-BIO-E2E-030-D | FR-BIO-022 | E2E 档案回看·桌面 | 归档存在 | 档案面板打开归档详情 | 详情显示阶段链/参数/产物/报告 | L5-D | P1 |
| TC-BIO-E2E-031-M | FR-BIO-020 | E2E 放弃存档·移动端 | 存档提示卡出现 | 点「放弃」 | 卡片消失;无 POST /api/bioflow/archives;任务保持 done 无副作用 | L5-M | P1 |
| TC-BIO-E2E-031-T | FR-BIO-020 | E2E 放弃存档·平板 | 存档提示卡出现 | 点「放弃」 | 卡片消失;无 POST /api/bioflow/archives;任务保持 done 无副作用 | L5-T | P1 |
| TC-BIO-E2E-031-D | FR-BIO-020 | E2E 放弃存档·桌面 | 存档提示卡出现 | 点「放弃」 | 卡片消失;无 POST /api/bioflow/archives;任务保持 done 无副作用 | L5-D | P1 |
| TC-BIO-E2E-032-M | FR-BIO-023 | E2E 面板复用发起·移动端 | 归档存在 | 档案面板→选中→点复用发起→确认 | 表单预填=归档参数;新任务入生信任务面板 | L5-M | P1 |
| TC-BIO-E2E-032-T | FR-BIO-023 | E2E 面板复用发起·平板 | 归档存在 | 档案面板→选中→点复用发起→确认 | 表单预填=归档参数;新任务入生信任务面板 | L5-T | P1 |
| TC-BIO-E2E-032-D | FR-BIO-023 | E2E 面板复用发起·桌面 | 归档存在 | 档案面板→选中→点复用发起→确认 | 表单预填=归档参数;新任务入生信任务面板 | L5-D | P1 |
| TC-BIO-E2E-033-M | FR-BIO-010 | E2E 自动连续可关闭·移动端 | 自动连续任务运行中 | 关闭自动连续开关 | 下一阶段前出现参数表单卡(切回手动) | L5-M | P1 |
| TC-BIO-E2E-033-T | FR-BIO-010 | E2E 自动连续可关闭·平板 | 自动连续任务运行中 | 关闭自动连续开关 | 下一阶段前出现参数表单卡(切回手动) | L5-T | P1 |
| TC-BIO-E2E-033-D | FR-BIO-010 | E2E 自动连续可关闭·桌面 | 自动连续任务运行中 | 关闭自动连续开关 | 下一阶段前出现参数表单卡(切回手动) | L5-D | P1 |
| TC-BIO-E2E-034-M | FR-BIO-024 | E2E 任务面板删除·移动端 | 非运行任务存在 | 面板点删除→确认 | 发出 DELETE;列表移除;刷新后仍无 | L5-M | P1 |
| TC-BIO-E2E-034-T | FR-BIO-024 | E2E 任务面板删除·平板 | 非运行任务存在 | 面板点删除→确认 | 发出 DELETE;列表移除;刷新后仍无 | L5-T | P1 |
| TC-BIO-E2E-034-D | FR-BIO-024 | E2E 任务面板删除·桌面 | 非运行任务存在 | 面板点删除→确认 | 发出 DELETE;列表移除;刷新后仍无 | L5-D | P1 |
| TC-BIO-E2E-035-M | FR-BIO-022 | E2E 档案删除·移动端 | 归档存在 | 档案面板点删除→确认 | 发出 DELETE;列表移除;刷新后仍无 | L5-M | P1 |
| TC-BIO-E2E-035-T | FR-BIO-022 | E2E 档案删除·平板 | 归档存在 | 档案面板点删除→确认 | 发出 DELETE;列表移除;刷新后仍无 | L5-T | P1 |
| TC-BIO-E2E-035-D | FR-BIO-022 | E2E 档案删除·桌面 | 归档存在 | 档案面板点删除→确认 | 发出 DELETE;列表移除;刷新后仍无 | L5-D | P1 |
| TC-BIO-E2E-036-M | FR-BIO-007 | E2E 聊天窗口指定路径·移动端 | 任务待文件 | 在聊天输入合法服务器路径并发送 | 路径登记成功;文件引导卡更新;阶段推进 | L5-M | P1 |
| TC-BIO-E2E-036-T | FR-BIO-007 | E2E 聊天窗口指定路径·平板 | 任务待文件 | 在聊天输入合法服务器路径并发送 | 路径登记成功;文件引导卡更新;阶段推进 | L5-T | P1 |
| TC-BIO-E2E-036-D | FR-BIO-007 | E2E 聊天窗口指定路径·桌面 | 任务待文件 | 在聊天输入合法服务器路径并发送 | 路径登记成功;文件引导卡更新;阶段推进 | L5-D | P1 |
6.1.18 DEPLOY 三形态部署(L2/L3 断言 + L2s 部署点冒烟)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-BIO-DEPLOY-001 | FR-BIO-027 | 只 rag:反代不注册 | BIOFLOW_ENABLED 缺省(false)启动 BFF | 检查路由表 | 无 /api/bioflow/* 路由 | L2 | P0 |
| TC-BIO-DEPLOY-002 | FR-BIO-027 | 只 rag:前端无生信痕迹 | 只 rag 部署;GET health 404 | 打开前端 | 无「生信任务/生信档案」TAB;无生信块分支;Composer 无生信上传分支 | L3 | P0 |
| TC-BIO-DEPLOY-003 | FR-BIO-027 | 只 rag:零请求 8098 | 只 rag 部署 | 打开前端并提问 | 网络面板无 /api/bioflow/* 请求 | L3 | P0 |
| TC-BIO-DEPLOY-004 | FR-BIO-027 | 只生信:8098 直连 | 仅部署生信服务 | GET :8098/api/bioflow/health | 200;catalog/jobs/chat 全部可用(不经 BFF) | L2 | P0 |
| TC-BIO-DEPLOY-005 | FR-BIO-027 | 只生信:报告降级下载 HTML | 只生信;任务 done | 取报告 | 返回 HTML 直下(Content-Type=text/html;Content-Disposition attachment 或页面内嵌,两态断言其一) | L2 | P0 |
| TC-BIO-DEPLOY-006 | FR-BIO-027 | 同部署:反代启用 | BIOFLOW_ENABLED=true | GET http://BFF/api/bioflow/health | 200 且响应体=直连响应体 | L2 | P0 |
| TC-BIO-DEPLOY-007 | FR-BIO-027 | 同部署:前端显形 | 同部署;health 200 | 打开前端 | 生信 TAB 出现;五类卡片/两面板可访问 | L3 | P0 |
| TC-BIO-DEPLOY-008 | FR-BIO-028 | BFF 停生信服务仍工作 | 同部署;停 BFF | 直连 8098 跑 mini 任务 | 任务正常完成(创建/确认/事件) | L2s | P0 |
| TC-BIO-DEPLOY-009 | FR-BIO-028 | BFF 重启不影响生信任务 | 同部署;任务 in-flight | 重启 BFF | 任务不受影响;8098 进程存活;GET jobs 仍含该任务 | L2s | P0 |
| TC-BIO-DEPLOY-010 | FR-BIO-027 | 三形态环境变量矩阵 | 三组配置 fixture | 逐组启动 BFF | 路由注册与否与 BIOFLOW_ENABLED 严格一致(3/3) | L2 | P1 |
| TC-BIO-DEPLOY-011 | FR-BIO-025 | 探活超时前端不白屏 | health 超时(mock 挂起) | 打开前端 | 页面正常渲染(无生信 TAB);无未捕获异常 | L3 | P1 |
| TC-BIO-DEPLOY-012 | FR-BIO-027 | 只生信形态 vstore 降级 | 只生信 | 跑流程咨询 | 检索不可用时 planner 走 LLM 直出(标记 llm_only);不 5xx | L2 | P1 |
6.1.19 REG 回归与串扰(L3/L4/L5,bioflow 引入不得破坏既有功能)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-BIO-REG-001 | FR-BIO-001 | QA 主流程无串扰 | 同部署;mock normal | 完整跑 E2E-01(QA 五相位) | 全相位通过;无 bioflow 请求产生 | L5-D | P0 |
| TC-BIO-REG-002 | FR-BIO-001 | 检索模式无串扰 | mock | 检索模式提问 | 只出来源不出答案块(与既有行为一致) | L5-D | P0 |
| TC-BIO-REG-003 | FR-BIO-001 | docgen 全链无串扰 | 同部署 | 写文档→编辑→导出 | 全部走既有 docgen 链路;无 bioflow 拦截 | L5-D | P0 |
| TC-BIO-REG-004 | FR-BIO-001 | 会话管理无串扰 | 同部署 | 新建/切换/删除会话 | 行为与既有一致 | L5-D | P1 |
| TC-BIO-REG-005 | FR-BIO-001 | 意图词典改动不打乱 docgen | 词典全表 | 跑 cases_intent.md(docgen 版)30 条 | docgen 判定 30/30 与既有表一致 | L3 | P0 |
| TC-BIO-REG-006 | FR-BIO-001 | 红线文件零改动 | git checkout 基线 | diff 五文件 | modes.js/labels.js/bench.js/qa.js/parser.js 无 diff | L3 | P0 |
| TC-BIO-REG-007 | FR-BIO-011 | PipelineCard 零改动 | 进度卡复用 | diff | PipelineCard.vue 无 diff;两卡同款视觉 | L3 | P1 |
| TC-BIO-REG-008 | FR-BIO-001 | BenchPanel TAB 数更新 | 同部署 | 数 TAB | 生信 TAB 计入后总数=既有+2;关服务时恢复既有数 | L4 | P0 |
| TC-BIO-REG-009 | FR-BIO-016 | doc_artifacts 与生信报告并存 | 同部署 | 查看文档工作台 | 既有 docgen 文档与生信报告同列表可切换;互不覆盖 | L5-D | P0 |
| TC-BIO-REG-010 | FR-BIO-001 | 首屏性能不劣化 | 同部署 | 测首屏 | 首屏时间与引入前基线差 <500ms | L5-D | P2 |
| TC-BIO-REG-011 | FR-BIO-001 | 主题切换生信组件适配 | 同部署 | 切深/浅 | 五卡片两面板令牌随主题(--pa-* 自动适配,无硬编码色) | L4 | P0 |
| TC-BIO-REG-012 | FR-BIO-001 | i18n 文案走 bioflow.js | 前端构建 | 检索文案键 | 生信文案全部在 i18n/bioflow.js;labels.js 未动 | L3 | P1 |
| TC-BIO-REG-013 | FR-BIO-001 | 生信会话与 QA 会话隔离 | 同部署 | 两会话并行操作 | 各自消息/任务状态互不串扰 | L5-D | P1 |
| TC-BIO-REG-014 | FR-BIO-001 | 既有 E2E 冒烟 6 条 | 同部署 | 跑 smoke.spec 三视口 | 6/6 pass(占位回退失效后走真实分支仍过) | L5 | P1 |
| TC-BIO-REG-015 | FR-BIO-001 | QA 上游 402 降级不受影响 | mock 402 | 提问 | fallback 证据列表展示与既有一致 | L5-D | P1 |
6.1.20 GOLD 金标与发布(L2s 部署点冒烟 + 编译门禁)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-BIO-GOLD-001 | FR-BIO-030 | 金标 24 ID 全等 | bioflow-gf 镜像;金标输入 | docker run identify | 输出集合与预期 24 成员 ID 全等;diff 输出为空 | L2s | P0 |
| TC-BIO-GOLD-002 | FR-BIO-030 | 金标冒烟脚本 | 镜像与数据就位 | bash bioflow_kernel/tests/smoke_golden.sh | 退出码 0;stdout 含 PASS | L2s | P0 |
| TC-BIO-GOLD-003 | FR-BIO-030 | 金标重复可复现 | 同上 | 连跑 2 次 | 两次输出集合一致(确定性) | L2s | P1 |
| TC-BIO-GOLD-004 | FR-BIO-032 | 18 入口 --help 冒烟 | 4 镜像 | 逐条 python -B -m cli.run_* --help | 18/18 退出码 0;无 traceback | L2s | P0 |
| TC-BIO-GOLD-005 | FR-BIO-032 | compile_bioflow.sh 编译产出 | 源码树 | 跑编译脚本(TL 执行后 T 验证) | 产出 .so 与明文白名单文件;无编译错误 | L2s | P0 |
| TC-BIO-GOLD-006 | FR-BIO-032 | 白名单外无明文 | 编译产物 | 检查产物 | 白名单外模块均为 .so(无 .py 明文残留) | L2s | P1 |
| TC-BIO-GOLD-007 | FR-BIO-032 | build_all.sh 4 镜像 | 构建环境 | 检查 docker images | bioflow-gf/bioflow-rnaseq/bioflow-wgs/bioflow-interproscan 四 tag 存在 | L2s | P0 |
| TC-BIO-GOLD-008 | FR-BIO-032 | SHA256SUMS | 构建产物目录 | 校验 | 文件存在且每条 sha256 与产物一致 | L2s | P0 |
| TC-BIO-GOLD-009 | FR-BIO-032 | 泄露门禁扫描 | 构建产物 | 扫描凭据模式 | 无 ACCESS_KEY/SECRET/密码类命中 | L2s | P0 |
| TC-BIO-GOLD-010 | FR-BIO-032 | 镜像启动冒烟 | 4 镜像 | docker run --help 版入口 | 4/4 容器启动并退出码 0 | L2s | P0 |
| TC-BIO-GOLD-011 | FR-BIO-029 | 资源限制生效验证 | 镜像 | docker run --cpus 2 --memory 4g 跑冒烟 | 容器内可见限制(/sys/fs/cgroup 或 nproc 断言) | L2s | P1 |
| TC-BIO-GOLD-012 | FR-BIO-029 | BIOFLOW_DATA 只读 | 镜像 | 挂载 :ro 跑冒烟 | 容器内写 /bioflow-data 失败(Permission denied) | L2s | P1 |
| TC-BIO-GOLD-013 | FR-BIO-032 | rag 侧装配开关 | rag 部署树 | 检查配置文件 | BIOFLOW_ENABLED 键存在且默认 false | L2s | P0 |
| TC-BIO-GOLD-014 | FR-BIO-032 | 生信服务编译白名单 | 编译产物 | 检查 | main.py/config.py/schemas.py/db.py 明文;业务模块 .so | L2s | P1 |
| TC-BIO-GOLD-015 | FR-BIO-032 | 内核映射表产物 | A1 交付 | 检查 bioflow_kernel/stage_image_map.json | JSON 合法;覆盖基因家族链 18 阶段 | L2s | P0 |
6.1.21 P0 冒烟(优先级 P0 快速验证集,TL 放行/验收快速通道)
| 编号 | 对应 FR | 标题 | 前置条件 | 步骤 | 预期结果 | 测试层 | 优先级 |
|---|---|---|---|---|---|---|---|
| TC-BIO-SMOKE-001 | FR-BIO-001 | P0 冒烟:分流命中 | mock | 发送「帮我跑水稻 SPL 家族鉴定」 | 进入生信流(出现路径卡或 bioflow 请求) | L5-D | P0 |
| TC-BIO-SMOKE-002 | FR-BIO-001 | P0 冒烟:漏判安全 | mock | 发送「什么是基因家族」 | 走 qa;无 bioflow 请求 | L5-D | P0 |
| TC-BIO-SMOKE-003 | FR-BIO-025 | P0 冒烟:探活 | mock | 打开应用(health 200) | 生信 TAB 可见 | L5-D | P0 |
| TC-BIO-SMOKE-004 | FR-BIO-002 | P0 冒烟:候选路径 | mock LLM | 读 plan_ready | 候选数∈[2,3] 且含阶段序列 | L2 | P0 |
| TC-BIO-SMOKE-005 | FR-BIO-004 | P0 冒烟:任务创建 | mock | POST jobs | 201 且 stages 入表 | L2 | P0 |
| TC-BIO-SMOKE-006 | FR-BIO-031 | P0 冒烟:状态机 | mock docker | 3 阶段任务跑通 | 全部 done;事件序正确 | L1 | P0 |
| TC-BIO-SMOKE-007 | FR-BIO-014 | P0 冒烟:事件回放 | 任务中途 | 连 events | 快照+补齐 | L2 | P0 |
| TC-BIO-SMOKE-008 | FR-BIO-029 | P0 冒烟:docker 拼装 | mock | 拼 identify 命令 | 含 --rm/--user/-v×3/--cpus/--memory/-e | L1 | P0 |
| TC-BIO-SMOKE-009 | FR-BIO-030 | P0 冒烟:金标 | 镜像就位 | 金标 diff | 输出为空 | L2s | P0 |
| TC-BIO-SMOKE-010 | FR-BIO-028 | P0 冒烟:反代开关 | BIOFLOW_ENABLED=true | GET BFF health | 200 | L2 | P0 |
| TC-BIO-SMOKE-011 | FR-BIO-011 | P0 冒烟:进度卡流转 | mock 事件 | 前端应用 | 状态点逐阶段点亮 | L4 | P0 |
| TC-BIO-SMOKE-012 | FR-BIO-012 | P0 冒烟:三选一 | 阶段 failed | 检查三按钮 | 重跑/跳过/改参数重跑出现 | L4 | P0 |
| TC-BIO-SMOKE-013 | FR-BIO-020 | P0 冒烟:存档 | 任务 done | POST archives | 201;磁盘目录存在 | L2 | P0 |
| TC-BIO-SMOKE-014 | FR-BIO-023 | P0 冒烟:复用 | 归档存在 | archives/{id}/run | 201;参数=归档值 | L2 | P0 |
| TC-BIO-SMOKE-015 | FR-BIO-016 | P0 冒烟:报告登记 | 任务 done | 登记 | doc_artifacts 新行 | L2 | P0 |
| TC-BIO-SMOKE-016 | FR-BIO-019 | P0 冒烟:图表调整 | 报告含图 | revise | 绘图阶段重跑;图更新 | L2 | P0 |
| TC-BIO-SMOKE-017 | FR-BIO-026 | P0 冒烟:知识问答 | flow_docs 入库 | 咨询 | 答案含引用块 | L2 | P0 |
| TC-BIO-SMOKE-018 | FR-BIO-027 | P0 冒烟:三形态 | 三配置 fixture | 逐形态启动 | 3/3 断言通过 | L2 | P0 |
| TC-BIO-SMOKE-019 | FR-BIO-032 | P0 冒烟:--help 18 入口 | 镜像 | 逐条 --help | 18/18 退出码 0 | L2s | P0 |
| TC-BIO-SMOKE-020 | FR-BIO-032 | P0 冒烟:SHA256SUMS | 产物 | 校验 | 全部匹配 | L2s | P0 |
| TC-BIO-SMOKE-021 | FR-BIO-006 | P0 冒烟:上传 | 任务待文件 | 上传小文件 | 200;files 列表+1 | L2 | P0 |
| TC-BIO-SMOKE-022 | FR-BIO-007 | P0 冒烟:路径登记 | 合法路径 | POST files server_path | 200;登记可见 | L2 | P0 |
| TC-BIO-SMOKE-023 | FR-BIO-010 | P0 冒烟:暂停恢复 | 任务 running | pause→resume | 状态迁移正确 | L2 | P0 |
| TC-BIO-SMOKE-024 | FR-BIO-024 | P0 冒烟:面板渲染 | 任务存在 | 打开面板 | 列表+DAG 渲染 | L4 | P0 |
| TC-BIO-SMOKE-025 | FR-BIO-022 | P0 冒烟:档案面板 | 归档存在 | 打开面板 | 档案列表渲染 | L4 | P0 |
6.2 追溯矩阵(FR-BIO → TC-BIO)
| FR | TC-BIO(引用即覆盖,≥1 条) |
|---|---|
| FR-BIO-001 | INTENT-001 |
| FR-BIO-002 | INTENT-001 |
| FR-BIO-003 | API-003,004; RUN-034; PATH-012; INTENT-003 |
| FR-BIO-004 | API-027 |
| FR-BIO-005 | RUN-017,018,032; FILE-001,002,015; E2E-004-M/T/D |
| FR-BIO-006 | API-039 |
| FR-BIO-007 | API-042 |
| FR-BIO-008 | API-056,058,121; RUN-019,020; FORM-001 |
| FR-BIO-009 | API-057,059 |
| FR-BIO-010 | API-067 |
| FR-BIO-011 | API-071 |
| FR-BIO-012 | API-062 |
| FR-BIO-013 | PROG-012 |
| FR-BIO-014 | API-013,017,077 |
| FR-BIO-015 | API-104,124,125; FLOW-005,006 |
| FR-BIO-016 | API-123; FLOW-003,004,007; REG-009; SMOKE-015; E2E-008-M/T/D |
| FR-BIO-017 | API-143; E2E-028-M/T/D |
| FR-BIO-018 | E2E-009,024-M/T/D |
| FR-BIO-019 | API-084~086,144; INTENT-033; FLOW-008; SMOKE-016; E2E-021-M/T/D |
| FR-BIO-020 | API-087 |
| FR-BIO-021 | API-131; DB-012; STORE-017; ARCH-007~010; E2E-010-M/T/D |
| FR-BIO-022 | API-090 |
| FR-BIO-023 | API-011,029,094 |
| FR-BIO-024 | API-032 |
| FR-BIO-025 | API-099,133; STORE-016; JOB-012,013; PANE-013,014; DEPLOY-011; SMOKE-003; E2E-020-M/T/D |
| FR-BIO-026 | API-012; INTENT-045; FLOW-009; SMOKE-017; E2E-022-M/T/D |
| FR-BIO-027 | DEPLOY-001~007,010,012; SMOKE-018; E2E-012,023-M/T/D |
| FR-BIO-028 | API-100 |
| FR-BIO-029 | API-115 |
| FR-BIO-030 | KERN-010,011,014 |
| FR-BIO-031 | API-016,109 |
| FR-BIO-032 | KERN-012,013,021 |
覆盖自核:32/32 FR-BIO 全部有 TC 引用;每个 TC-BIO 均映射至少 1 个 FR(见每行「对应 FR」列);无孤儿 TC。模块计数与规模门禁见 docs/team/report_bioflow_test1.md。
用例修订记录
| 日期 | 修订 | 原因 |
|---|---|---|
| 2026-09-06 | TC-BIO-API-021/022 期望 73/18 → 与 stage_image_map.json v2.0.0 权威数据一致(75/21) | BUG-R1-02:实现以 A1 交付物为事实源,用例按 dev 旧树冻结属口径过期 |
| 2026-09-06 | TC-BIO-INTENT-044 期望 bioflow+目标对象 → qa | BUG-R1-05:冻结词典无交互式补充规则,实现与词典一致;「换物种重跑」交互式补充转 P7 扩展加固期实现(新 FR 追加后补 TC) |