Files
sanguo_moziplus_v2/docs/design/archive-2.0/test-plan-v2.6.md
T
2026-06-01 22:41:30 +08:00

16 KiB
Raw Blame History

v2.6 测试计划

版本: v2.6.0-test-plan 作者: 司马懿(质量总监)🗡️ 日期: 2026-05-17 状态: F1-F5 已评审,F6-F18 待编码


一、测试基础设施

1.1 当前配置

  • 框架: pytest(已有 tests/ 目录,97 个用例全部通过)
  • Fixture: tmp_pathSQLite 临时数据库)、TestClientFastAPI
  • Mock 策略: 目前无 mock,全部用真实 SQLite 内存/临时文件
  • 运行方式: python3 -m pytest tests/ -q

1.2 测试分层

层级 覆盖范围 何时执行
单元测试 每个 F 的内部逻辑 每写完一个 F
集成测试 F1-F14 端到端链路 F14 完成后
E2E 验收 完整系统含前端 F18 完成后

1.3 测试规范

  • 每个 F 必须有对应的 test_*.py,测试文件与模块同名
  • 测试类按功能分组:class TestTaskCRUDclass 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.pyblocked_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.pyE2E

# 测试用例 P0 验证点
T1 页面渲染 5 个页面均可加载
T2 API 集成 页面操作 → API 调用正确
T3 SSE 实时更新 后端事件 → 前端 UI 更新
T4 项目切换 切换项目 → 数据刷新

四、集成测试计划(F14 完成后)

端到端链路测试

用户提需求 → 庞统规划 → 任务写入黑板 → Agent 执行 → 
Guardrail 检查 → 审查流水线 → 反驳协商 → 完成 → 经验沉淀
# 场景 关键验证
I1 正常流程(happy path 全链路无阻断,最终 done
I2 依赖链 A→B→CA done 后 B 自动 pendingB 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 → pendingretry_count +1)→ 再次执行

集成测试基础设施

# conftest.py 需要的 fixture
@pytest.fixture
def full_stack(tmp_path):
    """完整系统:FastAPI + Ticker + Dispatcher + Spawner(mock)"""
    ...

@pytest.fixture
def mock_spawner():
    """Mock spawner,模拟 Agent 执行"""
    ...

五、E2E 验收场景(F18 完成后)

# 场景 验收标准
E1 创建项目 → 提交任务 → 查看任务板 Dashboard 实时更新
E2 全局监控页 所有项目状态汇总、活跃 Agent 数、最近事件
E3 产物仓库页 任务产出物可浏览、可下载
E4 系统配置页 运行时配置可查看、Skill 列表可管理
E5 AI 简报页 项目级 AI 总结可生成
E6 SSE 实时 所有页面操作后 SSE 实时反映

六、测试通过标准

每个 F 的单元测试通过标准

  1. 全部 P0 用例通过(硬性要求)
  2. P1 用例通过率 ≥ 80%(可协商)
  3. 无 crash / 无未捕获异常
  4. 测试可重复运行(跑 3 次结果一致)

集成测试通过标准

  1. I1-I8 全部场景通过
  2. 无死锁、无资源泄漏
  3. 并发测试无数据竞争

E2E 验收标准

  1. E1-E6 全部场景通过
  2. 前端无 console error
  3. 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 本文档 17 通过
F7 本文档 5 通过
F8 本文档 4 通过
F9 本文档 16 通过
F10 本文档 13 通过
F11 本文档 10 通过
F12 本文档 13 通过
F13 本文档 待设计
F14 本文档 待设计
F15 本文档 4 通过
F16 本文档 待设计
F17 本文档 6 通过
F18 本文档 待设计

八、v2.8 新增测试(2026-06-01 更新)

覆盖 #07 Spawner Acquire-First + Prompt v3.0 + _check_timeouts 统一

F6-ext: Ticker _check_timeouts 增强(新增 4 个测试)

# 测试用例 P0 验证点
T-ext1 crash_limit 统一检查(working executor crash 3 次/30min → _check_timeouts 标 failed
T-ext2 crash_limit 统一检查(review reviewer crash 3 次/30min → _check_timeouts 标 failed
T-ext3 updated_at fallback mail auto-working 无 started_at → updated_at fallback → 超时回收
T-ext4 process_dead 对 review 状态 review agent 进程死 → 保持 review(不推 pending

F9-ext: Spawner Acquire-First(新增 6 个测试)

# 测试用例 P0 验证点
T-ext1 Phase 0 Pre-acquire revive timeout/failed → revive → acquire 成功
T-ext2 Phase 0 假死检测 status=running + lock PID 死 → revive
T-ext3 Phase 1 Counter acquire 互斥 并发 spawn → 第二个 AgentBusyError(counter_blocked)
T-ext4 Phase 2 Session check 锁保护 acquire 后 → session locked → release counter → AgentBusyError(session_locked)
T-ext5 Phase 2 多 blockers 收集 locked + compact → detail.blockers 列表
T-ext6 Phase 3 on_checks_passed 异常回滚 回调异常 → counter 自动 release

F9-ext2: Compact Hanging + Retry(新增 3 个测试)

# 测试用例 P0 验证点
T-ext1 compact_hanging release counter compact 超限 → 不标 failed → release counter → 任务保持 working
T-ext2 compact_hanging ticker 重新 dispatch P1 compact_hanging → ticker 超时 → pending → 重新 dispatch
T-ext3 retry 遇 busy 释放 counter _do_retry 遇 AgentBusyError → release counter → 任务保持 working

F9-ext3: AgentBusyError 分类(新增 3 个测试)

# 测试用例 P0 验证点
T-ext1 counter_blocked counter acquire 失败 → reason=counter_blocked
T-ext2 session blockers session locked/running/compacting → reason + detail.blockers
T-ext3 Dispatcher 错误区分 AgentBusyError → 路由决策记录具体原因

设计文档引用

  • docs/design/07-spawner-acquire-first.md#07.1 Acquire-First、#07.2 Executor/Review 统一、#07.3 Startup Recovery
  • docs/design/03-prompt-evolution.mdPrompt v3.0 任务式指挥
  • docs/design/06-pm2-crash-recovery.md:PM2 crash 恢复设计(启动恢复机制,待实施)

E2E 测试文件映射

文件 覆盖范围 状态
tests/test_e2e_v27.py E1-E10 API + 状态机 + 真实 Agent 已有
tests/test_e2e_v31.py v3.1 E2E 集成 已有
tests/test_e2e_four_phase.py #01 四相循环 E2E 已有
tests/test_four_phase_unit.py #01 四相循环单元测试 已有
E11-E15 新增用例 待添加到 test_spawner.py / test_ticker.py / test_dispatcher.py 本轮更新