エンドツーエンドテスト: 救いへの道か破滅への道か?

この記事はPeter G Walenによるゲスト投稿です。

誰かをびっくりさせて面白いリアクションを見てみたいですか?エンドツーエンドテストは、あなたが思っているようなことを教えてはくれない、と言ってみましょう。よく、エンドツーエンドテストはテストのあるべき姿のお手本だと考えられています。それは間違いないのでしょうか?そもそも理に適っているのでしょうか?

昔から、テストは細分化されすぎており、狭い範囲のテストに膨大な時間が費やされているという考えが信じられています。それに対してよくソリューションとして提示されるのが、機能レベルのテストや統合テストを捨てて「エンドツーエンド」(E2E)テストに集中することです。

これが妥当な状況もあることはわかります。適切な状況では、すばらしいアイデアです。しかし、私の経験では、E2Eを他のすべてのテストよりも優先させると、品質の問題やデリバリーの遅れにつながることも多くあります。

プロジェクトは1つとして同じものはありません。同じソフトウェアを対象とするプロジェクトでさえ、テスト方法だけでなくさまざまな理由でまったく異なる結果になることがあります。理由はいろいろです。ここではテストだけを考えてみます。

追跡のシンプル化

E2Eを支持する理由としてよく挙げられるのは、テストの単一の参照ポイントになるということです。関連するすべてのステップが1つの場所に連続して配置されます。これは大いに意味のあることで、たいていの場合に有効です。

私が心配になるのは、テスト対象アプリケーションの複雑さを考えたときです。可能性がかぎられており、単純な場合は、このアプローチを採用します。折に触れて私もこのアプローチを採用し、良い結果を出しています。

複雑さが増すにつれて、1つのシナリオ内でありうるパスをめぐるバリエーションのせいで雲行きが怪しくなってきます。テストスクリプトが15から20ステップなら、魅力的な選択肢です。可能な組み合わせが5つか6つあって、1つのE2Eテストを構成するステップが80から100も増えるようなら、魅力は減少します。

関連するすべてのパスを1つの「テスト」に押し込めることで、「エンド」という概念が失われます―少なくとも弱められます。

1つのテストの組み合わせを分割し、それぞれ15から20ステップのスクリプトにするほうがよいと私は考えます。そうすれば、各バリエーションや可能なパスを個別に追跡できます。問題が発生した場合、問題のあるパスを他の明らかな問題がないパスとは切り離して扱うことができます。

シンプルが複雑になる

私が見るところでは、問題は「シンプル」をどのように定義するかです。使われている変数の値を変えながら同じステップを4回か5回(またはそれ以上)繰り返して実行するテストスクリプトは、時間を節約できるアプローチかもしれません。「この機能で考えられるシナリオはこれだけです」ということを簡単に提示できる方法です。進捗の追跡が非常に容易かつ明確になります。とても単純で容易な方法です。

1つのテストで1つの機能の多数のシナリオをテストするのが魅力的なのはよくわかります。私自身も、ソフトウェアや使われている変数の各セットで期待される動作をよく知っているときには、このアプローチを使うことがあります。

そうすることで、管理や制御がいくらか容易になりました。ソフトウェアの該当部分にどのような動作の幅があるかを1つのテストで示すことができました。この方法はうまくいきました。ただし、何か予期しないことが起こってテストが途中で失敗した場合は別ですが。そうなると、たちまち失敗の解明は非常にややこしい問題になりました。

新しいソフトウェアや大幅に変更が入ったソフトウェアを検証する場合、さまざまな状況でどのように動作するかを完全に理解している可能性は劇的に低下します。これに当てはまらないような例にはいまだお目にかかったことがありません。

複雑さ

ソフトウェアの一部分が処理しなければならない変数が増えるほど、値の組み合わせの数は増えます。組み合わせの数が増えるほど、似たような値のパターンを複数検証する必要性が増します。

E2Eテストを擁護する人たちのなかには、変数のあらゆる組み合わせを1つのテストでテストできることが大きな利点だと主張する者もいます。それを実現するには、そもそも値を間違って入力する可能性を抑えるような変数の管理方法が必要です。ここで課題となるのは、変数の各セットに対してテストステップ全体を実行する必要があることです。

