Hypothesis项目中的策略收缩设计指南

Hypothesis项目中的策略收缩设计指南

hypothesis hypothesis 项目地址: https://gitcode.com/gh_mirrors/hyp/hypothesis

引言

在自动化测试领域,测试用例的缩减(shrinking)是一个至关重要的功能。Hypothesis项目作为Python生态中最强大的基于属性的测试框架之一,其测试用例缩减能力尤为出色。本文将深入探讨如何在Hypothesis项目中设计能够良好收缩的策略(strategy),帮助开发者理解其内部机制并优化自定义策略。

何时需要考虑收缩设计

对于大多数使用者来说,Hypothesis内置的策略已经足够优秀,不需要特别关注收缩行为。但在以下两种情况下,优化策略的收缩行为是值得考虑的:

  1. 广泛使用的自定义策略:当你的策略将被大量用户使用时,优化收缩行为可以带来显著的集体效益
  2. 反复调试的痛点:如果你经常需要手动缩减复杂测试用例来调试问题

如果以上情况都不适用,建议直接使用Hypothesis提供的优秀默认实现,把精力放在更有价值的地方。

第三方策略的收缩设计

收缩的组合性

Hypothesis采用"自底向上"的收缩方式。这意味着策略中任何组件的简化都应该导致最终结果的简化。设计时需要确保这种简化符合用户直觉,避免与其他策略组合时产生奇怪的行为。

以复数生成策略为例,我们希望在收缩时虚部先趋于零,因为纯实数比纯虚数更"简单"。为此,我们首先生成虚部,然后根据虚部值计算实部的允许范围,而不是简单地生成两个浮点数组合。

让生成变得"幸运"

有时,我们需要刻意寻找某些特殊值进行测试。这种技巧应谨慎使用,最好放在可被收缩引擎跳过的分支中(如if draw(booleans()))。

以时区感知的日期时间生成为例,我们希望更频繁地生成夏令时转换导致的"跳过"或"重复"时刻。传统二分查找方法收缩成本较高,而采用随机点查找方法可以让收缩引擎删除中间步骤,看起来就像"幸运地"一次就找到了目标时刻。

保持数据局部性

Hypothesis将每个测试用例视为带标签的选择树,收缩操作就是对这些树的变换。保持数据的局部性对高效收缩至关重要:

  1. 避免先确定大小再生成集合:这会导致收缩性能下降

    # 不推荐
    integers(0, 10).flatmap(lambda n: st.lists(..., min_size=n, max_size=n))
    # 推荐
    st.lists(..., min_size=1, max_size=10)
    
  2. 将过滤条件尽量靠近相关部分:这样Hypothesis可以只重试失败的部分而非整个策略

  3. 集中绘制对象属性:一次性绘制对象所需的所有属性,便于统一修改或删除

Hypothesis内部的收缩实现

这部分主要针对Hypothesis的贡献者,涉及一些内部API的使用技巧。

内部API的优势

使用内部API可以:

  1. 在比特流级别操作,更清晰地建立值与缓冲区之间的对应关系
  2. 查看缓冲区的子集范围,支持变换操作如转置或删除
  3. 处理极端情况下的性能问题

创造自己的"幸运"

这个技巧用于优化带过滤的采样策略。基本思路是:

  1. 首先尝试常规的拒绝采样方法
  2. 如果失败,创建允许值的短列表并从中选择
  3. 将选择的值在原始列表中的索引写入缓冲区

这样收缩引擎删除前几步时,缓冲区会直接指向最终选择的值,看起来就像"一次就中"。

"收缩开放"的标志

受"群体测试"(Swarm Testing)启发,随机禁用某些特性可能反而能更快发现bug。实现时需要注意:

  1. 标志需要能"收缩开放",最终所有标志都会被启用
  2. 需要使用拒绝采样或类似技术

以Unicode字符串生成为例,我们可以:

  1. 生成一组禁用的字符类别
  2. 使用characters().filter(category_is_not_banned)

收缩时先移除禁用类别,然后再按常规方式缩减字符串。

显式的示例边界

虽然通常由内部工具如cu.many处理,但有时显式标记需要同时删除的绘制部分很有用。例如:

  1. 将浮点数的值和符号组合在一起
  2. 标记可变大小的绘制,便于删除无用字节
  3. 标记难以区分的绘制,便于交换相似值

结语

Hypothesis的测试用例缩减系统是其强大功能的核心之一。理解这些设计原则和实现技巧,可以帮助开发者构建更高效、更可靠的自定义策略,无论是作为第三方库作者还是Hypothesis的贡献者。记住,大多数情况下内置策略已经足够优秀,只有在真正需要时才应该投入精力优化收缩行为。

hypothesis hypothesis 项目地址: https://gitcode.com/gh_mirrors/hyp/hypothesis

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柯展隽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值