テスト自動化は開発生産性を向上させるためには、強力なソリューションです。そのため、できる限りテスト自動化を取り組むことが望ましいでしょう。ただし、やみくもにテスト自動化を導入すると、かえって生産性を落とすことに繋がりかねません。
テスト自動化を導入する上で考慮すべきなのがテストバランスについてです。
アプリケーションのテストを行うとき、一般的にいくつかのテストレイヤーが存在します。
ソースコードのモジュールレベルのテストを行う「ユニットテスト」、
システム内のコンポーネントやサービス、これらを実現するAPIなどのテストを行う「統合テスト」、
アプリケーションをユーザー視点でテストを行う「UIテスト」。
これらのテストをバランスよく行うことで、開発生産性を維持することができます。
今回は、テスト自動化のバランスでよく用いられる「テストピラミッド」という考え方と、そのアンチパターンとなる考え方について解説します。
- もくじ
1.テストピラミッドとは? 概要と構造
「テストピラミッド」とはMike Cohn氏出版の「Succeeding with Agile」で提唱されたモデルです。
ソフトウェアテストの自動化にて、異なるテストレベルのテストを効果的に配置する考え方です。
テストレベルごとに適切な比率を示し、テストの信頼性と効率性を高めることを目的としています。
テストピラミッドの各レイヤーについて解説していきます。
1-1 ユニットテスト (Unit Tests)
ユニットテスト(Unit Tess)では、コードの最小単位(関数やメソッド)が意図した通りに動作するかを検証します。
特徴として以下の3つがあります
- 高速実行 : 短時間で実行でき、開発効率向上
- 独立性 : 他のテストに依存せず、単体で実行可能
- 再現性 : 常に同じ結果が得られる
ユニットテストを実施することで、開発初期段階で問題を早期発見し、修正コストを削減できます。
また、テスト駆動開発など、開発プロセスに組み込むことで、より高品質なコードを作成することが可能です。
1-2 統合テスト (Integration Tests)
統合テスト(Integration Tests)では、複数のコンポーネントやモジュールが正しく連携して動作するかを確認します。APIのテストもここに含まれます。
特徴として以下の3つがあります。
- 複数のユニットの連携検証 : 複数のユニットが組み合わさった状態の動作確認
- インタフェースの検証 : モジュール間のインタフェースが正しく機能するかの検証
- データの整合性の検証 : 異なるモジュール間でデータが正しくやり取りするかの検証
単体では問題がなくても、組み合わせて初めて問題が発生する場合があります。統合テストを実施することで、その連携問題を早期に発見できます。
ただし、ユニットテストに比べると、環境依存が発生し、テスト実行時間がかかる傾向もあります。
1-3 UIテスト (UI Tests)
UIテスト(UI Tests)では、システム全体をユーザー視点でテストします。
UIを通じて操作し、視覚的な要素や操作性が正しく機能しているか確認し、システム全体の信頼性を確認します。
特徴として以下の3つがあります。
- 忠実度の高い環境で検証:実際の運用条件に近しい環境で、ユーザーの視点でシステムを操作し、問題点を洗い出す
- 視覚的な要素の検証 : ボタンの色、フォントサイズ、レイアウトなど、視覚的な要素の表示確認
- 操作性の検証 : ボタンのクリック感、テキスト入力の反応など、操作性を確認
UIテストをすることで、ユーザーが気づきやすい問題点を早期に発見できます。また、本番運用に近しい環境でテストするため、外部要因などによる不具合も検出することができます。
ただし、 様々なユーザーの操作パターンを想定する必要があるため、テストケースの作成が複雑になる場合があります。さらに、実行時間は他のテストレベルに比べて時間がかかります。
2.テストピラミッドはテストバランスの理想形
テストピラミッドは、テスト自動化の理想的なボリュームバランスを表現したものです。
テストのバランスを最適化することは、テストの効率性、信頼性、そして開発スピードを最適化することになります。
ユニットテストは、粒度が細かく、実装コストを抑えて高速実行ができるために、バク改修も早く、テスト効率が良いです。また、外部要因に影響されにくいために、信頼性も高くなります。
ただし、結合した視点や外部要因の考慮などは検証できません。
統合テストは、ユニットテストではできない、ユニット間連携のテストをカバーできます。
ただし、ユニットテストに比べて、多少実装コストがかかり、テスト実行時間もかかります。外部要因によるテスト不安定さが増しますが、実運用を想定した外部要因を考慮したテストとしてある程度行うことは必要になります。
UIテストは、すべてのシステム結合し、忠実度の高い環境で、ユーザー視点の動作検証として必要です。
ただし、ほかのテストレベルに比べてUIテスト自動化はコストが高く、テスト実行が遅く、バグの原因を特定するのに時間がかかります。
このように、一つのテストレベルでテスト自動化を頑張るとテストの効率性、信頼性、開発スピードのどれかが落ちてしまいます。
そのため、具体的な目標値があるわけではないですが、一般的にユニットテストで多くカバーして、統合テストからUIテストと上に行くにつれて、テストを少なくすることが、テスト自動化のバランスがとれているということになります。
3.テストピラミッドのアンチパターン
テストピラミッドは、理想形のテスト自動化のバランスです。
しかし、現実はそうはいきません。いろいろな要因によってこの理想から外れてしまうことがあります。
理想通りでなくてもいいのですが、理想から外れるとどういった状況に陥るか、良くない状態を見直すために、テストピラミッドのアンチパターンを理解しておきましょう。
2-1 アイスクリームコーン
「アイスクリームコーン」は、ユニットテストが少なく、UIテストが非常に多い状態を指します(逆ピラミッド)。
このアイスクリームコーンの状態になると、UIのテスト実行時間が長いため、フィードバックサイクルが遅くなり、バグ発見が遅れる可能性があります。また、UIテストのメンテナンスコストが非常に高くなり、保守コストが増大します。 UIテストは忠実性の高いテストは多くカバーできますが、環境に依存しやすく、テストが不安定になります。
これが起きる原因としては、UIテストが比較的容易に作成できること、UIテストがシステム全体を検証できるために「このテストで十分」と錯覚していることなどが挙げられます。
2-2 カップケーキ
「カップケーキ」は、すべてのテストレベルが均等に存在する状態を表しています。
一番上のチェリーは探索的テストを表しており、手動テスト含めて各テスト同じボリュームのテストを行い、かつ心配なので探索的テストをしている、という効率の悪いものになっています。
これは、各レベルのテストケース数が多くなり、テスト実行時間が長くなっている状態にあります。 そして、異なるレベルのテストで同じロジックをテストしている可能性があり、 重複テストしていることが考えられます。それによりテストの保守性も低下してしまいます。
これが起きる原因としては、全てのケースを網羅するためにテストカバレッジを100%に近づけようとするあまり、不必要なテストを作成してしまうことが考えられます。
もしくは、それぞれのテストレベルの担当が異なり、コミュニケーションが取れていないために起きている可能性があります。
2-3 砂時計
「砂時計」とは、ユニットテストとUIテストが多く、統合テストが少ない状態のことです。
各コンポーネントが正しく連携しているかを確認する統合テストが不足しているため、バグが統合の段階で見つかる可能性が高まり、修正コストが大きくなる可能性があります。
これが起きる原因として、統合テストは環境構築やテストデータの準備が複雑なため敬遠されてしまうこと、単体テストやUIテストに注力し、統合テストが後回しになることなどが考えられます。
2-4 アンブレラ型
「アンブレラ型」は、テスト自動化が極端にUIテストが多く(もしくはUIのみで)、ユニットテストやインテグレーションテストが少ない形状を指します。
これにより、以下のような問題が生じます。
- UIテストは実行時間が長く、フィードバックが遅れるため、開発サイクルが遅くなる。
- UIテストの作成と保守に多くのコストがかかる。
- UIテストは不安定で、テスト結果の信頼性が低くなり、調査・やり直しテストなどが発生するため開発サイクルが遅くなる。
開発リソースが限られている場合、短期的な解決策として、比較的取り組みが簡単なUIテストに依存することがあります。
最後に
テストピラミッドは、テスト自動化の理想的なボリュームバランスを表現したものです。ただし、理想形にならないことが多く、また必ずしも理想形にする必要はありません。
また、テストのバランスは、システムのアーキテクチャに大きく依存します。
例えば、メインフレームシステムでは自動化が難しい部分が多く、GUIテストやバッチ処理のテストが中心となります。一方、マイクロサービスアーキテクチャではAPIテストや契約テストが有効です。
重要なのは、現状を把握し、段階的に改善していくことです。組織の文化や成熟度も考慮し、現実的な目標を設定することが大切です。
このように、アーキテクチャに合わせたテスト自動化のバランスを構築し、もしアンチパターンの類似の課題を感じるようであれば、適切な対策を講じることで、より効率的で高品質なソフトウェア開発を実現することができるでしょう。
テスト自動化のバランスに課題を感じている方はぜひ本記事を参考にしてみてください。