property-based-testing
作者 trailofbits用于在多种语言和智能合约中编写、审查和改进 PBT 的 property-based-testing 技能指南。使用这份 property-based-testing 指南来识别 roundtrip、idempotence、invariant、parser、validator 和 normalization 场景,选择 generators,并判断何时 property-based-testing 比 example-based tests 更有优势。
该技能得分 83/100,属于质量扎实的目录条目:它提供了足够明确的触发规则和工作流指引,能比通用提示更有实际帮助;但对于边缘情况和语言特定实现细节,用户仍需保留一定的人工判断。
- 对常见 PBT 模式提供了明确的自动识别触发条件,例如 encode/decode 配对、parser、normalizer、validator、pure functions 和智能合约。
- 覆盖了完整生命周期中的关键操作内容:设计 properties、生成 tests、审查失败结果,以及重构以提升可测试性。
- 语言和工具覆盖面广,并配有 7 个参考文件,能深化工作流且没有占位内容,因此具备不错的安装决策参考价值。
- SKILL.md 中没有安装命令,因此接入时需要用户手动将该技能接入环境,或自行推断安装方式。
- 带有实验性/测试信号,且部分文档偏参考资料型;用户可能需要自行解读指导,而不是直接照着一套端到端可运行流程执行。
property-based-testing 技能概述
这个技能适用于什么场景
property-based-testing 技能帮助你编写、审查和改进 property-based tests(性质测试),尤其是在 example-based tests(基于示例的测试)已经不足以提供足够信心的时候。它特别适合 property-based-testing 技能在需要验证 roundtrips、invariants、parsers、validators、normalizers、sorting logic 或 smart contract 状态规则时使用。
谁最适合使用
最适合的用户包括:使用成熟 PBT 库的工程师、检查薄弱测试的审查者,以及在设计功能时希望先用性质来定义需求的开发者。如果你正在判断是否安装 property-based-testing,关键问题是:你的代码是否具有可复用结构、可逆转换,或者需要在大量输入上都成立的规则。
它有什么不同
和通用测试提示不同,这个技能围绕 detection、property choice、strategy design 和 failure interpretation 来组织。之所以重要,是因为阻碍 adoption 的最大问题不是语法,而是如何选出一个有用的性质,以及如何在不过度过滤的前提下生成有效输入。这个技能的覆盖面也足够广,适用于跨多个生态的 property-based-testing for Skill Testing,包括 smart contracts。
如何使用 property-based-testing 技能
安装并加载正确上下文
使用 npx skills add trailofbits/skills --skill property-based-testing 安装,然后先打开 SKILL.md。为了更快做判断,也建议阅读 README.md,以及最相关的参考文件:references/generating.md、references/reviewing.md 和 references/interpreting-failures.md。
把粗略想法变成可用提示
一个好的 property-based-testing usage 提示,应该明确写出目标、操作和你关心的保证。更好的输入示例是:“为这个 serializer 的 decode(encode(x)) 添加 PBT,输入限制在有效 UTF-8 和大小上限内。”较差的输入是:“给这个模块写 property tests。”前者给了技能一个真正的性质、有效的领域边界和期望的输出形态。
你的请求里应该提供什么
请包含语言、测试库、函数签名、已知不变量、无效输入行为,以及任何示例或规格说明。如果你是用 property-based-testing 指南做审查,请贴出当前测试,并说明你想要的是 bug-finding、重构,还是质量审计。如果代码里有 parsing 或 validation 路径,请说明遇到 malformed data 时应该发生什么;这能避免测试过于空泛,也能减少错误的 assume() 用法。
推荐工作流
先把代码映射到某一类性质:roundtrip、idempotence、invariant、ordering 或 oracle。然后定义 strategies,通过构造方式生成有效输入,而不是靠大量过滤。最后,在把失败直接当成 bug 之前,先参考 references/interpreting-failures.md 解读结果。对于 smart contracts,还要查看 EVM-specific notes,并把 state model 保持明确。
property-based-testing 技能常见问题
property-based-testing 能替代普通测试吗?
不能。这个技能最有价值的地方,是普通示例测试容易漏掉边界情况,或者一个性质就能覆盖很多行为。应保留示例测试来覆盖局部回归,再在“用少量案例很难清楚表达”的场景中使用 property-based-testing。
这个 property-based-testing 指南适合初学者吗?
适合,前提是目标行为足够简单,而且性质本身很明显,比如 roundtrip 或 idempotence 检查。若规格写得不够明确,难度就会明显上升,因为 PBT 需要先有清晰契约,generator 才真正有用。
什么情况下不该用这个技能?
当行为主要由 UI 驱动、具有高度非确定性,或者根本无法用稳定性质表达时,不要优先考虑它。如果唯一可用的 oracle 只是长链路的 reimplementation,而且只是把生产代码又镜像了一遍,这个技能也不太合适。
它适合我的语言或框架吗?
这个技能支持很多生态,包括 Hypothesis、fast-check、proptest、jqwik、ScalaCheck、FsCheck、StreamData、QuickCheck,以及像 Echidna 和 Medusa 这样的 smart contract fuzzer。如果你的技术栈不在这个列表里,底层方法仍然有帮助,但你可能需要调整测试语法和 strategy API。
如何改进 property-based-testing 技能
给出最强的性质,而不只是目标
最好的结果来自对“具体保证”的明确描述。例如:normalize(normalize(x)) == normalize(x) 针对 Unicode strings,就比“测试 normalize”更好。property-based-testing 技能在性质具体、可证伪、并且与已知契约直接相关时表现最好。
提供会影响 generator 的约束
常见失败模式包括无效输入、过滤过度的 strategies,以及性质太弱,抓不住真实 bug。想提升输出质量,就要说明可接受范围、格式规则、大小限制,以及是否预期抛出异常。如果某个性质只应在验证之后成立,也要明确说出来。
从失败样例继续迭代
当第一个测试失败时,不要只要求修复。请提供 shrink 后的反例、预期规则,以及定义边界行为的任何文档。这样技能才能区分“真实 bug”和“性质写错了”,并给出更强的第二轮测试或重构建议。
