Open6

【メモ】テスト駆動Python 第2版

ImakiImaki

1章:はじめてのpytest

理解

  • 単語
    • トレースバック:pytestの実行ログのうち、テストが失敗した正確な場所とその周囲のコードを 表示するセクション。
    • テストディスカバリ:pytestを実行する際に、実行するテストを検索する部分
  • CLIオプション
    • -v, --verboseでログの詳細表示
    • --tb=noでトレースバックの表示をオフ
  • テスト結果見方
    • PASSED
    • FAILED(テストのエラー)
    • SKIPPED
    • XFAIL(失敗するはずのテストが想定通りに失敗した)
    • XPASS(xfail マーカーが付いたテストの実行が想定に反して成功)
    • ERROR(フィクスチャなどテストの結果以外でのエラー)

疑問・確認

  • XFAILの使い方としては、システム上で設定したエラーをちゃんと吐き出せているかのテストをする時とか?
ImakiImaki

2章:テスト関数を書く

理解

  • pytestでは任意の式をassert <式>で表現できてシンプル。(assertでなくても例外が出されればエラーを出す仕様にはなっている
    • unittestだとassertTrueassertEqualなどが必要
  • まれにassertが適していない場合があり、その時はpytest.fail()を使う
  • 例外が出されればテストは失敗してしまう。例外が出ることを想定するテストの場合はpytest.raises()を使う
  • Arrange-Act-Assert(準備 - 実行 - 検証)を意識する
    • 初期状態/データ整備 - 正しいふるまいか確認したい動作の実行 - 結果
  • 一つのクラスに複数のテストをまとめることができる。もちろん継承もできるが、テストにおいてはクラスは特定のものをまとめるためだけに使うのがよい。
  • デバッグの際は特定のテストだけ実行して挙動を確認できるのが便利。

疑問・確認

  • pytest.fail()を使うケースの感覚がふわふわなので、どのようなものがあるか調べておきたい。
ImakiImaki

3章:pytestのフィクスチャ

理解

  • テストのセットアップやティアダウンにはフィクスチャを使う
    • fixture関数のyieldより前がセットアップ、yieldより後がティアダウン
    • --setup-showでフィクスチャのセットアップやティアダウンも含めてログを出せる
  • フィクスチャのスコープ@pytest.fixture(scope="<scope>")
    • "function"(default):関数ごとに1回実行
    • "class":クラスごとに1回実行
    • "module":モジュールごと
    • "package":パッケージごと
    • "session":pytestコマンド1回で1回実行
  • conftest.pyに記述されたフィクスチャは、明示的にimportしなくても使える
    • テストディレクトリであればどの階層に配置しても問題ない
    • どの階層のフィクスチャが使われているかを確認するには--fixturesを使う
  • 複数の階層のフィクスチャを組み合わせテストを効率的にする
  • フィクスチャのスコープをは動的に決定できる
    • フィクスチャのスコープはフィクスチャの定義時に決める必要がある。
    • 呼び出し時にスコープをどこに設定するかをparserを使って動的に決めるテクニックみたいなものはある
  • 全てのテストに共通したフィクスチャを使う場合
    • フィクスチャを引数に渡さなくてもautouse=Trueを設定しておけば良い
    • それほど使用頻度は高くなく、特に理由がなければフィクスチャは明示する

疑問・確認

  • フィクスチャのスコープを動的にするのはよく使われているパターンか?結構複雑になりそうだが。
ImakiImaki

4章:組み込みフィクスチャ

理解

  • 一時ディレクトリ
    • tmp_path:関数スコープ
    • tmp_path_factory:セッションスコープ
  • CLI呼び出し、テスト
    • capsysを作う
    • with capsys.disableの中でテストを書くことででテストの出力を表示できる
  • monkeypatch
    • アプリケーションコードの実行環境をいじれる、一部のテストだけDBを一時ディレクトリにリダイレクトするなど可能
    • 公式の環境変数やConfigの例がわかりやすい

疑問・確認

  • monkeypatchの公式のAPIの例だとAPIの投げる先をモックしているが、DjangoとかFastAPIとかはその辺便利なものが充実してるし、そっち使えば良さそう
ImakiImaki

5章:パラメータ化

理解

  • 同じようなコードのテストを繰り返す場合パラメータ化する
    • それぞれのテストでフルで書くと冗長
    • 一つにまとめるとテストが何で失敗したかわかりづらい
  • パラメータ化の方法
    • 関数のパラメータ化
      • @pytest.mark.parametrize()マーカーを使う
    • フィクスチャのパラメータ化
      • @pytest.fixture(params=[...])
      • パラメータのあたいごとにセットアップ、ティアダウンを実行する必要がある際に利用する
    • pytest_generate_testsを使ってパラメータ化
      • 公式の例
      • pytestのコマンドラインのオプションを作成してパラメータリストから選択できる
  • より複雑なパラメータ化は16章

疑問・確認

  • pytest_generate_testsの使い方はわかったが、使い所のイメージがまだそんなに湧いていない
ImakiImaki

6章:マーカー

理解

  • @pytest.mark.skip,@pytest.mark.skipif,@pytest.mark.xfailを使って、まだ実装していなかったりバグがあるところのテストをスキップ/通すことができる
    • ただし、reason引数に必ず理由を書く!
    • TDDで進める場合など初めにxfailをつけておき、実装したものから外していくような使い方が便利
    • バグを見つけたが、修正に時間がかかり一旦テストを通しておかなければならない場合に便利
    • xfailのstrict=True/Falseは設定ファイルで設定できる
  • オリジナルのマーカーは設定ファイルに記述する
  • デフォルトの設定だと定義していないmarkerを指定しても実行自体ははしる(警告は出る)。設定ファイルに--strict-markersを設定しておくことで、定義していないmarker名が指定されるとエラーになる
    • --strict-markersは設定しておくのがベター
    • オプション-raでテストがうまくいかない理由を出力できるので、これも設定しておくのがベター
  • FakerというPythonパッケージを利用することでダミーデータを生成するpytestフィクスチャを使えるようになる

疑問・確認

  • Fakerの使い方は要確認