pytest の使い方
(同僚への紹介用に書いてみた。)
目標
以下のようにしてテストができるようにします。
cd test; pytest test*.py
手順
pytest のインストール
python3 -m pip install pytest
リポジトリにtestのディレクトリを追加します。
テストをモジュールの説明になるように開発する
よりよいテストは、モジュールの動作の説明としてわかりやすいように実装する。
何かの理由により実装が壊れたときには、見つけられように書く。
動作テストと性能の評価は別物にする
pytestでの動作テストは、典型例での動作の検証にして、実施例の数を減らす。
機械学習などの推論の性能に関する指標の評価はpytestには含めないようにする。
テストされるモジュールがモジュールとして呼び出し可能なことの確認
テストされるモジュールがモジュールとしてインストールされている状況をになっていることを確認します。
モジュールのフォルダには__init__.py
ファイルがあること。
pyproject.toml(もしくはsetup.cfg)を書いてあって、
python3 -m pip install .
で、そのモジュールがインストールに成功していることを確認します。
まず、スクリプトとして動くものを作る。
pytest の始め方
pytestがすること
pytest test_*.py
と実行することで、 test_*.py
のパターンにマッチするファイル中のテストを全て実行します。
testされる関数あるいメソッドは
def test_foo()
などのようにtest_
で始まっていることを前提としています。
test_*.py
ファイルにはif __name__ == "__main__":
の中で、test_foo()などの関数呼び出しは不要です。
pytestはテストに失敗する項目があっても、残りのテストを継続します。
通常のプログラムの場合には、assert で失敗したときは、それ以降の作業がされないので、
網羅的なテストをすることはできません。
pytest の基本パターンの1つは、入力値に対する結果の期待値とを比較するものです。
パラメータ化したテスト
import pytest
@pytest.mark.parametrize(
)
pytest.mark.parametrize
というキーワードでwebで検索をかければ、それっぽい例題が見つかるはずです。
pytestをいきなり書きにくい場合:
test ディレクトリでふつうに動くスクリプトを作ります。
python3 ファイル.py
モジュールが利用するデータファイルがあるときには、そのパスが正しくアクセスできるように
モジュールのファイルを書き換えます。
そのスクリプトから、
モジュールの関数もしくはモジュールのクラスのメソッドに対応する部分を関数(あるいはメソッド)として切り出します。
python3 ファイル.py
としてまだ動作するはずです。
関数としての抜き出しが全て終わったあとは
def test_foo():
assert 1 + 1 == 2
def test_bar():
assert 1 + 2 == 3
# もはやあとには、if __name__ == "__main__": のようなブロックはない。
のような状況になっていて
pytest test_foo.py
依存ライブラリのライセンスの有無によってテストの実行のありなしを制御したい。
pytest.mark.skip
pytest.mark.skipif
を調べてみてください。
class のメソッドに対応するテストを書く
https://docs.pytest.org/en/stable/index.html
やweb上のpytestの記事を読んでください。
テスト用の入力データファイル
- データファイルの数は少なくしましょう。
- pytestが目指すのは、プログラムのロジックのテストです。機械学習の推論の精度の評価は含めません。
- git でそのまま管理するのは避けましょう。
- 大量のファイルである場合には、ローカルなコピーがなければ、ストレージからコピーするように書きましょう。
- Google drive の個人のストレージにデータを置くのはやめましょう。
- あなたがいなくなった時に、そのデータは消えてしまいます。
- 画像ファイルの場合,
git lfs track "*.jpg" "*.png"
などとしてLFS(large file system)を使っておくこともあります。