尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Hypothesis 对计算机科学研究者的价值:从 QuickCheck 到 Conjecture 引擎的探索

发布时间:2026/9/25 5:56:52

资讯中心
01
ARTICLE

Hypothesis 对计算机科学研究者的价值:从 QuickCheck 到 Conjecture 引擎的探索

Hypothesis 对计算机科学研究者的价值:从 QuickCheck 到 Conjecture 引擎的探索
测试开发工具【免费下载链接】hypothesisThe property-based testing library for Python项目地址https://gitcode.com/gh_mirrors/hy/hypothesis点击查看免费下载Hypothesis 是 Python 生态中广泛使用的 property-based testing属性测试库。本文源自项目作者 David MacIver 于 2017 年撰写的技术长文见 website/content/2017-03-09-hypothesis-for-researchers.md面向潜在博士导师与测试/验证领域研究者系统回答了四个问题Hypothesis 是什么、创新点在哪里、基于哪些先验工作、以及有哪些值得投入的研究方向。文中所有示例均可直接在本仓库中运行验证源码引用以 hypothesis/src/hypothesis/internal/conjecture/ 下的实现为准可将其视为可运行的研究文献。研究视角下为什么要关注 Hypothesis简短回答Hypothesis 把一种已在实践中被证明高效的测试风格——property-based testing——带给了更广泛的受众。它通过组合此前在测试与验证研究文献中彼此孤立的多条思想线索产生了一个在实践中被验证为非常有效的全新实现。详细回答就是本文的其余部分。文章按以下脉络展开What is Hypothesis?从零介绍 Hypothesis如果你已熟悉 QuickCheck 这类 property-based testing 可跳过How is Hypothesis innovative?介绍 Hypothesis 的当前技术水准及其有趣之处What prior art is it based on?给出支撑 Hypothesis 设计的主要文献脉络篇幅短但值得一读What are some interesting research directions?探索作者对 Hypothesis 未来走向的思考其中部分有望进入相关博士课题。什么是 Hypothesis属性测试的现代实现Hypothesis 是property-based testing的一个实现。这一思想起源于 Haskell 库 QuickCheck用结构化随机数据补充单元测试让工具自动探索测试的边缘情况、尝试发现错误。属性测试的核心是描述性质而非手写用例——你只需声明一段代码应当始终满足的性质测试框架负责生成尽可能多的输入去验证它。一个可运行的例子排序的幂等性下面的测试断言对同一个列表排序两次结果不变from hypothesis import given, strategies as st given(st.lists(st.integers())) def test_sort_is_idempotent(ls): sort1 sorted(ls) assert sorted(sort1) sort1given装饰器把普通函数暴露给标准测试运行器如 pytest也可以直接调用if __name__ __main__: test_sort_is_idempotent()运行时Hypothesis 会生成随机整数列表并传入测试函数先排序一次再排一次断言两次结果相等。只要每个输入都通过它看起来就是个普通测试。关键差异发生在失败时Hypothesis 会反复用逐渐更简单的例子重跑测试直到找到一个引发失败的最小输入。假如我们写了一个错误的排序实现def sorted(ls): return list(reversed(ls))运行后输出given(st.lists(st.integers())) def test_sort_is_idempotent(ls): sort1 sorted(ls) assert sorted(sort1) sort1 E assert [0, 1] [1, 0] E At index 0 diff: 0 ! 1 E Use -v to get the full diff sorting.py:12: AssertionError ---- Hypothesis ---- Failing test case: test_sort_is_idempotent(ls[0, 1])Hypothesis 最初很可能从更复杂的例子开始几乎所有长度大于 1 的列表都会失败然后成功约简为最简情形一个含两个不同元素的列表。这就是shrinking最小化机制在 engine.py 的shrink_interesting_test_cases中引擎把每个失败用例替换为具有相同interesting_origin的最小失败用例并对过程中发现的新失败持续收缩直至 500 次收缩上限MAX_SHRINKS见 engine.py或 300 秒总时长上限MAX_SHRINKING_SECONDS见 engine.py被触发。更重要的是测试重跑时Hypothesis 会从上次找到的失败例子出发而不是重新生成并收缩一个新例子见reuse_existing_test_casesengine.py。对简单用例这差别不大但对复杂、慢速的测试而言这是开发工作流的关键一环测试跑得更快并且在 bug 真正修复前不会停止失败。这也是示例可保存、可回放能力的底层支撑——数据库模块database.py负责把失败用例序列化为字节并持久化重跑时按最短优先策略取回。测试中动态抽取数据Hypothesis 允许测试在执行过程中按需继续抽取数据given(st.lists(st.integers(), min_size1), st.data()) def test_sort_is_idempotent(ls, data): ls.sort() i data.draw(st.integers(0, len(ls) - 1)) assert ls[i - 1] ls[i]这个测试失败因为忘了i可能为 0也忘了 Python 列表的负索引given(st.lists(st.integers(), min_size1), st.data()) def test_sort_is_idempotent(ls, data): ls.sort() i data.draw(st.integers(0, len(ls) - 1)) assert ls[i - 1] ls[i] E assert 1 0 sorting.py:15: AssertionError ---- Hypothesis ---- Failing test case: test_sort_is_idempotent(ls[0, 1], datadata(...)) Draw 1: 0以这种方式抽取的数据其收缩与失败示例保存同样正常工作。这个互动式抽取能力正是 Hypothesis 区别于 QuickCheck 传统模型的核心data.draw在运行时向引擎请求更多字节流st.data()策略定义于 core.py引擎的ConjectureData.drawdata.py负责把字节流翻译回策略值。模型化测试Model-Based TestingHypothesis 还提供规则化状态机测试你定义一组作用于 API 的合法操作它尝试用这些操作拼出完整程序并寻找能破坏不变量/断言的简单序列。实现位于 stateful.pyRuleBasedStateMachine类stateful.py配合rulestateful.py与preconditionstateful.py装饰器用Bundle在规则之间传递产生/消费的值。这种测试形态把 property-based testing 从单次输入的性质推广到整个交互序列的性质。Hypothesis 的创新之处从最终用户视角Hypothesis 带来了几项重要改进它真实存在且有人用这类测试历史上主要活跃于函数式编程社群在其他语言中的推广鲜有成功。Hypothesis 能做到一部分归功于其新颖的实现细节一部分归功于让它感觉像普通测试而非形式化方法的设计决策。生成器定义更简单且免费获得大量功能与传统 QuickCheck 风格相比Hypothesis 的 API 设计提供了显著更高的灵活性——这一点与 Clojure 的 test.check 或 Erlang 版 QuickCheck 相似但若干设计决策使其更灵活。任意示例可保存与回放这大幅改善了开发工作流。其他 property-based testing 实现要么完全不保存、只保存随机种子要么依赖序列化生成对象读回时可能破坏不变量。Hypothesis 的引擎天然支持字节级序列化不需要策略层参与。测试内可动态生成额外数据这一能力似乎在同类别工具中是 Hypothesis 独有的其底层就是上一节的data.draw机制。这些特性共同作用相当有效地把 property-based testing 带给了大众Hypothesis 在 Python 社群中的使用越来越广泛并被用于工具与库的开发中包括 CPython 和 PyPy 这两大 Python 实现自身的开发。实现层面的核心创新上述用户侧优势大多源于实现上的根本差异与其他 property-based testing 实现不同Hypothesis 完全不需要理解它正在生成的数据结构它偶尔会猜测结构但正确性不依赖这些猜测的准确性。Hypothesis 在逻辑上分为三个相互独立的部件核心引擎 Conjecture可视为一个面向轻结构化字节流的交互式 fuzzer。它负责生成、收缩、序列化——策略实现无需感知这些特性即可正确工作只需反复向引擎索要字节块并返回期望的结果。策略库strategy library把 Conjecture 的输出翻译为语言中可表示的各种值。例如st.lists(elements, min_size0, max_sizeNone, uniqueFalse, unique_byNone)core.py支持长度区间、元素唯一性等约束st.integers(min_value, max_value)numbers.py生成的整数向 0 收缩。外部测试运行器接口接收建立在策略库之上的测试并用 Conjecture 执行它们。在 Python 中这主要是暴露一个可被运行器识别的函数given装饰器而在 Java 原型中则涉及与 JUnit 特定特性的交互。Conjecture 正是 Hypothesis 实现中最有趣的部分支撑了绝大部分功能。在源码中ConjectureRunnerengine.py维护随机源、数据库键、感兴趣失败用例集与帕累托前沿等状态其run()engine.py按reuse复用数据库用例→ generate生成新用例→ shrink收缩失败用例三阶段推进见_runengine.py与Phase配置reuse/generate/target/shrink/explain一一对应。ConjectureDatadata.py则以max_choices、prefix、observer等字段记录单次测试运行的所有抽取与状态。基于哪些先验工作文献脉络在开发 Hypothesis 的过程中作者进行了大量文献阅读。支撑其设计的两篇核心论文是QuickCheck: a lightweight tool for random testing of Haskell programs基本开创了整个 property-based testing 领域。Hypothesis 最初就是一个 QuickCheck 实现其面向用户的 API 至今仍深受 QuickCheck 影响——尽管底层实现已与其分道扬镳上文的given 策略组合风格即是明证。EXPLODE: a lightweight, general system for finding serious storage system errors提供了 Conjecture 引擎的关键思想——不做与测试分离的静态数据生成而是给测试提供一个可从中抽取数据的交互式原语对应本仓库中的data.draw与ConjectureData.draw。此外Conjecture 引擎还有两个重要的设计灵感来源虽然其设计当前未被直接使用American Fuzzy LopAFL优秀的面向安全的 fuzzer。作者从中学习了不少 fuzzer 设计知识由于多种务实原因目前没有使用它最重要的创新用分支覆盖度量驱动语料发现但已在 Hypothesis 之上成功原型化了该实现且效果不错。Swarm Testing推动了早期数据生成设计的许多决策。当前并未显式出现在 Conjecture 实现中但 Conjecture 为诱导数据中刻意关联所做的一些工作受其启发。有趣的研究方向作者列出了若干可能的研究方向。需要说明这些方向并不必然成为博士课题的焦点——真正做博士时几乎肯定会聚焦更具体的研究问题。值得注意的共同点是大多数方向都能在不改变 Hypothesis 公开接口的前提下带来改进这意味着由于大量且不断增长的开源项目已在用 Hypothesis许多改动可以仅通过跑别人现成的测试、看能否发现新 bugs来部分验证——这是极具实操优势的研究环境。更结构化的字节流当前最直接的研究焦点把 Conjecture 的核心原语替换为更有结构的形式使其更贴近 EXPLODE 的起源。这旨在解决用户当前遇到的实际问题大多与性能相关同时为构建在核心引擎之上的新抽象打开空间。具体设想是精简接口调用 Conjecture 时只抽取单个字节并指定合法字节的取值范围。这让引擎获得更细粒度的信息从而支撑更多新特性与抽象。由此原语可重建出能正确收缩的任意加权采样器使用 Alias Method 的变体与任意文法可能使用 Boltzmann Samplers 或类似方法。这比当前有点临时的字节流指定方式为高质量数据生成提供了更扎实的基础。这或许更多是工程而非研究但至少能让关于核心方法的论文更有说服力且包含大量有趣的理论应用。玻璃箱测试Glass Box Testing当前 Conjecture 把测试视为黑箱几乎拿不到测试在执行什么的信息。一个明显的方向是借鉴 AFL 的思路引入更多覆盖信息但作者坦承目前这些原型方案在真实场景中尚不理想——主要原因在于所有已尝试的技术在允许测试运行数分钟或数小时时表现良好而 Hypothesis 当前的设计目标是测试最多运行数秒这限制了这些方法的效用因此尚未成为优先级。但原则上这应是一条极富成效的路线。主要设想是给 Conjecture 核心引擎加入tags概念用于引导搜索覆盖信息只是 tags 的一个来源其他来源同样可能。例如作者之前关于 Schroedinteger 的工作实现了某种轻量级 Concolic testing可成为另一个有趣的信息来源。如何在严格受限的时间内用好这类信息很可能结出有趣的果实观察 Concolic testing 在真实世界的表现也会引出大量新问题。让 Conjecture 引擎更聪明作者过去曾研究用文法推断grammar inference改进收缩与数据生成。当时遇到的障碍是所用算法——L* 搜索的优化变体——在实际问题上性能不佳。Synthesizing Program Input Grammars 一文承诺通过在实际场景中提供更好的文法推断来解除这一限制而该场景与这一问题域密切相关因此值得重新审视。此外结合玻璃箱测试特性Conjecture 引擎很可能还有多种探测被测系统状态、发现潜在有趣行为的方式。由于此前连可接受的性能都未达到第一步自然是验证能否达到这还需要大量实证实验此时用 Hypothesis 测试的开源项目语料将极其有用。其他测试抽象尽管 Hypothesis 首先是 property-based testing 库核心 Conjecture 引擎本身其实与属性测试关系不大而是一种更强大的底层测试抽象。探索它能走多远会很有趣——现有的状态机/模型测试已是迈向该方向的一步但引擎还可更直接地用于其他目的例如配合上述特性对二进制进行底层 fuzzing或驱动线程调度。Conjecture 分离设计的好处在于它足够自包含可被当作核心构建块让其他工具在其上重建并获得大量主要特性。作者目前没有具体计划但认为在进一步研读测试文献后这里很可能浮现出有趣的可能性——即便目前看来多半是工程工作除非出现特别有趣的应用。你应该如何消化这些信息取决于你是谁如果你已经是潜在博士导师请告诉作者什么引起了你的兴趣并多提问如果你是尚未接触的潜在博士导师且有意向欢迎直接联系如果你是其他读者主动权在你——可以发送论文、问题等任何内容。无论你是谁若觉得这篇文章有意思都可以通过 daviddrmaciver.com 与作者联系。延伸阅读与验证路径若要亲自验证本文论述最直接的路径是在仓库中运行 hypothesis/tests/ 下的测试集特别是 hypothesis/tests/cover/覆盖核心功能与 hypothesis/tests/conjecture/针对引擎本身的测试如test_engine.py、test_shrinker.py、test_provider.py阅读 guides/internals.rst 与 hypothesis/docs/reference/internals.rst 了解引擎内部设计参考 hypothesis/rust/ 下用 Rust 实现的部分底层原语如cathetus与浮点处理体现引擎跨语言复用的方向若想从更高层面理解设计取舍可阅读 website/content/2016-12-10-how-hypothesis-works.md。从 2017 年至今Conjecture 的三阶段运行框架、失败用例回放、动态抽取等核心思想在 hypothesis/src/hypothesis/ 中依然清晰可辨——这正是本文所描述的架构持续演进、并被验证有效的直接证据。赞分享测试开发工具【免费下载链接】hypothesisThe property-based testing library for Python项目地址https://gitcode.com/gh_mirrors/hy/hypothesis点击查看免费下载相关推荐BaiduPCS-Go学术论文在计算机科学领域的研究价值BaiduPCS Go学术论文在计算机科学领域的研究价值 摘要 BaiduPCS Go作为一款开源的百度网盘命令行客户端在计算机科学领域具有多方面的研究价值CLI网络OpenCore Legacy Patcher三步让老旧Mac焕发新生体验最新macOS的终极指南OpenCore Legacy Patcher三步让老旧Mac焕发新生体验最新macOS的终极指南 你是否有一台被苹果官方抛弃的老旧Mac看着手中的2测试开发工具torchao模型优化的跨学科研究从计算机科学到神经科学torchao模型优化的跨学科研究从计算机科学到神经科学 在人工智能模型日益复杂的今天如何在有限的计算资源下实现高效训练与推理成为关键挑战。torchao作上一篇marshmallow与PySpark集成大数据处理中的数据转换方案下一篇lbry-sdk P2P流量控制拥塞避免算法实现创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。