Fragments of verbose memory

冗長な記憶の断片 - Web技術のメモをほぼ毎日更新(準備中)

Jan 2, 2025 - 日記

pytest テスト実行中の状態を知るデバッグオプション --pdb

pytest は Python 開発者にとって無くてはならないテストフレームワークです。その中でも、失敗したテストケースで即座にデバッガーを起動できる --pdb オプションは、テスト駆動開発 (TDD) やバグ修正において非常に便利な機能です。

この記事では、 --pdb の使い方、注意点、副作用、そしてその回避方法について詳しく解説します。

基本的な使い方

pytest --pdb を使うと、エラー発生時に自動的に pdb (Python デバッカ) が起動し、その場でスタックトレースや変数の中身を確認できます。

実行例

以下のようなコードがあるとします:

def test_example():
    x = 10
    y = 0
    assert x / y == 0  # ZeroDivisionError が発生

このテストを実行する際に --pdb オプションを付けると:

pytest --pdb

エラーが発生した時点で pdb が起動します:

>>>>>>>>>>>>>>>> traceback >>>>>>>>>>>>>>>>
test_example.py:4: in test_example
    assert x / y == 0
E   ZeroDivisionError: division by zero
(Pdb)

pdb では以下の操作が可能です:

  • スタックトレースを確認:
(Pdb) where
  • 変数の中身をチェック:
(Pdb) print(x)
10

注意点と副作用

--pdb は便利ですが、使用する際にいくつか注意すべき点があります。

1. 大量のテスト失敗への対応

失敗するテストが多い場合、それぞれの失敗でデバッガが起動するため作業が煩雑になります。

特定のテストに限定して実行することで解決できます:

pytest --pdb -k "test_target_case"
2. キーボード割り込み (Ctrl+C) の副作用

長時間停止するテストや無限ループ中のコードをデバッグする際、Ctrl+C による割り込みでデバッガを起動できます。ただし、外部リソース (例: スレッドやサブプロセス) を利用している場合、割り込みがリソース解放に影響を与える可能性があります。

対策:
  • リソース解放を確実にするため、finallypytest.fixtureyield 構文を利用しましょう。
3. CI/CD 環境での使用

自動化されたテスト環境では、 --pdb を有効にするとインタラクティブモードでテストが停止してしまいます。手動実行時のみ有効にする工夫が必要です。

環境変数を使った切り替え例:
pytest ${DEBUG:+--pdb}
4. 他の pytest プラグインとの干渉

pytest-xdist (並列実行) や pytest-cov (カバレッジ測定) と組み合わせると、以下の問題が発生する場合があります:

  • 並列実行中のプロセスが見えない
  • カバレッジ測定が中断される
対策:

デバッグ中は並列実行を無効化するか、プラグインを一時的に無効にします:

pytest -n 0 --pdb

デバッグ中の心得

デバッグは慎重に行いましょう。特に以下の点に気を付けるべきです:

  • 状態を意図せず変更しない: デバッガ内で変数を書き換えたり、関数を実行したりするとテスト環境が汚染される可能性があります。
  • デバッガの終了方法: 終了時は q コマンドを使い、適切に抜けるようにします:
(Pdb) q

まとめ

pytest --pdb は、Python 開発におけるデバッグを効率化する強力なツールです。ただし、利用時には以下の点を意識しましょう:

  • 大量のテスト失敗時にはテストケースを絚り込む
  • リソース解放の仕組みを整備する
  • CI/CD 環境では無効化する
  • 他のプラグインとの組み合わせを慎重に検討する

これらの注意点を抱えることで、 --pdb をさらに有効活用できるようになるはずです。