Files
deepseek-harness/docs/rfc/implemented/testing/2026-06-11-property-based-testing.zh.md
Ziya 2565133af3 docs(i18n): RFC tree batch — 146 bilingual pairs via the committed pipeline
implemented(除 4 篇超长文档随后补)、proposed、rejected 全树配对;
同一流水线 + 二遍校验(paraphrase-back + 仓库上下文一致性)产出。
docs/rfc/implemented/AGENTS.md 与其 CLAUDE.md 符号链接列入排除
(agent 指令文件,与根 AGENTS.md 同策略)。
2026-07-15 23:25:06 -07:00

30 lines
3.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# RFC:对协议形态代码进行基于属性的测试
Status: implemented
[English](2026-06-11-property-based-testing.md) | 中文
> 将原始提案与决策记录合并为一篇。首次运行即发现了 BlockAssembler 的重复 `block-end` 真实 bug。
## 问题
基于示例的测试只能固定我们想到的用例。harness 的核心是协议形态的代码:分片流、事件日志、schema 转换、收件箱调度。这类代码的输入空间是组合爆炸的,有趣的 bug 藏在没人写过示例的交错序列里。佐证:一个 block 组装的排序 bug 曾在 happy path 100% 行覆盖率下存活。逐文件 100% 覆盖率只能证明每行都跑过,不能证明每种交错都正确。
## 决策
引入 `fast-check`(根 devDependency),在每个协议形态的包中编写一个 `tests/properties.spec.ts`。生成器调优为*逼真但对抗性*的输入(而非均匀噪声),`numRuns` 控制在本地套件总耗时远低于约 10 秒。失败时打印可复现的 seed。(原始提案还草拟了一个夜间 CI job,以 100 倍迭代运行;该部分未交付——属性测试套件仅在常规 `push`/`pull_request` CI 中运行,定时高迭代 job 仍属可能的后续工作。)
- **dsh-llm / BlockAssembler:** 任意分片流(合法 + 畸形:重复索引、滞后分片、缺少 block-start)。不变式:`blocks()` 数量 ≤ 出现过的不同索引数;重组幂等(`blocks()` 在重复调用间稳定,且 `message().content` 与之一致);`blocks()` 从不抛异常且只产出合法的 content-block 标签;`finish` 反映最后一个 `finish` 分片,无 `finish` 分片时默认为 `{kind:'stop'}`。
- **dsh-session:** 任意事件日志。不变式:`deriveMessages` 确定性;从 seed 回放结果一致;seq 严格单调递增;非消息事件不影响派生历史;派生内容与日志解耦。
- **dsh-tools:** 任意 `SchemaSpec`。不变式:JSON Schema 的 `required` 等于每层 `required:true` 的键集合;转换是全函数;**并且与[运行时参数校验](../architecture/2026-06-11-runtime-arg-validation.md)组合验证**——满足 spec 的生成参数通过 `validateArgs`,定向破坏(删除 required 键、顶层非 object)被拒绝。这封堵了 validator 与 `InferArgs` 漂移的风险。
- **dsh-agent-loop:** 任意发送调度,对接一个永不耗尽的适配器,通过 `agent/status` settle 信号驱动(无挂钟 sleep)。不变式:无消息丢失;轮次编号严格递增;状态转换始终在合法状态机上。
## 后果
- 生成器质量是价值杠杆——生成器偏向小索引池和短字符串,使碰撞与交错频繁出现。
- **已经产出回报:** BlockAssembler 的流测试发现了一个真实 bug——同一索引的重复 `block-end` 覆写了已刷出的块,导致流式前缀与最终 `blocks()` 不一致。已修复(首次关闭生效,与既有的滞后分片规则一致),并附带专门的回归测试。
- 属性测试因超时而 flake 是一个发现,不应重试了事。agent loop 的属性测试在设计上是确定性的(通过 `agent/status` settle),因此挂起即为真实缺陷。
- 属性测试是示例测试的补充而非替代;示例测试固定特定分支,服务于 100% 覆盖率门禁。
<!-- rfc-format: alternatives-not-recorded (pre-format RFC) -->