首页 > 解决方案 > 如何在假设中定义策略以生成一对相似的递归对象

问题描述

我是假设的新手,我正在寻找一种方法来生成一对相似的递归对象。

我对单个对象的策略类似于假设文档中的这个示例

我想测试一个采用一对递归对象 A 和 B 的函数,这个函数的副作用应该是A==B.

我的第一种方法是编写一个获取两个独立对象的测试,例如:

@given(my_objects(), my_objects())
def test_is_equal(a, b):
    my_function(a, b)
    assert a == b

但缺点是假设不知道这两个对象之间存在依赖关系,因此它们可能完全不同。这是一个有效的测试,我也想测试它。

但我也想测试只是略有不同的复杂递归对象。

也许该假设能够将测试失败的一对非常不同的对象缩小为测试以相同方式失败的一对仅略有不同的对象。

标签: python-hypothesis

解决方案


这很棘手 - 老实说,我会先编写与您上面已有的相同的测试,然后将 max_examples 设置得很长。然后我可能会编写一些传统的单元测试,因为明确不支持从假设中获取特定的数据分布(即,我们尝试使用启发式和一些反馈的某种组合来打破假设特定分布的所有内容)。

我将如何实际生成类似的递归结构?我会使用一种@composite策略同时构建它们,对于每个元素或子树,我会绘制一个布尔值,如果 True 绘制不同的元素或子树以在第二个对象中使用。请注意,这将为您提供一个包含两个对象的元组的策略,您需要在测试中解压缩它;如果您希望它们相关,这是不可避免的。

认真地尝试首先在幼稚的方法上破解 max_examples,运行 Hypothesis 约一个小时非常有效,我什至希望它可以很好地缩小输出。


推荐阅读