Python

Jupyter notebookでPythonのテストコードを書く

インストールから実行まで

使用するライブラリ:ipytest (PyPIページ)

インストールコマンド

pip install ipytest

インポート

import ipytest
ipytest.autoconfig()

実行例

%%ipytest -qq

def test_example():
    assert [1, 2, 3] == [1, 2, 3]

%%ipytest -qqは、過去に定義されたテスト(他のセルや同一セルの過去の実行で登録されたテスト)を削除してからテストを実行するコマンドです。
ipytest.clean() 関数を使用することでも、以前に定義されたテストを削除できます。

テストコードの最低限の書き方

  • 関数名に「test_」をつける(test_で始まる関数名をテストとして自動検出します)
  • assert に続けて「TRUE/FALSEの真偽値を返す表現・比較式」を書く

assertはPython組み込みの構文で、条件式がFalseの場合にAssertionErrorを発生させます。

グローバルの状態について

以前に定義されたテストを削除する意味

Pytestの仕様として、一度定義したテストは記憶され続けます。
そのため古いテストが意図せず残ったままになり、同名テストが重複したり、削除したはずのテストが再び実行されるなど、予期せぬ動作が発生する可能性があります。
このような問題を防ぐために、%%ipytestipytest.clean()で「実行前に過去のテストを削除する」という手順が推奨されています。

モジュールの再ロード

Python のモジュール システムはインポートをキャッシュするため、グローバル状態として機能します。
モジュールの最新バージョンをテストするには、都度モジュールを再ロードする必要があります。
そのため ipytest は ipytest.force_reload() 関数を提供します。または IPython の自動再ロード拡張機能も役立つかもしれません。
ローカル パッケージをテストするには、開発パッケージとしてインストールすることをお勧めします (例: pip install -e ..)。

別のスレッドでのテストの実行

非同期コードの場合、IPython は現在のスレッドでイベント ループを作成します。
この設定は、非同期テストに干渉する可能性があります。
そのため ipytest は別のスレッドでのテストの実行をサポートしています。
ipytest.autoconfig(run_in_thread=True) と設定するだけです。

テストコードの書き方

定義した関数をテストする例

テストをパスした場合の表示:左下に緑色のドットと、右下に緑色で100%と出る

テストをパスできなかった場合

フィクスチャ(fixture)の使用例

フィクスチャとは「テスト実行前後の準備・後処理を行う仕組み」です。

@pytest.fixtureデコレータはpytestの機能なのでimport pytestが必要

パラメトリックテスト

同じテストロジックで異なる入力を検証したい場合に使います。

※こちらもimport pytestが必要

エラー・例外のテスト

例外が発生することを確認するにはpytest.raisesを使用します。

テストのスキップ・条件付きスキップ

スキップした分は黄色い小文字でsと表示される

よく使うオプション

  • -v: 詳細表示
  • -q: 簡潔表示
  • --maxfail=1: 最初の失敗でテスト停止
  • -k <文字列>: 特定の文字列を含むテストのみ実行
    例: pytest -k add は"add"が名前に含まれるテストだけ実行

-vの使用例

-Python