※記事内に商品プロモーションを含むことがあります。
はじめに
pytestによる基本的なテストの実行方法と、複数のテストケースを記述する方法を解説します。
環境は以下の通りです。
- OS: Windows 10 Home
- Python 3.9.18
- pytest 7.4.0
pytestの基本的な使い方
まず、以下のPythonスクリプトfoo.py
を作成します。
1
2
3
4
5
|
def add(x, y):
return x+y
def test_add():
assert add(1, 2) == 3
|
add()
がテスト対象となる関数です。
また、test_add()
はpytestでテストするための関数です。pytestでは、test
から始まる関数を対象にテストを実行します。assert
文の後ろに、True
になると期待される(=テスト結果として正しい)判定式を記述します。
次に、Powershellなどのコマンドラインで以下を実行します。pytest
の引数としてスクリプト名を与えます。
1
2
3
4
5
6
7
8
9
10
|
> pytest foo.py
======================= test session starts =======================
platform win32 -- Python 3.9.18, pytest-7.4.0, pluggy-1.0.0
rootdir: D:\document\Python Scripts\pytest
plugins: anyio-3.5.0
collected 1 item
foo.py . [100%]
======================== 1 passed in 0.04s ========================
|
X passed
とのみ表示されている場合、テストに成功しています。
テストに失敗した場合の挙動
次に、add()
関数にバグがあった場合の挙動を確認します。バグがあるスクリプトfoo2.py
を作成し、同じようにpytestを実行します。
1
2
3
4
5
|
def add(x, y):
return x+y+1
def test_add():
assert add(1, 2) == 3
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
> pytest foo2.py
======================= test session starts =======================
platform win32 -- Python 3.9.18, pytest-7.4.0, pluggy-1.0.0
rootdir: D:\document\Python Scripts\pytest
plugins: anyio-3.5.0
collected 1 item
foo2.py F [100%]
============================ FAILURES =============================
____________________________ test_add _____________________________
def test_add():
> assert add(1, 2) == 3
E assert 4 == 3
E + where 4 = add(1, 2)
foo2.py:5: AssertionError
===================== short test summary info =====================
FAILED foo2.py::test_add - assert 4 == 3
======================== 1 failed in 0.23s ========================
|
テスト結果に間違いがある場合、このようにFAILURES
と出力されます。
ファイルを分割する
プログラムの量が増えてくると、テスト対象となるファイルと、pytestでテストを実行するためのファイルを分割したくなります。
前者をfoo3.py
, 後者をtest_foo3.py
として、以下のように作成して同じフォルダに置きます(別のフォルダに置く方法もあります)。
1
2
|
def add(x, y):
return x+y
|
1
2
3
4
|
from foo3 import add
def test_add():
assert add(1, 2) == 3
|
なお、テストを実行するためのプログラムのファイル名はtest_*.py
または*_test.py
とします。
foo3.py
とtest_foo3.py
があるディレクトリで、引数を付けずにpytest
コマンドを実行するとテストが実行されます。
1
2
3
4
5
6
7
8
9
10
|
> pytest
======================= test session starts =======================
platform win32 -- Python 3.9.18, pytest-7.4.0, pluggy-1.0.0
rootdir: D:\document\Python Scripts\pytest
plugins: anyio-3.5.0
collected 1 item
test_foo3.py . [100%]
======================== 1 passed in 0.05s ========================
|
複数ケースでテストする
ある関数に対して、通常は複数の入力値を与えてテストをすると思います。pytest上の書き方はいくつかあります。
- テスト用関数を複数定義する
- 1つのテスト用関数の中で複数回テストする
pytest.mark.parametrize
を使う
テスト用関数を複数定義
以下のようにテスト用関数を複数定義します。関数名の末尾に連番を振っていますが、pytestの仕様では必須ではありません。もし途中のテストに失敗した場合でも、最後の関数までテストは実行されます。なお、以下の例では、テストケース数は3としてカウントされます。
1
2
3
4
5
6
7
8
9
10
11
|
def add(x, y):
return x+y
def test_add_01():
assert add(1, 2) == 3
def test_add_02():
assert add(2, 3) == 3
def test_add_03():
assert add(3, 4) == 7
|
1
2
3
4
5
6
7
8
9
10
|
> pytest foo4.py
======================= test session starts ========================
platform win32 -- Python 3.9.18, pytest-7.4.0, pluggy-1.0.0
rootdir: D:\document\Python Scripts\pytest
plugins: anyio-3.5.0
collected 3 items
foo4.py ... [100%]
======================== 3 passed in 0.04s =========================
|
1つのテスト用関数の中で複数回テスト
以下のように1つのテスト用関数test_add()
の中に複数のassert
文を書いた場合でも、複数回のテストは可能です。しかし、途中のassert
文のテスト結果が正しくなかった場合、同じ関数にあるそれ以降のassert
文は評価されません。例えば、add(1, 2) == 3
の評価結果が正しくなかった場合、add(2, 3) == 4
とadd(3, 4) == 7
は評価されません。なお、以下の例では、テストケース数は1としてカウントされます。
1
2
3
4
5
6
7
|
def add(x, y):
return x+y
def test_add():
assert add(1, 2) == 3
assert add(2, 3) == 4
assert add(3, 4) == 7
|
1
2
3
4
5
6
7
8
9
10
|
> pytest foo5.py
======================= test session starts ========================
platform win32 -- Python 3.9.18, pytest-7.4.0, pluggy-1.0.0
rootdir: D:\document\Python Scripts\pytest
plugins: anyio-3.5.0
collected 1 item
foo5.py . [100%]
======================== 1 passed in 0.05s =========================
|
pytest.mark.parametrizeを使う
pytestをインポートし、テスト用関数の前にデコレータ@pytest.mark.parametrize
を追加します。デコレータは、関数を装飾するPythonの機能です。デコレータの第1引数として、"a, b, c"
のように関数の引数を文字列で与えます。第2引数には、テストケースごとの引数のタプルをリストで与えます。このデコレータを使用すると、途中で失敗しても最後のテストケースまで実行します。なお、以下の例では、テストケース数は3としてカウントされます。
1
2
3
4
5
6
7
8
9
10
11
12
|
import pytest
def add(x, y):
return x+y
@pytest.mark.parametrize("a, b, c", [
(1, 2, 3),
(2, 3, 5),
(3, 4, 7)
])
def test_add(a, b, c):
assert add(a, b) == c
|
1
2
3
4
5
6
7
8
9
10
|
> pytest foo6.py
======================= test session starts ========================
platform win32 -- Python 3.9.18, pytest-7.4.0, pluggy-1.0.0
rootdir: D:\document\Python Scripts\pytest
plugins: anyio-3.5.0
collected 3 items
foo6.py ... [100%]
======================== 3 passed in 0.05s =========================
|
参考