はじめに
pytestに触れてみたので本記事は備忘録を兼ねてその学習内容をまとめたものになります。
対象の方
とりあえずコピペで動かしながらざっくりpytestの書き方を把握されたい方
インストール
pytestをインストールします。
pip install pytest
環境
- python:3.12.2
- pytest:8.2.2
とりあえず動かしてみる
足し算を行うシンプルな関数を準備します。
def add(a, b):
return a + b
足し算を行う上記の関数をテストするためのテストコードを作成します。
from sample import add
def test_add():
assert add(1, 2) == 3
assert add(-1, 1) == 0
assert add(0, 0) == 0
テストコードのファイル名、メソッド名は test~
で記載する。
https://docs.pytest.org/en/8.2.x/explanation/goodpractices.html#test-discovery
下記のコマンドでテスト実行します。
pytest test_sample.py
テストを実行した結果は次の通りです。テストが1つ通っている事が確認できました。
test_sample.py . [100%]
======================================================= 1 passed in 0.01s =======================================================
テストコード内でprint()出力の内容を見たい時には、以下のように「--capture=no」オプションを設定するとログの内容を確認可能。
pytest test_sample.py --capture=no
よく使いそうなもの
1. assert文
以下に使用例を記載。assert
の後にテストしたい条件を記述する。
def test_example():
assert 1 == 1 # 成功するテスト
assert 1 == 2 # 失敗するテスト
動かしてみると次のように 1==2
で失敗していることを確認。
def test_example():
assert 1 == 1 # 成功するテスト
> assert 1 == 2 # 失敗するテスト
E assert 1 == 2
test_sample.py:3: AssertionError
2. pytest.mark
◆ pytest.mark.parametrize
同じテストを異なるデータセットで複数回実行したい場合は @pytest.mark.parametrize
を使用するとまとめてテストができて便利です。
def add(a, b):
print('テスト開始')
return a + b
import pytest
from sample import add
@pytest.mark.parametrize("a,b,expected", [
(1, 2, 3),
(-1, 1, 0),
(0, 0, 0),
])
def test_add(a, b, expected):
assert add(a, b) == expected
動かしてみるとデータセットの回数実行されていることを確認。(今回は3回)
test_sample.py テスト開始
.テスト開始
.テスト開始
.
======================================================= 3 passed in 0.01s =======================================================
◆ pytest.mark.skip
一部の処理をスキップしたい場合に使用します。
import pytest
@pytest.mark.skip(reason="このテストはまだ実装されていません")
def test_not_implemented_yet():
print('エラー')
assert False
def test_ready_to_run():
print('実行')
assert True
実行するとテストが1件passしており、もう1件はスキップされている事を確認。
test_sample.py s実行
.
================================================= 1 passed, 1 skipped in 0.01s ==================================================
実行結果の略称について
- s:テストがスキップされたことを示す
- .:テストがパスしたことを示す
3. pytest.raises
意図的に例外を発生させてみます。エラーが発生すればテストはpass、エラーが発生しなければfailedになります。
import pytest
def test_raises_exception():
with pytest.raises(ValueError):
int("a") # エラーを発生させる
動かしてみるとテストがpassしており、想定通りエラーを起こせていたことを確認。
test_sample.py .
======================================================= 1 passed in 0.01s =======================================================
4. Fixtures
fixtureを利用する事でテストの前後に処理を設けることができます。
import pytest
@pytest.fixture
def temp_file(tmpdir):
# テストの前処理:ファイルを一時的に作成
print('テスト開始')
temp_file = tmpdir.join("temp_file.txt")
temp_file.write("Hello, World!")
# テスト実行:テストには作成したファイルを渡す
yield temp_file
# テストの後処理:ファイルを削除
temp_file.remove()
print('テスト終了')
def test_temp_file(temp_file):
# テスト: ファイルに書き込まれた文字の一致、ファイルの存在
assert temp_file.read() == "Hello, World!"
assert temp_file.check()
動かしてみるとテストがpassしている事を確認。
test_sample.py テスト開始
.テスト終了
======================================================= 1 passed in 0.02s =======================================================
参考