11. Deterministic Runtime Tests
本章说明为什么 agent runtime 需要不依赖真实模型的确定性测试。模型调用可以验证集成,但不能作为 runtime 语义的唯一证明。
读完本章后,应该理解:
- fake model gateway 为什么是测试基础设施
- 哪些 loop 行为必须用真测试覆盖
- 为什么测试应该断言 history、tool call 和 final response
- 真实工具集成测试与 fake gateway 测试分别解决什么
背景
如果每个测试都调用真实模型,agent 行为很难测试。
Runtime 需要不依赖这些因素的测试:
- 网络可用性
- provider behavior
- model randomness
- API keys
Fake Gateway
tests/agent-sampling-loop.test.ts 创建 fake AgentModelGateway。
Fake gateway 返回脚本化的 AgentModelStreamEvent[] rounds。
这让测试可以精确断言:
- no-tool final answers
- tool calls
- tool outputs
- malformed provider streams
- recoverable tool errors
- repeated-call guardrails
测试证明什么
关键 case:
no tool call
-> assistant message becomes final_response
tool call
-> assistant message becomes working_message
-> function_call is written
-> function_call_output is written
-> later no-tool message becomes final_response
text_delta without assistant_message_done
-> protocol error
tool_call_delta without tool_call_committed
-> protocol error为什么重要
这些不是 helper function unit tests,而是 runtime 最重要 invariant 的 contract tests:
provider stream -> sampling round result -> model-visible history真实工具集成
真实 read-only tools 加入后,sampling-loop tests 更新为 fake model 请求 read,然后真实 tool runtime 执行它。
这证明链路:
fake model tool call
-> permission/runtime boundary
-> concrete built-in tool
-> function_call_output historyGit 证据
相关提交:
f8652ee Add deterministic sampling loop tests测试哲学
项目避免永远不会失败的假测试。测试应该锁定具体 history shape 和 error message。发现 runtime bug 时,第一步应该是写可复现测试。
常见误解
误解一:agent 行为没法稳定测试
模型智能不可预测,但 runtime contract 可以稳定测试。Fake gateway 固定模型事件后,loop、history、tool execution 和 final response 都可以断言。
误解二:只跑真实 provider 更可靠
真实 provider 测试容易受网络、额度、模型版本和中转站影响。它适合冒烟测试,不适合作为 runtime 语义的主要保障。
误解三:测试只需要覆盖成功路径
Agent runtime 的关键风险常在错误路径:工具失败、取消、重复调用、没有 committed message、schema 不合法。这些都应该被确定性测试覆盖。
本章小结
这一章建立了 agent runtime 的测试地基:用 fake gateway 固定模型行为,用真实工具测试验证集成,用断言证明 loop 语义而不是模型质量。
本章验证点
验证"不依赖真实模型"是字面成立的:在一台没有 .env.local、没有任何 OPENAI_* 环境变量的机器上直接全量跑:
npm test实测尾部输出:
ℹ tests 103
ℹ suites 0
ℹ pass 103
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 1651.784667103 个用例、约 1.6 秒、零网络请求、零 key。这可能成立是因为:fake gateway 把模型事件固定成脚本化的 AgentModelStreamEvent[],真实工具在本地文件系统上执行,因此 loop 语义、history 形状和错误路径都能在无 key 环境下断言。真实 provider 只在冒烟测试时才需要在场。