我有一个类似的功能(它实际上是一个类,但在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();
而另一个没有?
答案 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)]
这会为b
,c
和(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()
内的条件将其设置为其他条件。