PythonでProperty-based TestingをするためのライブラリHypothesisのインストールと基本的な使い方を説明します。
日本語の情報が見つけられなかったので、こちらのページを参考に、備忘録がてら書いておきます。
ちなみに、「hypothesis」は、日本語で「仮説」という意味らしいです。
インストール
pipでインストールできます。
$ pip install hypothesis
サンプルコード内でnoseも使用してるので、noseもついでにインストールしてください。
$ pip install nose
使用したバージョンはそれぞれ以下になります。
ツール | バージョン |
---|---|
Python | 3.6.2 |
pip | 9.0.1 |
hypothesis | 3.30.2 |
nose | 1.3.7 |
使い方
Hypothesisを使ったサンプルコードが以下になります。
from nose.tools import raises
from hypothesis import given
from hypothesis.strategies import integers
def division(x, y):
return float(x) / float(y)
@given(x=integers())
def test_div(x):
"""整数値除算のテスト"""
print(x) # エラー時にログ表示
assert division(x * 2, x) == 2.0
@raises(ZeroDivisionError)
def test_divzero():
"""0除算のテスト"""
division('4', 0)
「given」というデコレータで、テストメソッドの引数の値を指定します。
ここでは x=integers()
とすることで、xの値を整数値のPropertyでテストすることができます。
@given(x=integers())
def test_div(x):
"""Test integers."""
print(x) # エラー時にログ表示
assert division(x * 2, x) == 2.0
テスト実行(エラー発生)
上記のコード(example.py)をテスト実行します。
$ nosetests example.py
E.
======================================================================
ERROR: Test integers.
----------------------------------------------------------------------
Traceback (most recent call last):
[...]
ZeroDivisionError: float division by zero
-------------------- >> begin captured stdout << ---------------------
102860293121396009173326105558127297308
55485753836579463694521216132454618744
55485753836579463694521216132454618624
62718710765820030520700417840365121327
62718710765820030520700417840365121280
121434099567864314412419957946238851931
-22018270800766606459394827539702648976
-22018270800766606459394827539702648832
-22018270800766606459394827539702648833
169012129506219865175533834052023541029
169012129506219865175533834052023540992
0
0
Falsifying example: test_div(x=0)
0
--------------------- >> end captured stdout << ----------------------
----------------------------------------------------------------------
Ran 2 tests in 0.066s
FAILED (errors=1)
一部省略してますが、上記のようなエラーが発生するはずです。
capturedを見てもらえればわかるように、複数の値でテストを実行してくれてます。
ここでエラーとなっているのは、テストケースの入力値として想定しない 0
がテストに含まれていることが原因です。
テストケースの修正(assume関数)
0
をテストケースから除外するために、assume関数を使用します。
修正版のコードが以下になります。
from nose.tools import raises
from hypothesis import given
from hypothesis import assume
from hypothesis.strategies import integers
def division(x, y):
return float(x) / float(y)
@given(x=integers())
def test_div(x):
"""整数値除算のテスト"""
assume(x != 0) # 0はテスト対象から除外する
print(x) # エラー時にログ表示
assert division(x * 2, x) == 2.0
@raises(ZeroDivisionError)
def test_divzero():
"""0除算のテスト"""
division('4', 0)
assume(x != 0)
でテスト条件を設定しています。
ここでは、0はテストケースに含まないように指定しています。
テスト実行
再度、テストを実行します。
$ nosetests example.py
..
----------------------------------------------------------------------
Ran 2 tests in 0.490s
OK
今回は、成功しました。
以上
こんな感じで、PythonでもProperty-based Testingをすることができます。
また、指定するデータのパターンはここに一覧があるので、テストケースに合わせて使用してください。