CI/CDパイプライン:品質を維持し、追加コストをかけずに、自動化ソフトウェアのテスト時間を85%短縮する方法
はじめに
自動化テストをCI/CDパイプラインに組み込むと非常に大きな利点が得られます。ただし、真に効果的であるためには、テスト時間が標準的な開発サイクルと合致して、可能な限り迅速にフィードバックが提供されなければなりません。実装を完了させた後に、パイプラインに定義されたリグレッションテストやDevSecOpsテストにコードが合格したかどうかを確認するまで長い時間待たされることほど、開発者がフラストレーションを感じることはありません。
プラクシディティ エックスは、社内の製品開発部門とお客様の双方のために開発サイクルの最適化に取り組んでいます。
これから、当社の主要な製品開発チームが、夜間のテスト実行時間を2時間44分からわずか21分に短縮した方法についてご紹介します。
ステップ1 – 現状分析
テスト実行の改善に向けた最初のステップは、現状を理解し、テストにかかる時間の裏に潜む根本原因を明らかにすることでした。
チームはウィザードとして構築されたWebベースのアプリケーションのテストを担当しています。ウィザードでは、一連のステップを通じてシステムに様々なパラメータや機能を設定でき、最終的にはユーザーが使用できるダウンロード可能な出力が提供されます。
安全性が保証された範囲を確保するために、テストは主に次の2つのカテゴリーに分かれていました。
- 機能テスト – アプリケーションの様々な機能、ロジック、要素をテストする
- エンドツーエンド(E2E)テスト – システムの様々なフローを実行し、出力をダウンロードし、出力に期待通りの結果が含まれているか検証する
Allureレポートとコードを詳しく調べたところ、実行時間に関する興味深い知見を得ることができました。
- テストは順番に実行されている。つまり、総実行時間は個々のテストにかかった時間の合計である
- 何かが原因で単純な機能の検証に時間がかかっている
- 他より大幅に時間のかかる機能がある
- テストケースとそれらのステップ、再実行方法に冗長性が見つかった
ステップに長い時間がかかっている原因を分析したところ、次のようないくつかの要因が重なっていることがわかりました。
- アプリケーションを実行するマシンリソースが不足していたために、アプリケーションの動作が遅くなっていた
- テスト効率が最適ではなかった。UIで操作し、より効率のよいRESTful APIを使用していなかった(UI要素がテスト対象でない場合)
次に、一部のステップに他のステップより大幅に時間がかかっていた原因の解明に取り組みました。例えば「ページに移動」のステップは効率よくコード化されていなかった、ということがわかりました。該当ページに移動するのに、自動化インフラストラクチャとして目的画面にただ「ジャンプ」すれば済むところを、ユーザーとして目的のページまで各画面への移動を繰り返していました。
テストケースにおけるログインメカニズムの問題解決にも取り組みました。通常、各テストケースでは設定フェーズ時にブラウザを開き、URLに移動してログインを実行します。一部のテストケースでログインメカニズムを検証すれば、他のすべてのテストケースでこのプロセスを踏む必要はありません。代わりに、一度ログインしてセッションを維持し、残りのテストケースを実行することで、ログインフェーズをスキップすることができます。
注:不安定なテスト(一貫性のない結果を出すテスト)は、テストケースを再実行して貴重な時間を浪費することになりがちな重大な課題です。次のブログでは、不安定なテストを管理・軽減するための戦略を掘り下げます。どうぞお楽しみに。
ステップ2 – 必要な改善の導入
最初のステップで集めた知見と情報に基づき、私たちは次のアクションアイテムを定めました。
- テストケースの並列実行を実装する
- テスト対象システム(SUT)を実行するマシンリソースを拡充する
- テストインフラストラクチャにRESTful APIハンドラーを実装する
- 「ページに移動」などの機能の実装を最適化する
- ログインフェーズを最適化する
- テストケースを確認し、冗長なケースを取り除く
- テストケースを確認し、冗長なステップを取り除く
上記のアクションアイテムは1人以上の分量だったため、複数のチームメンバーが関与しました。これらのアクションアイテムを割り当てた後、「クイックウィン(即効性のある小さな成功)」を達成することを優先して、早い段階で目に見える改善を実現し、フィードバック時間を10~15分に短縮するという目標に向けてチームの士気を上げました。
並行テストの実行
並行テストの実行は有益であると広く認められていますが、次のような課題が存在します。
- テストランナーが並行実行をサポートしなければならない
- テスト用システムで複数の同時操作をサポートするか、複数のテスト環境を設定する必要がある
- 各テストは独立して実行できる必要がある。テストの設定で必要な状態を作り、テスト後にクリーンアップしなければならない
- テストケースは他のテストケースで使用している共有リソースを上書きしたり、共有リソースへのアクセスに関して競合したりしてはならない
私たちは次のような方法でこれらの課題に対処しました。
- テストランナーにpytestを使用する。これには「pytest-xdist」という並行実行向けのすぐれたプラグインが用意されている
- テスト用システム自体が複数の操作をサポートしている。そのため、システムの動作が大幅に遅くなっていた。システムリソースを最適化するためにDevOpsチームと協力した
- テストの独立性はすでに実装されていた(テスト自動化のための一般的なベストプラクティス)
- 出力ファイルの管理は重要な課題だった。テストを並行実行すると、相互のファイルが上書きされていた。各テスト出力に一意のパスを割り当て、テスト名と正確な実行時間をそれに組み入れることで、この課題を解決した。UUIDもこの目的に役立ったと考えられる
注意すべき重要なことの一つは、起動できるワーカー(独立したプロセス)の数を、実行するマシンに含まれるCPUの数と等しくすることです。CPUの数が増えれば増えるほど、並行で実行できるテストの数が増え、実行時間が短くなります。
2営業日後、私たちは8つのCPUを備えたマシンを使用して並行実行を組み込むことに成功ました。これにより、夜間の実行が2時間45分から48分にまで短縮できました。
今後、各マシンのCPUの数を増やして、さらに改善を進めようと計画しています。
テストインフラストラクチャにRESTful APIハンドラーを実装する
テストは通常、前処理、実行、後処理の3つのフェーズで構成されます。
前処理と後処理のフェーズで実行する操作は主要機能をテストしないため、必要な機能を使用できる限り、柔軟に実装することができます。したがって、より軽くて速いRESTful API呼び出しで同じ結果を効率良く達成することができるのであれば、重くて遅いUI操作に頼る必要はなくなります。
テストケースでRESTful API呼び出しを使用するために、次のことを実行しました。
- 統合レイヤーの開発 – RESTful APIとのすべてのインタラクションを処理するテストフレームワーク内のレイヤー。このレイヤーにはリクエストの送信、応答の処理、認証トークンの管理を行う機能が含まれます。
- RESTful APIベースの機能の実装 –テストの一環として使用する機能(「create_new_project」など)について、RESTful APIハンドラーを使用した実装を追加できました。そのため、設定に応じてRESTful APIまたはUI操作のいずれかを使用して操作できるようになりました。
- テストケースの前処理と後処理を変換してRESTful API機能のみを使用するようにしました。
この移行には開発チームとの幅広い連携が欠かせませんでした。結果的にテストケースの実行時間が大幅に短縮(各テスト約2分からわずか30秒に短縮)され、夜間の実行時間が全体で23分にまで短くなりました。
その他の改善点
上記に加え、アクションアイテムリストの他のアクティビティも実装して、テストインフラストラクチャの効率を向上させ、自信を持ってCI/CDプロセスを行えるようになりました。最も重要なことは、これらのすべての改善を、テスト品質を損なうことなく達成できたことです。つまり、同じ機能やセキュリティをより短い時間で網羅できるようになったのです(グラフを参照)。
現在、テスト実行時間は21分にまで短縮され、目標の10~15分も視野に入ってきました。目標達成まであと少しです!
覚えておきたい重要点
ここまでお読みいただいた方はおそらく、自社のテスト自動化を改善する方法にご興味をお持ちなのではないでしょうか。
次に、私たちが経験から得た学びをご紹介しますので、ぜひご検討ください。
技術的なヒントとリソース
- テストインフラストラクチャ用の並列テスト実行プラグインをご検討ください。
- Python – pytest – pytest-xdist
- Python – unittest – nose2
- Java – JUnit 5 – junit-platform-parallel
- Java – TestNG – ビルトインサポート
- JavaScript – Jest – ビルトインサポート
- JavaScript – Mocha – ParallelBufferedRunner
- JavaScript – Cypress – ビルトインサポート
- 自動化にRESTful APIをまだ利用していない場合は、RESTful APIテスト戦略の計画を開始し、関連する開発マネージャーに必要なプラットフォームの提供を依頼してください。
- Playwrightを使用していて、ワンタイムログインのメカニズムを導入したいとお考えの場合は、このブログをご確認ください。他のフレームワークでも、同じ結果を達成するための独自の方法があるはずです。
まとめ
この投稿はCI実行時間の短縮に焦点を当てていますが、このアプローチは一連のパフォーマンステストの実施、新たなDevSecOPSツールのパイプラインへの組み込み、自動テストケース生成へのAIの統合など、プロジェクトの内容に関わりなくあらゆる自動化改善プロジェクトに適用できます。
QA自動化改善プロジェクトを成功させるための当社の基本計画は次の通りです。
- 現在の稼働状況とその要因を分析する
- アクションアイテムを管理可能な小さなステップに分割する
- タイムラインに沿ってアクションアイテムの実施を計画し、関係リソースを割り当てる
- 各アクティビティを継続的にモニタリングする
最後に、クイックウィンの重要性を過小評価しないでください。簡単に完了できて目に見える効果を発揮するステップがどれかを見つけ出してください。クイックウィンによってチームの自信が高まるだけでなく、取り組みの正当性を組織内の他のステークホルダーに説明しやすくなります。
さらに詳しい内容にご興味をお持ちでしょうか?