見出し画像

pytest_ファイルごとに並列実行する #369

pytestはPython用に設計された単体テスト用フレームワークです。
私の所属するチームでも、Pythonで定義したAPIのテストで導入しています。

pytestを導入すると、テスト工程の効率化によって開発のリリースサイクルを早められる等のメリットがあります。一定以上のcaverageを確保できていれば、フレームワークやライブラリのバージョンアップもやりやすくなります。

ただ、私のチームではgithub actionsでpushの度にpytestを実行するようにしているのですが、以下のような課題がありました。

  • テスト本数が多くpytestの実行に多大な時間がかかるため並列実行したい

  • しかし単純に並列実行すると失敗するテストが存在する


並列実行するためのコマンド

pytestを並列実行するコマンドは以下です。

pytest ディレクトリパス -n auto

-nオプションが並列実行を意味し、ワーカー数はautoで自動設定されるようにしています。ここは2や4などの数字を直接指定することもできます。

これにより、単体テスト毎に並列実行されます。

なぜ並列実行すると失敗するのか

これはプロダクションコードの内容にもよりますが、我々の場合は以下の要因で失敗していました。

・パラメタライズしているテストがある
・tmpディレクトリを作成したり削除したりする動作がある

パラメタライズとは1つのテスト関数を使って複数のパラメータをテストできる機能ですが、これはパラメータ毎に単体テストと見做され、並列実行するとそれぞれ独立して実行されます(順番ではなく)。

我々のプロダクションコードにはエクセルダウンロード機能があり、それはユーザーごとにtmpディレクトリを作り、エクセルを一時保存する仕組みです。

そのためパラメタライズされたテストが並列実行されると、あるテストで作成したディレクトリを別のテストで削除してしまったりして、テストが失敗するようになりました。


テストファイル毎に並列実行する

そこで、並列実行の単位を変えられないかと思い、以下のオプションに行きつきました。

pytest ディレクトリパス -n auto --dist loadfile

--dist loadfileオプションをつけると【テストファイル】単位で並列実行され、1つのファイル内で定義された単体テストは、同じワーカーで直列実行されます。

つまりパラメタライズされたテストが順番に実行されるので、上記のようなエラーは防げます。

--dist loadfile:テストは、その含むファイルによってグループ化されます。グループはユニット全体として利用可能なワーカーに配布されます。これにより、ファイル内のすべてのテストが同じワーカーで実行されることが保証されます。

pytest-xdistドキュメント


単体テスト毎に並列実行するより処理時間はかかりますが、並列実行による時間短縮をしつつ、エラーも起こさないようにできました。

ここまでお読みいただきありがとうございました!


参考


この記事が気に入ったらサポートをしてみませんか?