具有不同类型值的字典的假设搜索策略

Hypothesis search strategy for dictionaries with different types of values

我正在尝试使用假设模块生成包含不同 python 类型作为值的字典。

对于列表,我可以简单地使用表达式

from hypothesis import given
import hypothesis.strategies as st

@given(
    st.lists(
        st.from_type(type)
            .flatmap(st.from_type)
            .filter(lambda x: not isinstance(x, (type(None)))),
        min_size=2,
        unique_by=lambda x: type(x),
    )
)
def test_something(dictionary):
    ...

这给了我 [int, str, ...] (每个条目都有不同的 python 类型)。 但是对于字典,我没有 unique_by 的值。

@given(
    st.dictionaries(
        st.text(min_size=1, max_size=10),
        st.from_type(type).flatmap(st.from_type)
            .filter(lambda x: not isinstance(x, (type(None), bool))),
        min_size=2,
    )
)
def test_something(dictionary):
    ...

这导致例如{'a': int, 'b': int, ...} → 所有条目的值类型都相同。

有没有简单的方法生成{'a': int, 'b': str, ..}dict.values()中至少有两种不同的python类型)?

我们可以重用您的初始方法,因为 dict 可以从键值对构建,例如

from hypothesis import given, strategies as st


@given(st.builds(zip,
                 st.lists(st.text(min_size=1, max_size=10),
                          min_size=2,
                          unique=True),
                 st.lists(st.from_type(type)
                          .flatmap(st.from_type)
                          .filter(lambda x: not isinstance(x, (type(None)))),
                          min_size=2,
                          unique_by=lambda x: type(x),
                          ))
       .map(dict))
def test_something(dictionary):
    values_types = list(map(type, dictionary.values()))

    assert len(set(values_types)) == len(values_types)

正如 Azat Ibrakov 提到的,您可以从键值对构建它 - 但使用键值对比将两个列表压缩在一起更有效(因为如果列表长度不同,它可以避免丢弃一些元素) :

from hypothesis import given, strategies as st


@given(
    st.lists(
        st.tuples(
            st.text(min_size=1, max_size=10),
            st.from_type(type).flatmap(st.from_type).filter(lambda x: x is not None),
        ),
        min_size=2,
        unique_by=(lambda kv: kv[0], lambda kv: type(kv[1])),
    ).map(dict)
)
def test_something(dictionary):
    values_types = list(map(type, dictionary.values()))
    assert len(set(values_types)) == len(values_types)