理論上は、何らかの自動化されたテストツールを利用することが可能です。複雑なテストセットの手動テストでは、これがうまくいく確率は驚くべきものです。  

私の経験では、1つのスクリプトにデータの組み合わせが追加されるごとに、テストすべき条件を抜かしてしまう確率が上昇します。

複雑なものをシンプルに

私は「E2Eテストに集中して個々の部分のことは構わないように」と言われたことがあります。これがうまくいくのは、各コンポーネントが個別にテストされている場合だけだというのを悟るまでにしばらくの時間がかかりました。  

これを可能にするための次のステップは、E2Eテストを始める前に、コンポーネント間の統合ポイントであるハンドオフをテストすることでした。

また、テストの問題をレポートしたときに大いに難色を示されたことも覚えています。無効なデータの扱いから、数値であるはずがそうなっていない値まで、あらゆる問題がありました。さらに、毎晩実行する必要があるが、36時間ノンストップで実行しても終わらない「エンドツーエンド」のテストがありました。

解決策は、私がやっていたことより直接的であることがわかりました。E2Eテストの実行が求められたとき、それには必ず意味がありました。どの場合も、複雑なモデルを必要とし、シナリオが確実に期待どおり動作するようにさまざまな条件を通して実行する必要がありました。そのためにE2Eテストが求められたのです。

私が遭遇した問題は、テスト自体の性質からくる複数の問題の組み合わせでした。私たちは、組織として、個々のコンポーネントや関係するポイントの準備ができているかをしっかりと理解していませんでした。統合ポイントが問題になることが多々ありました。

問題が入り込んだ場所からずっと下流で見つかることもありました。あるコンポーネントから取得したデータを、ずっと下流で使用するために別のコンポーネントに渡すこともありましたが、データが無効であることもたびたびでした。

問題は、E2Eテスを実施するという方針にあるのではなく、どのようにE2Eを行うかという方法にありました。何もかもを大きな塊で処理しようとしているのが問題のように思われました。解決策は単純でした。少しずつテストするのです。

少しずつテストする

ソフトウェアの各セクションまたは機能を担当する開発チームが担当部分を注意深くテストしていたなら、個々の機能自体を心配する必要がないのは当然です。問題は、もちろん、各チームがそれぞれの成果物をどれほどテストしているかです。

それはともかく、もしコンポーネントが結合されるポイントを理解できるなら、各ポイントを個別に検証し、ソフトウェアの「エンドツーエンド」操作にどのような影響があるかをすべての関係者に理解させることができるでしょう。

2つの機能を取り出して機能自体と機能間の接点が動作することを確認したら、次に別の2つの機能に着目します。追加の2つの機能も動作することを確認できたら、4つの機能をすべて組み合わせることができます。

テストの範囲を徐々に拡大していくと、それぞれのコンポーネントについて、またコンポーネントがどのように相互作用しているかについて、貴重なナレッジベースを構築できるでしょう。他のチームが問題を解決するのを待たなければならないことによる時間の浪費は少なくなります。

この過程で蓄えた情報と遭遇した問題は、すべての関係者にソフトウェアがどのように動作するかについての明確な情報を提供します。これによって、プロジェクトチームは、解決すべき問題に対処するために必要なことをソフトウェアが実行しているかを判断する機会を得られます。

エンドツーエンドテストはどんなチームにとってもパワフルなツールです。ただし、実施が早すぎたり、個々の機能を理解する前に行った場合、貴重な時間やリソースが失われ、結局はプロジェクトをスローダウンさせるでしょう。

Peter G. Walenは、ソフトウェア開発、テスト、アジャイルプラクティスで25年以上の経験を持っています。ソフトウェアがどのように動作し、他のソフトウェアと連携するか、またソフトウェアを利用するユーザーをチームが理解できるよう支援に尽くしています。Agile AllianceScrum AllianceAmerican Society for Quality (ASQ)のメンバーであり、ソフトウェアミートアップに熱心に参加し、カンファレンスでもたびたび講演しています。

(この記事は、開発元Gurock社の Blog 「End to End Testing: Road to Salvation or Perdition?」2020年4月16日の翻訳記事です。)

eBook 公開中

Paul Gerrard著 効果的なテスト管理12の秘密 (日本語)

テスト計画やテスト管理に役立つ12のトピックを解説します。

詳細はこちら