状況
- 毎回は実行したくないテストをpytestで書いている(エンドツーエンドテスト、負荷テストなど)。
- 引数なしのpytestコマンドだけで、必要なテストが実行できると便利。
問題
- pytestに引数を付けないと、すべてのテストが実行されてしまう。
- 負荷テストなどを選択して実行するときは、簡単な引数だと嬉しい。
解決方法
pytest.markを使って、普段実行しないテストをマークする(印を付ける)。pytest.iniで、マークしたテストを実行しないように設定する。
some_test.py:
import pytest
def test_something():
...
def test_another():
...
@pytest.mark.performance
def test_performance():
...
pytest.ini:
[pytest]
...
addopts = -m "not performance"
これで実行すると、デフォルトではperformanceのマークを付けたテストを実行しない。
> pipenv run pytest -v
========================================= test session starts =========================================
(中略)
collected 3 items / 1 deselected / 2 selected
test/some_test.py::test_something PASSED
test/some_test.py::test_another PASSED
マークしたテスト(だけ)を実行するには、コマンドラインで -m 引数を付ければよい。
> pipenv run pytest -v -m performance
========================================= test session starts =========================================
(中略)
collected 3 items / 2 deselected / 1 selected
test/some_test.py::test_perfomance PASSED
補足
コマンドラインから個別のテストファイルやメソッドを直接指定するとき(node ID指定)も、-mオプションを付けないと無視されてしまうので注意。
@pytest.markでは任意の名前を指定できるので、ここをtypoすると絶対実行されないテストになってしまったりする。防止策として、pytest.iniのmarkersを書き、addoptsで--strictを指定しておくとよい。
pytest.ini:
[pytest]
...
addopts = -m "not performance" --strict
markers =
performance: performance tests
間違ったマークを付けると、実行時にエラーになる。
> pipenv run pytest -v
========================================= test session starts =========================================
(中略)
collected 0 items / 1 error
=============================================== ERRORS ================================================
_________________________________ ERROR collecting test/some_test.py __________________________________
'peformance' not found in `markers` configuration option
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
========================================== 1 error in 0.12s ===========================================
マークをいろいろ使い分けるなら、コマンドライン(シェル)でエイリアスを設定しておくと便利かも。補完も効くし。
% alias
ppytest='pipenv run pytest'
ppytestperf='pipenv run pytest -m performance'
ppyteste2e='pipenv run pytest -m e2e'
参考
Marking test functions with attributes - pytest documentation