🐞
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