はじめてのpytest

Author

Ryo Nakagami

Published

2024-11-11

Modified

2025-11-21

なぜ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_から始まってますが,pytesttest_で始まる関数をテスト関数として検出しテストを実行します.

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ヘルパー関数と比べシンプルに利用することができます. 例として,

pytest unittest
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 例外が想定通り発生したことを示す