🐞
Hypothesisで組み合わせでストラテジーを作る
hypothesis.strategies
にあるコアなストラテジーはよく使うけれども、それらを組み合わせてストラテジーを作りたいことがよくある。そういう場合にはいくつかの方法がある。
one_of
を使う(|
を使う)
one_of
に渡した複数のストラテジーの直和型のストラテジーが生成できる。たとえば数値か真偽値を返すストラテジーを作りたいという場合には次のようになる。
from hypothesis.strategies import booleans, integers, one_of
int_or_bool = one_of(integers(), booleans())
for _ in range(0, 5):
print(int_or_bool.example())
これを実行すると次のようになる。
-149
False
47081944555646014
-30273
-3379797192290189948
|
で連結してあげても複数のストラテジーの直和型のストラテジーが生成できる。先ほどと同様の例であれば
from hypothesis.strategies import booleans, integers
int_or_bool = integers() | booleas()
for _ in range(0, 5):
print(int_or_bool.example())
これを実行すると次のようになる
127
0
False
-966895869
3
ここで one_of
と |
で何が違うのかといえば、何も違わず、|
が one_of
のシュガーになっている。ともに hypothesis.strategies.OneOfStorategy
を返している。
composite
を使う
まだ one_of
で済む程度であればいいが、より複雑に組み合わせたい場合は、 @composite
を使って、新しいストラテジーを定義したほうが @given
にわたす場合に見通しが良くなる。
from hypothesis import given
from hypothesis.strategies import booleans, composite, integers, lists
@composite
def list_of_int_or_bool(draw):
int_or_bool = one_of(booleans(), integers())
return draw(lists(int_or_bool))
@given(list_of_int_or_bool)
def test_foo(x):
return any(isinstance(a, boolean) foor a in x)
この @composite
でデコレートされた関数の引数となっている draw
は特別な関数で、用途としては関数内で各ストラテジーの example
メソッドを呼んだのと同じような意味合いになっている。
Discussion