假设(Python):省略论证

时间:2017-11-01 09:52:52

标签: python python-3.x python-hypothesis

我有一个类似的功能(它实际上是一个类,但在Python的打字方式下它并不相关):

def myfunc(a=None, b=None):
    <snip>

现在我想编写一个假设测试,它始终提供a,但有时只提供b

我试过

from hypothesis import given, strategies as strat

@given(a=strat.booleans())
@given(b=strat.integers(min_value=1) | strat.nothing())
def test_model_properties(self, **kwargs):
    myval = myfunc(**kwargs)
    <snip>

但似乎只有strat.nothing()才会跳过该测试运行(我将hypothesis.errors.FailedHealthCheck: It looks like your strategy is filtering out a lot of data.作为b的唯一策略时使用b

我怎样才能有时只提供假设检验的论证?我是否需要编写两个测试,一个使用 string query = @"UPDATE prijslijst SET omschrijving = @omschrijving, prijs = @prijs, catagorie = @catagorie WHERE id = @id"; SqlCommand cmd = new SqlCommand(query, connDatabase); cmd.Parameters.Add("@id", SqlDbType.integer).Value = 7; cmd.ExecuteNonQuery(); connDatabase.Close(); 而另一个没有?

4 个答案:

答案 0 :(得分:2)

您的方法可以保证失败,因为hypothesis docs暗示

hypothesis.strategies.nothing()[source]

    This strategy never successfully draws a value and will always reject on an attempt to draw.

您尝试不为b提供值始终会失败。

这个怎么样:

from hypothesis.strategies import tuples, integers, booleans, one_of
B = booleans()
I = integers(min_value=0, max_value=10)
one_of(tuples(B), tuples(B, I)).example()

在一系列试验中,我给了(True,)(False, 9)(False, 4)(True, 5)(False,)等输出。

您当然会将此与*args而不是**kwargs一起使用。

答案 1 :(得分:1)

jacq's answer让我走上正轨 - 选择关键字需要成为自己的策略。

使用标准词典

std = {'a': strat.booleans()}

和可选字典

opt = {
    'b': strat.integers(),
    'c': strat.integers(),
}

然后我可以使用chained list comprehension来表示所有可能的“可选参数组合”:

# chain.from_iterable may or may not be faster; it doesn't matter for me.
optional = [combo
            for n in range(len(opt.items()))
            for combo in itertools.combinations(opt.items(), n+1)]

这会为bc(b, c)生成键值元组。

为了绘制一组值,我们需要获得其中一个选项,可以使用sampled_from(optional)来完成。使用获得的元组,除了std字典中的策略之外,我们必须从内部策略中提取。

strat.sampled_from(optional).flatmap(
    lambda x: strat.fixed_dictionaries(
        {**std, **dict(x)}
    )
)

这可以全部包含在一个函数中,我们称之为valid_values()。如果您在包装函数的签名中指定@given(valid_values())*args,则无法使用**kwargs

因此,test_model_properties(self, **kwargs)变为test_model_properties(self, kwargs)(您可以使用@given(kwargs=valid_values())) - 通过调用字典kwargs,函数的其余部分保持不变。

注意:如果您希望没有可选参数,则不会包含空元组,但可以轻松地将其附加到optional列表中。或者,使用range(n+1)代替combinations(..., n+1),因此包括长度为0。

答案 2 :(得分:1)

看起来您需要none()而不是nothing()

from hypothesis import given, strategies as strat

@given(a=strat.booleans(), b=strat.none() | strat.integers(min_value=1))
def test_model_properties(self, **kwargs):
    myval = myfunc(**kwargs)
    ...

这比生成字典用作** kwargs更简单,也更有效。对b的策略进行排序也非常重要 - 首先放置none()可确保最小示例为a=False, b=None而不是a=False, b=1

另请注意,与单次使用相比,多次应用@given效率非常低,并且自版本3.34.0起实际上已弃用。

答案 3 :(得分:-1)

怎么样:

def myfunc(a=None, b=None):
    if b is None:
        b=strat.nothing() 
        # Or whatever you would like b to be when you don't supply an argument
    else:
        <snip>

因此,您b成为默认值(在这种情况下,None)会触发&#39; if&#39; myfunc()内的条件将其设置为其他条件。