使用 st.deferred() 使用具有已知键的假设生成字典值,并且特定值策略无法按预期工作

using st.deferred() to generate dictionary values using hypothesis with known keys, and specific value strategies doesn't work as expected

提问人:hadromi 提问时间:11/5/2023 更新时间:11/15/2023 访问量:13

问:

我正在尝试生成复杂的树状字典来测试我的代码。 字典基本上是复合类,包含结构列表和更简单的字段。

我使用的是假设策略延迟方法,通过 lambda 函数实现,我想将某个生成的“键”映射到为该“键”制定的特定策略。出于某种原因,我的映射似乎没有按预期工作,并且不同的“键”获得了不同的策略。

将不胜感激您的帮助。谢谢。

这是我尝试过的:


name_strategy = st.text(min_size=0, max_size=10)
fanout_ref_strategy = st.lists(st.booleans())

MyClass_keys = [
    "name",
    "fanout_ref",
]  

MyClass_strategy_mapping = {
    "name": name_strategy,
    "fanout_ref": fanout_ref_strategy,
}
MyClass_value_strategy = st.deferred(lambda: MyClass_key_strategy.map(MyClass_strategy_mapping.get) | MyClass_key_strategy)
MyClass_key_strategy = st.sampled_from(MyClass_keys)
MyClass_strategy = st.dictionaries(keys=MyClass_key_strategy, values=MyClass_value_strategy)

@given(specific_dict=MyClass_strategy)
def test_specific_dictionary(specific_dict):
    # Your test code here
    print(specific_dict)

这是我看到的生成输出:

{}
{}
{'name': text(max_size=10)}
{'fanout_ref': 'name', 'name': text(max_size=10)}
{'fanout_ref': text(max_size=10), 'name': text(max_size=10)}
{'fanout_ref': lists(booleans())}
{'fanout_ref': lists(booleans()), 'name': lists(booleans())}
{'fanout_ref': text(max_size=10), 'name': lists(booleans())}
{'name': lists(booleans()), 'fanout_ref': lists(booleans())}
{'name': lists(booleans()), 'fanout_ref': 'fanout_ref'}
{'name': text(max_size=10)}
{'name': text(max_size=10)}

我期待有字典,以“name”和“fanout_ref”为键,字符串和布尔值列表为值。

pytest 假设-测试 python-hypothesis

评论


答:

0赞 Zac Hatfield-Dodds 11/15/2023 #1

执行此操作的惯用方法使用 st.fixed_dictionaries()

MyClass_strategy = st.fixed_dictionaries(
    {"name": st.text(min_size=0, max_size=10),
     "fanout_ref": st.lists(st.booleans())}
)

另外,您可能希望了解示例代码不起作用的原因。

一个错误是 和 策略是完全独立的 - 如果你需要每个键的特定值,你需要使用 ,或者为共享值策略的每组键生成和合并一个字典。keys=values=st.dictionaries()fixed_dictionaries()

另一个错误是st.deferred(lambda: MyClass_key_strategy.map(MyClass_strategy_mapping.get) | MyClass_key_strategy)

  • 什么都没做st.deferred()
  • 他们说你可以从关键策略中产生价值| MyClass_key_strategy
  • 将策略作为值返回;还要从返回的策略中汲取您需要的 .这是文档;它看起来像..map().flatmap()= MyClass_key_strategy.flatmap(MyClass_strategy_mapping.get)

最后,并不总是生成所有可能的键 - 您需要为此进行设置,尽管从相对于 的一组固定键生成是一种非常糟糕的方法。st.dictionaries()min_size=2fixed_dictionaries