v2.6 测试计划
版本: v2.6.0-test-plan
作者: 司马懿(质量总监)🗡️
日期: 2026-05-17
状态: F1-F5 已评审,F6-F18 待编码
一、测试基础设施
1.1 当前配置
- 框架: pytest(已有
tests/ 目录,97 个用例全部通过)
- Fixture:
tmp_path(SQLite 临时数据库)、TestClient(FastAPI)
- Mock 策略: 目前无 mock,全部用真实 SQLite 内存/临时文件
- 运行方式:
python3 -m pytest tests/ -q
1.2 测试分层
| 层级 |
覆盖范围 |
何时执行 |
| 单元测试 |
每个 F 的内部逻辑 |
每写完一个 F |
| 集成测试 |
F1-F14 端到端链路 |
F14 完成后 |
| E2E 验收 |
完整系统含前端 |
F18 完成后 |
1.3 测试规范
- 每个 F 必须有对应的
test_*.py,测试文件与模块同名
- 测试类按功能分组:
class TestTaskCRUD、class TestTransitions 等
- P0 测试必须有,P1 测试建议有但不强阻塞
- 测试必须可重复运行(不依赖外部状态、不依赖时序)
- 新增测试必须在
tests/ 目录下,不放在 src/ 内
二、F1-F5 单元测试评审(已完成)
现有覆盖情况
| F |
测试文件 |
用例数 |
P0 覆盖 |
评审 |
| F1 骨架 |
test_main.py |
10/10 |
✅ 启动、健康端点、配置、Swagger |
通过 |
| F2 黑板 |
test_blackboard.py |
39/39 |
✅ CRUD、状态机、并发、WAL、事件 |
通过(附 2 条意见) |
| F3 多项目 |
test_registry.py |
11/11 |
✅ 创建/删除/归档/持久化/黑板的联动 |
通过 |
| F4 CLI |
test_cli.py |
14/14 |
✅ 8 子命令 + admin + 错误处理 |
通过 |
| F5 API |
test_api.py |
23/23 |
✅ 全端点 CRUD + 状态码 + SSE 连接 |
通过(附 1 条意见) |
总计: 97/97 通过,质量合格。
评审意见(F1-F5)
BUG-1 [P1] /api/daemon/status 端点重复注册
- 位置:
main.py 第 99-111 行直接定义了 daemon_status 端点,同时 daemon_routes.py 也定义了同名路由
- 现象: pytest 输出
Duplicate Operation ID daemon_status warning
- 修复: 删除
main.py 中的 /api/daemon/status 端点定义,统一由 daemon_routes.py 提供
- 影响: 不影响功能,但 Swagger 文档会混乱
OBS-1 [P2] operations.py 的 _conn() 每次操作都新建连接
- 位置:
operations.py 全文,每次方法调用 self._conn() → sqlite3.connect()
- 现状: 单次操作用完即关,连接不池化
- 评估: v2.6 阶段可接受(SQLite WAL + busy_timeout 足够),但如果后续 F6 ticker 30s 轮询 + 多项目并发,建议 F6 阶段引入连接池或
per-thread 连接复用
- 行动: 不阻塞当前进度,F6 编码时再评估性能
OBS-2 [P2] queries.py 的 blocked_tasks_with_deps() 和 pending_dispatchable() 存在 SQL 注入风险
- 位置:
queries.py 第 52 行和第 71 行,使用 f-string 拼接 SQL
- 现象:
f"SELECT ... WHERE id IN ({','.join('?' * len(deps))})" — 虽然 deps 来自数据库的 depends_on 字段(不是用户输入),且用了参数化占位符,但 f-string 拼接 SQL 是坏习惯
- 评估: 当前实际安全(因为值都来自参数化
?),但风格不好
- 行动: 不阻塞,但后续统一改为纯参数化写法
三、F6-F18 测试计划(逐模块)
F6 Daemon Ticker — test_ticker.py
| # |
测试用例 |
P0 |
验证点 |
| T1 |
tick 循环正常运行 |
✅ |
30s 间隔(测试中加速),不阻塞 event loop |
| T2 |
scan_tasks 检测 pending |
✅ |
pending → 触发调度 |
| T3 |
依赖推进 |
✅ |
blocked → pending(依赖 done 后) |
| T4 |
events 写入 |
✅ |
每次 tick 写 daemon_tick 事件 |
| T5 |
多项目轮询 |
✅ |
tick 遍历所有 active 项目 |
| T6 |
tick 异常不中断 |
P1 |
单次 tick 抛异常 → 下次 tick 继续 |
| T7 |
手动 tick 端点 |
P1 |
POST /api/daemon/tick 触发即时 tick |
F7 Inbox JSONL Watcher — test_inbox.py
| # |
测试用例 |
P0 |
验证点 |
| T1 |
写入+消费 |
✅ |
Agent 写 JSONL → 1s 内 Daemon 读取并处理 |
| T2 |
truncate |
✅ |
消费后清空文件 |
| T3 |
并发写入 |
✅ |
多 Agent 同时写不同行 |
| T4 |
损坏行恢复 |
P1 |
非法 JSON 行跳过不崩溃 |
| T5 |
空文件处理 |
P1 |
空文件不触发处理 |
F8 健康检查 — test_health.py
| # |
测试用例 |
P0 |
验证点 |
| T1 |
正常场景 |
✅ |
有变更 → 无告警 |
| T2 |
僵尸检测 |
✅ |
连续 N tick 无变更 → observation 写入 |
| T3 |
恢复场景 |
✅ |
僵尸后有变更 → 告警解除 |
| T4 |
多项目独立检测 |
P1 |
项目 A 僵尸不影响项目 B |
F9 Agent 调度器 — test_dispatcher.py
| # |
测试用例 |
P0 |
验证点 |
| T1 |
三级决策树 |
✅ |
Daemon task → Full task → Sub task 正确分流 |
| T2 |
调度不阻塞 |
✅ |
spawn 用 asyncio.create_subprocess_exec |
| T3 |
队列满拒绝 |
✅ |
active agent 数达上限 → 不调度 |
| T4 |
任务优先级排序 |
P1 |
高优先级先调度 |
F9 Agent Spawner — test_spawner.py
| # |
测试用例 |
P0 |
验证点 |
| T1 |
spawn 成功 |
✅ |
子进程启动 + session 注册 |
| T2 |
超时处理 |
✅ |
超时后 kill + task_attempt 记录 |
| T3 |
spawn 失败 |
✅ |
命令不存在 → task_attempt 记录 spawn_failed |
| T4 |
session 清理 |
P1 |
子进程结束后 session 归档 |
F10 ActiveAgentCounter — test_counter.py
| # |
测试用例 |
P0 |
验证点 |
| T1 |
全局上限 |
✅ |
max_global=5 时第 6 个 acquire 失败 |
| T2 |
per-agent 串行 |
✅ |
同一 agent 第二个 acquire 排队 |
| T3 |
release 恢复 |
✅ |
release 后等待中的 acquire 成功 |
| T4 |
并发竞争 |
P1 |
多 agent 同时 acquire 不超限 |
F11 Bootstrap 拼装 — test_bootstrap.py
| # |
测试用例 |
P0 |
验证点 |
| T1 |
各 role 拼装 |
✅ |
不同 role 得到不同 L0-L3 四层 |
| T2 |
token 估算 |
✅ |
拼装结果 < 4096 tokens |
| T3 |
缺失组件降级 |
P1 |
某层文件不存在 → 跳过不崩溃 |
| T4 |
模板变量替换 |
P1 |
{{task_id}} 等占位符正确替换 |
F12 审查流水线 — test_review_flow.py
| # |
测试用例 |
P0 |
验证点 |
| T1 |
4 级分流 |
✅ |
high/standard/low/research 正确路由 |
| T2 |
confidence 计算 |
✅ |
分值在 0-1 区间,阈值逻辑正确 |
| T3 |
升级到庞统 |
✅ |
confidence < 阈值 → 升级 |
| T4 |
审查通过 → done |
✅ |
verdict=approved → 状态变 done |
| T5 |
审查拒绝 → 重新执行 |
P1 |
verdict=rejected → 回到 working |
F13 Guardrail — test_guardrail.py
| # |
测试用例 |
P0 |
验证点 |
| T1 |
L1 assert 通过 |
✅ |
合规产出 → 放行 |
| T2 |
L1 assert 失败 |
✅ |
不合规产出 → 拦截 |
| T3 |
L2 subagent 触发 |
✅ |
高风险 → 二次确认 |
| T4 |
配置加载 |
P1 |
guardrails.yaml 正确解析 |
| T5 |
误杀恢复 |
P1 |
L2 确认通过 → 放行 |
F14 反驳权 — test_rebuttal.py
| # |
测试用例 |
P0 |
验证点 |
| T1 |
反驳触发 |
✅ |
review rejected → 反驳协商开始 |
| T2 |
轮次计数 |
✅ |
round 递增正确 |
| T3 |
超轮次升级 |
✅ |
超过 max_rounds → 庞统裁决 |
| T4 |
结果写入 |
✅ |
最终裁决写入 reviews 表 |
F15 经验沉淀 — test_experience.py
| # |
测试用例 |
P0 |
验证点 |
| T1 |
一级蒸馏 |
✅ |
任务完成 → experiences 表写入 |
| T2 |
tag 匹配 |
✅ |
相似 tag 的经验可被查询到 |
| T3 |
二级触发 |
P1 |
N 条同类经验 → Skill 草稿生成 |
| T4 |
过期清理 |
P1 |
deprecated 经验不被查询 |
F16 Skill 体系 — test_skill_loader.py
| # |
测试用例 |
P0 |
验证点 |
| T1 |
加载 + 验证 |
✅ |
四要素完整才加载 |
| T2 |
per-project 覆盖 |
✅ |
项目级 Skill 覆盖全局 Skill |
| T3 |
缺要素拒绝 |
P1 |
缺少 name/description/triggers/actions → 拒绝 |
| T4 |
版本管理 |
P1 |
同名 Skill 版本号正确比较 |
F17 SSE + Hook — test_sse.py / test_hooks.py
| # |
测试用例 |
P0 |
验证点 |
| T1 |
SSE 连接 |
✅ |
客户端连接 → 收到初始事件 |
| T2 |
SSE 4 级推送 |
✅ |
task/agent/daemon/system 四级 |
| T3 |
断线重连 |
P1 |
断线后重连 → 收到后续事件 |
| T4 |
降级轮询 |
P1 |
SSE 不可用 → 轮询兜底 |
| T5 |
Hook 触发 |
✅ |
3 个触发点正确执行 |
| T6 |
Hook 过滤 |
P1 |
条件不满足 → 不触发 |
F18 前端 Dashboard — test_frontend.py(E2E)
| # |
测试用例 |
P0 |
验证点 |
| T1 |
页面渲染 |
✅ |
5 个页面均可加载 |
| T2 |
API 集成 |
✅ |
页面操作 → API 调用正确 |
| T3 |
SSE 实时更新 |
✅ |
后端事件 → 前端 UI 更新 |
| T4 |
项目切换 |
✅ |
切换项目 → 数据刷新 |
四、集成测试计划(F14 完成后)
端到端链路测试
| # |
场景 |
关键验证 |
| I1 |
正常流程(happy path) |
全链路无阻断,最终 done |
| I2 |
依赖链 |
A→B→C,A done 后 B 自动 pending,B done 后 C 自动 pending |
| I3 |
审查拒绝 → 反驳 → 通过 |
review rejected → rebuttal → verdict 翻转 |
| I4 |
审查拒绝 → 反驳 → 超轮次 → 庞统裁决 |
max_rounds 后升级 |
| I5 |
Guardrail 拦截 → L2 确认 → 放行 |
L1 fail → L2 confirm → proceed |
| I6 |
Agent 僵尸检测 |
无 heartbeat → observation → reclaim |
| I7 |
多项目并行 |
项目 A/B 同时运行,互不干扰 |
| I8 |
失败重试 |
failed → pending(retry_count +1)→ 再次执行 |
集成测试基础设施
五、E2E 验收场景(F18 完成后)
| # |
场景 |
验收标准 |
| E1 |
创建项目 → 提交任务 → 查看任务板 |
Dashboard 实时更新 |
| E2 |
全局监控页 |
所有项目状态汇总、活跃 Agent 数、最近事件 |
| E3 |
产物仓库页 |
任务产出物可浏览、可下载 |
| E4 |
系统配置页 |
运行时配置可查看、Skill 列表可管理 |
| E5 |
AI 简报页 |
项目级 AI 总结可生成 |
| E6 |
SSE 实时 |
所有页面操作后 SSE 实时反映 |
六、测试通过标准
每个 F 的单元测试通过标准
- 全部 P0 用例通过(硬性要求)
- P1 用例通过率 ≥ 80%(可协商)
- 无 crash / 无未捕获异常
- 测试可重复运行(跑 3 次结果一致)
集成测试通过标准
- I1-I8 全部场景通过
- 无死锁、无资源泄漏
- 并发测试无数据竞争
E2E 验收标准
- E1-E6 全部场景通过
- 前端无 console error
- SSE 延迟 < 2s
七、进度追踪
| F |
测试计划 |
用例设计 |
编码 |
执行 |
评审 |
| F1 |
✅ |
✅ 10 |
✅ |
✅ 10/10 |
✅ 通过 |
| F2 |
✅ |
✅ 39 |
✅ |
✅ 39/39 |
✅ 通过(附 2 条意见) |
| F3 |
✅ |
✅ 11 |
✅ |
✅ 11/11 |
✅ 通过 |
| F4 |
✅ |
✅ 14 |
✅ |
✅ 14/14 |
✅ 通过 |
| F5 |
✅ |
✅ 23 |
✅ |
✅ 23/23 |
✅ 通过(附 1 条意见) |
| F6 |
✅ 本文档 |
⬜ 待设计 |
⬜ |
— |
— |
| F7 |
✅ 本文档 |
⬜ 待设计 |
⬜ |
— |
— |
| F8 |
✅ 本文档 |
⬜ 待设计 |
⬜ |
— |
— |
| F9 |
✅ 本文档 |
⬜ 待设计 |
⬜ |
— |
— |
| F10 |
✅ 本文档 |
⬜ 待设计 |
⬜ |
— |
— |
| F11 |
✅ 本文档 |
⬜ 本文档 |
⬜ |
— |
— |
| F12 |
✅ 本文档 |
⬜ 待设计 |
⬜ |
— |
— |
| F13 |
✅ 本文档 |
⬜ 待设计 |
⬜ |
— |
— |
| F14 |
✅ 本文档 |
⬜ 待设计 |
⬜ |
— |
— |
| F15 |
✅ 本文档 |
⬜ 待设计 |
⬜ |
— |
— |
| F16 |
✅ 本文档 |
⬜ 待设计 |
⬜ |
— |
— |
| F17 |
✅ 本文档 |
⬜ 待设计 |
⬜ |
— |
— |
| F18 |
✅ 本文档 |
⬜ 待设计 |
⬜ |
— |
— |