本記事では、Pythonの標準的なテストライブラリである pytest のプラグイン、pytest-xdist を紹介します。
テストケースが増えるにつれて長くなりがちな実行時間を、並列実行 によって大幅に短縮する方法を解説します。導入は非常に簡単ですが、いくつか注意すべきポイントも存在するため、その対策も合わせて記載します。
対象
- Pythonで
pytestを利用している方 - テストの実行待ち時間が長いと感じる方
- CI(継続的インテグレーション)の実行時間を短縮したいエンジニア
目次
- pytest-xdistとは
- インストール方法
- 基本的な使い方
- 注意点:並列実行の落とし穴
- おすすめのオプション設定
- まとめ
- 参考
1. pytest-xdistとは
pytest-xdist は、pytestのテストランナーを拡張し、複数のCPUコアを使ってテストを並列(Parallel) に実行できるようにするプラグインです。
通常、pytestは1つのプロセスで順次テストを実行しますが、xdistを使用することで、複数のワーカープロセスにテストを分散させることができます。これにより、CPUのコア数に応じて、理論上は数倍の速度向上が見込めます。
補足: ワーカープロセスとは、実際にテスト処理を行う独立した実行単位のことです。
2. インストール方法
pip install pytest-xdist
PoetryやPipenvなどのパッケージマネージャを使用している場合は、開発用依存関係(dev dependencies)として追加することをおすすめします。
3. 基本的な使い方
もっとも基本的な使い方は、実行時のオプションに -n を追加するだけです。
コア数を自動指定する場合
PCのCPUコア数を自動検出し、最大限のリソースを使ってテストを実行します。
pytest -n auto
コア数を手動指定する場合
他の作業への影響を抑えたい場合など、使用するプロセス数を明示的に指定することも可能です。以下の例では2つのプロセスで並列実行します。
pytest -n 2
これだけで、テストスイート全体が複数のワーカーに分割され、同時に実行されます。
4. 設定ファイルでデフォルト化する
毎回 -n auto を入力するのが手間な場合、設定ファイルに記述しておくことで、単に pytest と打つだけで並列実行されるようになります。
プロジェクトで利用している設定ファイルに合わせて、以下のように追記してください。
pytest.ini を使用する場合
addopts にオプションを記述します。これはコマンドライン引数のデフォルト値を設定する項目です。
[pytest]
addopts = -n auto
pyproject.toml を使用する場合
[tool.pytest.ini_options] セクション内に同様の設定を行います。
[tool.pytest.ini_options]
addopts = "-n auto"
5. 注意点:並列実行の落とし穴
非常に便利なプラグインですが、導入するだけで全てが解決するとは限りません。並列実行特有の問題に注意する必要があります。
データベースの競合
複数のワーカーが同じデータベースに対して同時に読み書きを行うと、データの整合性が取れなくなり、テストが落ちることがあります。
これを防ぐためには、ワーカーごとに異なるデータベースを作成するか、トランザクションを適切にロールバックして影響を及ぼさない設計が必要です。
fixtureのスコープと実行回数
scope="session" と設定されたfixtureは、通常であれば全テストで1回だけ実行されます。
しかし、xdistを使用すると各ワーカープロセスごとに1回ずつ実行される挙動になります。重い初期化処理(Dockerコンテナの起動など)がある場合は、別途排他制御(ロック機構)などの工夫が必要になるかもしれません。
6. おすすめのオプション設定
副作用を抑えつつ高速化の恩恵を受けるために、以下のオプションを知っておくと便利です。
--dist=loadscope
同じテストクラスやモジュール内のテストを、同一のワーカーで実行するようにグルーピングします。
クラス単位でセットアップを行っている場合や、テスト間の依存関係が疑わしい場合に、このオプションをつけると安定することがあります。
pytest -n auto --dist=loadscope
--dist=loadfile
loadscope と似ていますが、こちらはファイル単位でグルーピングを行います。ファイルごとに独立性が保たれている場合は、こちらが有効な場合があります。
まとめ
pytest-xdist を導入することで、以下のメリットを得られます。
- 実行時間の短縮: CPUリソースを有効活用し、待ち時間を削減できます。
-
簡単な導入:
-n autoをつけるだけで、すぐに効果を体感できます。 - 柔軟な設定: プロジェクトの構成に合わせて、実行単位(スコープ)を調整可能です。
導入していない方は、ぜひ一度試してみてください。
参考