🙌
初めて pytest でテストを書いてみた
イントロダクション
pytest とは
pytest は、Python のテストフレームワークであり、Python プロジェクトのテストを効率的に行うための強力なツールです。
-
簡単なテスト記述
pytest は、テストケースを記述するために簡潔で自然な構文を提供します。テスト関数は通常、test_
で始まる関数名を持ち、アサーションを使用してテスト条件を表現します。 -
自動テスト検出
pytest は、テスト関数を自動的に検出します。テストファイルやテストスイートを手動で登録する必要はありません。テストケースがコンフォーミングな名前規則に従っていれば、自動的に実行されます。 -
アサーションの使用
テストケース内でアサーションを使用して、期待結果と実際の結果を比較します。アサーションが失敗した場合、pytest は失敗したテストケースの詳細情報を提供します。
環境のセットアップ
-
Python 環境の構築
今回は省略します。 -
pytest のインストール
pip install pytest
-
poetry の設定
通常ならpoetry add
でインストールしますが、pytest は開発環境でのみ使用するため、--dev
オプションを付けてインストールします。poetry add pytest --group dev
-
テスト対象のプロジェクトのセットアップ
pytest_demo ├── README.md ├── myapp | └── prime.py <- テスト対象の関数 ├── tests | └── test_prime.py <- テストコード ├── poetry.lock └── pyproject.toml
基本的なテストを書く
- テストケースをパスさせるための最小限のコードを書きます
素数判定の関数を書く
# myapp/prime.py
def is_prime(n: int) -> bool:
"""
与えられた数値が奇数であるかを判定する関数
Args:
n: 判定する数値
Return:
奇数であればTrue、偶数であればFalse
"""
if n <= 1:
return False
if n == 2:
return True
if n % 2 == 0:
return False
i = 3
while i * i <= n:
if n % i == 0:
return False
i += 2
return True
テストケースを書く
# tests/test_prime.py
from myapp.prime import is_prime
def test_is_prime():
assert not is_prime(1)
assert is_prime(2)
assert is_prime(3)
assert not is_prime(4)
assert is_prime(5)
assert not is_prime(6)
assert is_prime(7)
assert not is_prime(8)
assert not is_prime(9)
assert not is_prime(10)
テストの実行
- テストが通ることを確認する
pytest tests/test_prime.py
結果が返ってきます
============= test session starts =============
platform darwin -- Python 3.10.8, pytest-7.4.0, pluggy-1.2.0
rootdir: ~/pytest_demo
collected 1 item
tests/test_prime.py . [100%]
============== 1 passed in 0.00s ==============
コードを変えてみる
csv ファイルを読み込んで電話番号を抽出する関数を書く
# myapp/find_phone_numbers.py
import csv
import re
def find_phone_numbers(file_path: str) -> list:
"""
ファイルを読み込んで、電話番号を抽出する関数
Args:
file_path: ファイルパス
Return:
電話番号のリスト
"""
phone_numbers = []
with open(file_path, "r") as file:
reader = csv.reader(file)
for row in reader:
for item in row:
matches = re.findall(r"\d{2,4}-\d{2,4}-\d{4}", item)
phone_numbers.extend(matches)
return phone_numbers
csv ファイルを作成しつつ、テストケースを書く
# tests/test_find_phone_numbers.py
import csv
from myapp.fine_phone_numbers import find_phone_numbers
# find_phone_numbers() 関数のテスト関数
def test_find_phone_numbers():
data = [
["1", "Alice", "female", "080-1234-5678"],
["2", "Bob", "male", "090-2345-6789"],
["3", "Charlie", "male", "070-3456-7890"],
]
with open("./data/test_find_phone_numbers.csv", "w", newline="") as file:
writer = csv.writer(file)
writer.writerow(["ID", "name", "sex", "phone numbers"])
writer.writerows(data)
phone_numbers = find_phone_numbers("./data/test_find_phone_numbers.csv")
assert phone_numbers == ["080-1234-5678", "090-2345-6789", "070-3456-7890"]
- テストケースが引き続き通ることを確認
pytest tests/test_find_phone_numbers.py
無事、csv ファイルから電話番号を抽出できたようです。
まとめと次のステップ
今回はかなり簡単なテストを書いてみました。
実際は、例外処理のテストや mocker を使ったテストなどかなり複雑なことが出来ます。
次回は、より複雑なテストを書いてみたり、テストのレポートを見てみたりしてみたいと思います。
Discussion