Pytestを利用したPythonのユニットテスト
最近ちょっと忙しくなってきて、ブログの更新頻度が減ってきてたので、ぼちぼち更新していこうかなと。。。
ということで、テスト関連で少し記載していきます。
今まで、Pythonのテストとしては、組み込みの unittest
を利用することが多かったのですが、最近 pytest
を触れる機会があったので、そちらに関して記載して行こうと思います。
Pytestとは
Pythonのテスティングフレームワークで、小さくて簡単なテストから、複雑なテストまでサポートをしてくれるようです。
pytest: helps you write better programs — pytest documentation
インストール
pip install pytest
使い方
pytest
コマンドで、ファイル名の先頭が test_
で始まるファイル(デフォルト設定)内の、先頭がtest_
で始まる関数(メソッド)をテスト対象として、テストを実行します。
assert
文を利用し、結果がFAILのものを出力してくれます。
def inc(x): return x + 1 def test_answer(): assert inc(1) == 2 assert inc(2) == 2
pytest ============================================================================================================ test session starts ============================================================================================================= platform darwin -- Python 3.6.1, pytest-3.6.2, py-1.5.3, pluggy-0.6.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 1 item test_sample.py F [100%] ================================================================================================================== FAILURES ================================================================================================================== ________________________________________________________________________________________________________________ test_answer _________________________________________________________________________________________________________________ def test_answer(): assert inc(1) == 2 > assert inc(2) == 2 E assert 3 == 2 E + where 3 = inc(2) test_sample.py:9: AssertionError ========================================================================================================== 1 failed in 0.14 seconds ==========================================================================================================
assert文について
assertの条件に満たないものについて、AssertionError
を発生させます。
assert 条件, メッセージ
詳しくは、以下の記事が参考になりました。
クラスベース
テストケースをクラスごとに、グルーピングすることが可能です。
class TestClass(object): def test_one(self): x = "this" assert 'h' in x def test_two(self): x = "hello" assert hasattr(x, 'check')
fixture
pytestにはfixture
という機能があり、これを利用することで、繰り返し実行するケースや、テストの前後処理等、様々な場面で活用することが出来ます。
import pytest @pytest.fixture def user_api_mock(): return { 'first_name': 'Taro', 'last_name': 'Tanaka', 'age': 32 } def test_fullname(user_api_mock): assert user_api_mock['first_name'] + user_api_mock['last_name'] == 'TaroTanaka'
setup/teardown
unittestの setUp
、tearDown
に相当する機能です。
- Moduleレベル
def setup_module(module): """ モジュールテスト実行の前処理 """ def teardown_module(module): """ モジュールテスト実行の後処理 """
- Classレベル
class TestClass(object): @classmethod def setup_class(self): """ テストclass実行の前処理 """ @classmethod def teardown_class(self): """ テストclass実行の後処理 """
設定
実行対象のディレクトリ以下に、conftest.py
ファイル名で、pytestの設定を変えることが出来ます。
- 例: pytestに引数を追加する
import pytest # pytest_plugins = 'plugin_name' # pluginの追加も可能 def pytest_addoption(parser): parser.addoption('--target', default='unit', dest='target', help='Target test type (all|e2e|unit)') def pytest_configure(config): config.addinivalue_line('markers', 'target(name): Target test type name.') def pytest_runtest_setup(item): target = [mark.args[0] for mark in item.iter_markers(name='target')] if target: if item.config.getoption('--target') not in target: pytest.skip('test require target in %r' % target)
pytest --help ... custom options: --target=TARGET Target test type (all|e2e|unit)
プラグイン
よく使うプラグインをいくつか紹介です。
Good Integration Practices
公式で紹介されている、Good Integration Practicesの解説をかいつまんでみました。
- ディレクトリ構造
Pythonのパッケージ開発の構造。他にもいくつかありますが、とりあえず、ここでは1パッケージ単位で解説します。
setup.py mypkg/ __init__.py app.py view.py tests/ test_app.py test_view.py
- setup.py
pytest-runner
プラグインを使用して、テスト実行をsetuptoolsベースのプロジェクトに統合することができます。
from setuptools import setup setup( # ..., setup_requires=["pytest-runner", ...], tests_require=["pytest", ...], # ここで予めplugin入れてもok # ..., )
- setup.cfg
aliasesとしてpytestを指定します。
[aliases] test=pytest
pytestの設定も指定することが出来ます。
[tool:pytest] addopts = --verbose --cov cchan_web --cov-report html --cov-config .coveragerc python_files = tests/*/test_*.py norecursedirs = .git .tox .env venv dist build south_migrations migrations example
.coveragerc
で pytest-covの設定が指定できます。
- 実行
python setup.py test