pip install pytest pytest-cov pytest-randomly pytest-mock
- pytest-cov: カバレッジ計測プラグイン
- pytest-randomly: 実行順のランダム化
- pytest-mock: mock利用プラグイン
import pytest
class TestClassA:
@pytest.fixture
def target(self):
""" setUp / tearDown の代わりに fixture を使う。テストの前に呼び出される
"""
from name.space.to.moduleX import ClassA
return ClassA
@pytest.mark.parametrize("x, expected", # テストのパラメータ化はここで行う
[
(1, 2),
(2, 3)
]
def test_f(self, target, mocker, x, expected):
mock_ClassB = mocker.patch("name.space.to.moduleX.ClassB") # mockしておけば呼び出し先の実装は気にしなくていい
obj = target()
result = obj.f(x)
assert result == expected
mock_ClassB.assert_called_with(x) # mockを使ったら必ず渡している引数のテストを書く
pytest
pytest --lf
pytest --cov=<ソースコードのディレクトリ> --cov-report=html
pytest --cov=<ソースコードのディレクトリ> --cov-report=term-missing
個人的に一番ハマった場所。 テスト対象のモジュールから見たときの名前空間をパッチするのだが、説明するよりも実例を見る方が早い。
/name/space/to/moduleX.py
に書いてある ClassA
をテストしたいとする。
このモジュールでは /name/space/to/moduleY.py
に書いてある ClassB
を以下のようにimportしている。
from name.space.to.moduleY import ClassB
このときパッチを当てる名前空間は name.space.to.moduleX.ClassB
である。
moduleY
でないことに注意。
基本は tests/test_<name>/test_<space>/test_<to>/test_moduleX.py
と書くのだが、私は以下のような書き方をしている。
tests/
system/
name/
space/
to/
test_moduleX.py
unit/
name/
space/
to/
test_moduleX.py
外部接続を行わないユニットテストを unit
以下に、外部接続(他システムAPIを叩くなど)を必要とするテストを system
以下に書くようにしている。
もちろん単体で完結するパッケージならこのようにする必要はない。
やはり 公式ドキュメントが最新かつ確実な情報が載っているので、英語に抵抗がない限りはまずドキュメントに当たるのがいい。 Examplesには豊富な使い方の例が載っている。
書籍として読むならテスト駆動Pythonがおすすめ。書籍名に書いてあるようなテスト駆動の話は特になく、基本は全てPytestの話であることに注意。