简体   繁体   English

创建返回唯一值的假设策略

[英]Create hypothesis strategy that returns unique values

I'm trying to create a hypothesis strategy which produces integers with no repeats.我正在尝试创建一个hypothesis策略,它产生没有重复的整数。 Here's my code:这是我的代码:

import hypothesis
import hypothesis.strategies as strategies

def unique(strat):
    previous = set()

    @strategies.composite
    def new_strategy(draw):
        while True:
            value = draw(strat)
            if value not in previous:
                previous.add(value)
                return value

    return new_strategy

strategy = unique(strategies.integers(min_value=0, max_value=1000))

@hypothesis.given(num=strategy)
def test_unique(num):
    pass

However, when I run pytest , I get但是,当我运行pytest时,我得到

    @check_function
    def check_strategy(arg, name="")
        if not isinstance(arg, SearchStrategy):
            hint = ""
            if isinstance(arg, (list, tuple)):
                hint = ", such as st.sampled_from({}),".format(name or "...")
            if name:
                name += "="
            raise InvalidArgument(
                "Expected a SearchStrategy%s but got %s%r (type=%s)"
                % (hint, name, arg, type(arg).__name__)
            )
E           hypothesis.errors.InvalidArgument: Expected a SearchStrategy but got mapping['num']=<function accept.<locals>.new_strategy at 0x7f30622418b0> (type=function)
@st.composite
def unique(draw, strategy):
    seen = draw(st.shared(st.sets()))
    return draw(
        strategy
        .filter(lambda x: x not in seen)
        .map(lambda x: seen.add(x) or x)
    )

There's a couple of cute tricks here:这里有几个可爱的技巧:

  1. Use st.shared() to create a new seen cache for each distinct example.使用st.shared()为每个不同的示例创建一个新的seen缓存。 This fixes your "what if you run out of values" problem, but also fixes your critical "the test can't replay failures" problem which would make the whole thing horribly flaky.这解决了您的“如果您的值用完怎么办”问题,但解决了您的关键“测试无法重播失败”问题,这将使整个事情变得非常脆弱。
    • For advanced tricks, try using the key= argument to `shared, or having it construct a dictionary.对于高级技巧,尝试使用 `shared 的key=参数,或者让它构造一个字典。
  2. .filter(...) to exclude already-seen items. .filter(...)排除已经看到的项目。 This is better than a loop because it means Hypothesis can more effectively avoid and report on futile attempts to generate a not-yet-seen example.这比循环更好,因为这意味着假设可以更有效地避免和报告徒劳的尝试来生成一个尚未见过的例子。
  3. The .map(...) call to add it to the set is a blatant abuse of the facts that set.add() returns None after mutating the object, and that or evaluates to the second item if the first is falsey.将其添加到集合中的.map(...)调用是对set.add()在改变 object 后返回None的事实的公然滥用,并且如果第一个是假的,则它or评估为第二个项目。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM