不安定なテスト

「不安定な」テスト (Flaky tests) とは、断続的または散発的な失敗を示し、非決定的な動作をするように見えるテストのことです。 時々成功し、時々失敗し、その理由が明確ではありません。 このページでは、pytest の機能や、それらを特定、修正、または軽減するための一般的な戦略について説明します。

不安定なテストが問題である理由

不安定なテストは、継続的インテグレーション (CI) サーバーを使用している場合に特に厄介です。 すべてのテストが合格しなければ、新しいコード変更をマージできません。 テスト結果が信頼できる信号でない場合 (テストの失敗がコード変更によってテストが壊れたことを意味する場合)、開発者はテスト結果を信頼しなくなり、本物の失敗を見逃す可能性があります。 また、開発者がテストスイートを再実行し、偽の失敗を調査する必要があるため、時間の無駄にもなります。

潜在的な根本原因

システムの状態

広く言えば、不安定なテストは、テストが適切に制御されていないシステムの状態に依存していることを示しています。 テスト環境が十分に隔離されていません。 より高レベルのテストは、より多くの状態に依存するため、不安定になる可能性が高くなります。

不安定なテストは、テストスイートが並行して実行される場合 (例えば pytest-xdist の使用) に現れることがあります。 これは、テストがテストの順序に依存していることを示している可能性があります。

  • おそらく、別のテストが自分自身の後片付けに失敗し、不安定なテストが失敗する原因となるデータを残している可能性があります。

  • 不安定なテストは、自分自身の後片付けをしない前のテストのデータに依存しており、並行実行ではその前のテストが常に存在するわけではありません。

  • グローバル状態を変更するテストは、通常、並行して実行することはできません。

過度に厳しいアサーション

過度に厳しいアサーションは、浮動小数点の比較やタイミングの問題を引き起こす可能性があります。 ここでは pytest.approx() が役立ちます。

スレッドセーフ

pytest はシングルスレッドであり、常に同じスレッドでテストを順次実行し、自身でスレッドを生成することはありません。

テストを並行して実行するプラグインの場合でも、例えば pytest-xdist のように、通常は複数の プロセス を生成し、複数のスレッドを使用せずにバッチでテストを実行します。

もちろん、テストやフィクスチャがテストワークフローの一環としてスレッドを生成することは可能 (そして一般的) ですが、いくつかの注意が必要です。

  • 生成されたスレッドを最終的に待機することを確認してください。 例えば、テストの終了時やフィクスチャのティアダウン時に。

  • pytest が提供するプリミティブ (pytest.warns(), pytest.raises() など) を複数のスレッドから使用することは避けてください。 これらはスレッドセーフではありません。

テストスイートがスレッドを使用しており、不安定なテスト結果が見られる場合、テストが pytest 自体のグローバル状態を暗黙的に使用している可能性を無視しないでください。

その他の一般的な戦略

テストスイートの分割

単一のテストスイートをユニットと統合のように 2 つに分割し、ユニットテストスイートのみを CI ゲートとして使用することが一般的です。 これにより、高レベルのテストは遅くなる傾向があるため、ビルド時間を管理しやすくなります。 しかし、ビルドを壊すコードがマージされる可能性があるため、統合テストの結果を監視するために追加の警戒が必要です。

失敗時のビデオ/スクリーンショット

UI テストの場合、テストが失敗したときの UI の状態を理解するためにこれらは重要です。 pytest-splinter は pytest-bdd などのプラグインと一緒に使用でき、テスト失敗時にスクリーンショットを保存 でき、原因を特定するのに役立ちます。

テストの削除または書き直し

機能が他のテストでカバーされている場合、おそらくそのテストを削除することができます。 そうでない場合、おそらくより低レベルで書き直すことで、不安定さを取り除くか、その原因をより明確にすることができます。

隔離

Mark Lapierre は、2018 年の投稿で 隔離されたテストの長所と短所 について議論しています。

失敗時に再実行する CI ツール

Azure Pipelines (以前の Visual Studio Team Services または VSTS である Azure クラウド CI/CD ツール) には、不安定なテストを 識別 し、失敗したテストを再実行する機能があります。

研究

これは限られたリストです。 拡張するために issue または pull request を提出してください!

  • Gao, Zebao, Yalan Liang, Myra B. Cohen, Atif M. Memon, and Zhen Wang. "システムユーザーインタラクティブテストを再現可能にする: いつ、何を制御すべきか?." In Software Engineering (ICSE), 2015 IEEE/ACM 37th IEEE International Conference on, vol. 1, pp. 55-65. IEEE, 2015. PDF

  • Palomba, Fabio, and Andy Zaidman. "テストの臭いのリファクタリングは、不安定なテストの修正を誘発するか?." In Software Maintenance and Evolution (ICSME), 2017 IEEE International Conference on, pp. 1-12. IEEE, 2017. Google Drive の PDF

  • Bell, Jonathan, Owolabi Legunsen, Michael Hilton, Lamyaa Eloussi, Tifany Yung, and Darko Marinov. "DeFlaker: 不安定なテストの自動検出。 " In Proceedings of the 2018 International Conference on Software Engineering. 2018. PDF

  • Dutta, Saikat and Shi, August and Choudhary, Rutvik and Zhang, Zhekun and Jain, Aryaman and Misailovic, Sasa. "確率的および機械学習アプリケーションにおける不安定なテストの検出。 " In Proceedings of the 29th ACM SIGSOFT International Symposium on Software Testing and Analysis (ISSTA), pp. 211-224. ACM, 2020. PDF

リソース