Skip to content
预计 1 分钟右侧目录可快速定位

Runtime 怎么做确定性验证:Unit、Contract、Fault Injection 与 Invariant Tests ​

前置:Agent Trace 如何标准化导出:OpenTelemetry 与 Export Pipeline
核心问题:哪些 Runtime 行为必须用 deterministic test 证明,Fault Injection 应打在什么 crash window 才能真正验证 invariant?

为什么真实模型反而会污染 Runtime Test ​

如果要验证“Tool timeout 后只重试一次,并正确记录两个 attempts”,真正被测的是 Runtime。测试若依赖真实模型、真实网络和随机输出,一旦失败就很难判断是哪一层出了问题。

因此 Runtime Test 应优先使用 Fake Clock、Scripted Model、Fake Tool/Store,把输入和故障位置固定下来。

Unit Test:证明状态迁移和 Policy Wiring ​

例如:

text
ScriptedModel → tool_call(search)
FakeTool attempt-1 → TIMEOUT
FakeTool attempt-2 → SUCCESS

断言:

text
attempts == 2
same logical operation_id
retry budget consumed once
final node == SUCCEEDED

测试不需要真实 Provider,因为这里验证的是自己的状态机和 retry wiring。

Contract Test:证明 Adapter 没破坏内部语义 ​

Model / Tool / MCP Adapter 的 Contract Test 只关心它是否满足 Harness 的内部 contract,例如:字段规范化、error taxonomy、stream event、schema/capability、timeout/cancellation。

更换 SDK/Provider 后复用同一套 cases,就能判断变化是否被 Adapter 正确吸收,而不用重跑整个 Scheduler 的每个路径。

Fault Injection:把 Crash 打在两个事实之间 ​

最有价值的故障点通常是:

text
remote side effect success
→ CRASH
→ local completion commit

或:

text
READY state committed
→ CRASH
→ broker enqueue / ack

只有主动在这些边界 kill worker,才能验证 idempotency、reconciliation、checkpoint 和 redelivery,而不是只证明 happy path 会跑。

🔍 源码对照:最值得故障注入的地方:Checkpoint 已写、Transcript 未 commit ​

完整源码与通用分析见 09-06 Checkpoint / Pause / Resume。这里不重复代码;这里关注 fault injection:故障点应插在 checkpoint 已提交与 transcript commit 之间,并断言恢复结果仍满足既定 invariant。

源码说明

该 reconstruction 本身维护 focused regression tests,而 turn-observation / auto-review-gate 又提供清晰可注入的状态和依赖边界。对我们真正有价值的不是复制测试文件,而是看到 Runtime correctness 可以通过 fake clock、fake controller、fake tool/event sink 做 deterministic assertions,不需要让真实 LLM 来判断 state machine 是否正确。

工程边界

仓库测试覆盖范围不等于完整产品质量证明;本文仍坚持 Testing 验证 software contract,Evaluation 才衡量 Agent decision quality。

Shadow Harness 对照

  • FakeModel/FakeTool/FakeClock 是一等测试接口。
  • 所有 state transition、approval gate、retry class 都有 table/property tests。

验证

不联网、不调用真实模型,完整跑通 tool success、timeout、approval wait、cancel、resume 五条 Runtime trajectory,并断言事件顺序。

Invariant / Property Test:检查“无论怎么组合都不能发生”的事 ​

与固定 case 不同,Property Test 可以生成大量 DAG、事件和 retry 顺序,只断言不变量,例如:

text
terminal state 不回到 RUNNING
dependency 未满足不得启动
同一 fencing epoch 只能有一个合法 owner
同一 logical operation 不出现两个 committed success

它尤其适合状态组合爆炸的 Runtime。

四类测试怎么分工 ​

方法最适合验证
Unit单个 reducer/policy/调度决策
ContractAdapter 是否保持内部接口语义
Fault Injectioncrash/timeout/partial write 边界
Invariant / Property大量组合下永远成立的规则

关联源码 ​

自测 ​

  1. 要测试“side effect 成功后、checkpoint 前 crash”,Fault Injection 应插在哪个精确边界,关键断言是什么?
  2. Unit、Contract、Invariant test 分别更适合验证局部函数、组件协议还是跨状态机不可破坏条件?

Sources ​

AI Engineering · Agent · Harness · Backend Systems