なぜpytestを使うのか?
Pythonが提供するユニットテストフレームワークとして, unittestがありますが,unittestと比べpytestは以下のようなメリットがあります.
- command-line tool
- Classは必要に応じて作成すれば良く,小規模なテストについてはテスト関数の定義のみで十分
assert 文がシンプル
- traceback機能が充実しており,また不必要ならばoffすることができる
assert文
pytestを用いたunit testの基本構文を理解するために以下のコードを見てみます.
def test_passing():
assert (1, 2, 3) == (1, 2, 3)
assert文はテストの成否を判断するPythonの組み込みコマンドです.assert以下がFalseと評価されると,AssertionErrorを発生させます.
test_passingという関数の名前はtest_から始まってますが,pytestはtest_で始まる関数をテスト関数として検出しテストを実行します.
Example 1 : test_script_001.py
def test_passing():
assert (1, 2, 3) == (1, 2, 3)
def test_passing2():
assert (2, 3, 4) == (2, 3, 4)
def nottest_passing():
assert (1, 2, 3) == (1, 2, 3)
というpytest用のファイルを用意します.これを実行すると
pytest -v ./pytest_scripts/test_script_001.py
============================= test session starts ==============================
platform linux -- Python 3.14.0, pytest-8.4.2, pluggy-1.6.0 -- /opt/hostedtoolcache/Python/3.14.0/x64/bin/python
cachedir: .pytest_cache
rootdir: /home/runner/work/python-statisticalpackage-techniques/python-statisticalpackage-techniques
configfile: pyproject.toml
plugins: anyio-4.11.0, timeout-2.4.0
collecting ... collected 2 items
pytest_scripts/test_script_001.py::test_passing PASSED [ 50%]
pytest_scripts/test_script_001.py::test_passing2 PASSED [100%]
============================== 2 passed in 0.02s ===============================
上記の例では,
collecting ... collected 2 itemsよりテスト関数が2つ検出された
test_passing, test_passing2 が問題なくテストパスした
という情報が表示されています.
▶ テストが失敗する場合
def test_failing():
assert (1, 2) == (1, 1)
という関数を準備し,あえて失敗させてみます.
pytest -v ./pytest_scripts/test_script_002.py
============================= test session starts ==============================
platform linux -- Python 3.14.0, pytest-8.4.2, pluggy-1.6.0 -- /opt/hostedtoolcache/Python/3.14.0/x64/bin/python
cachedir: .pytest_cache
rootdir: /home/runner/work/python-statisticalpackage-techniques/python-statisticalpackage-techniques
configfile: pyproject.toml
plugins: anyio-4.11.0, timeout-2.4.0
collecting ... collected 1 item
pytest_scripts/test_script_002.py::test_failing FAILED [100%]
=================================== FAILURES ===================================
_________________________________ test_failing _________________________________
def test_failing():
> assert (1, 2) == (1, 1)
E assert (1, 2) == (1, 1)
E
E At index 1 diff: 2 != 1
E
E Full diff:
E (
E 1,
E - 1,
E ? ^
E + 2,
E ? ^
E )
pytest_scripts/test_script_002.py:2: AssertionError
=========================== short test summary info ============================
FAILED pytest_scripts/test_script_002.py::test_failing - assert (1, 2) == (1, 1)
At index 1 diff: 2 != 1
Full diff:
(
1,
- 1,
? ^
+ 2,
? ^
)
============================== 1 failed in 0.03s ===============================
At index 1 diff: 2 != 1 とあるように index 1が一致していないと教えてくれます.pytestが表示するテストが失敗した場所とその周囲のコードのセクションのことをトレースバック(traceback)と呼びます.これの表示をoffにしたい場合は
pytest --tb=no ./pytest_scripts/
============================= test session starts ==============================
platform linux -- Python 3.14.0, pytest-8.4.2, pluggy-1.6.0
rootdir: /home/runner/work/python-statisticalpackage-techniques/python-statisticalpackage-techniques
configfile: pyproject.toml
plugins: anyio-4.11.0, timeout-2.4.0
collected 3 items
pytest_scripts/test_script_001.py .. [ 66%]
pytest_scripts/test_script_002.py F [100%]
=========================== short test summary info ============================
FAILED pytest_scripts/test_script_002.py::test_failing - assert (1, 2) == (1, 1)
At index 1 diff: 2 != 1
Full diff:
(
1,
- 1,
? ^
+ 2,
? ^
)
========================= 1 failed, 2 passed in 0.02s ==========================
Pytest assert
pytestが利用するassertはPythonの組み込みstatementと同じですが,unittestなどの他のフレームワークのassertヘルパー関数と比べシンプルに利用することができます. 例として,
assert something |
assertTrue(something) |
assert a == b |
assertEqual(a, b) |
assert a != b |
assertNotEqual(a, b) |
assert a <= b |
assertLessEual(a, b) |
assert a is None |
assertIsNone(a) |
assert a is not None |
assertIsNotNone(a) |
テスト結果
pytest_scripts/test_script_001.py .. [ 66%]
pytest_scripts/test_script_002.py F [100%]
に着目すると .., F といった文字列が確認できます.これはpytestのテスト結果を表しています.
| PASSED |
. |
正常に実行された個数を.の個数で示す |
| FAILED |
F |
正常に実行されなかった個数をFの個数で示す |
| SKIPPED |
s |
スキップされたテストを示す |
| XFAIL |
x |
想定通り失敗したテストを示す.@pytest.mark.xfail()でpytestに教える |
| XPASS |
X |
xfailマーカーを設定したのに成功したテストを示す |
| ERROR |
E |
例外が想定通り発生したことを示す |