テストピラミッドアプローチで製品の迅速な納品を実現する

I. テストピラミッドの理由

企業は自動化テストに多額の投資をしていますが、次のような改善が見られていません。

品質が向上しない
生産性が増えない
ユーザーの評判が良くならない

これの主な理由は、ブラウザベースのエンドツーエンドテストに過度に依存していることです。

技術チームが目に見えるビルドの状況を把握していれば、たとえばこんな感じになるかもしれません。

画像

テストスイートの実行が長い; 30分~4時間、時には数日
不安定なテストが10回に1回、あるいは3回に1回失敗する
QAと開発者がリグレッションテストの作成とメンテナンスに多くの時間を費やし、問題を見つけて修正する代わりに
環境が壊れている、または本番環境を反映していないため、リグレッションテストの有用性が否定される

II. テストピラミッドとは

2012年、マーチン・ファウラーはテストピラミッドについての記事を書きました。これはマイク・コーエンが開発した概念です。

テストピラミッドは、長時間実行されるUIテストへの過度な依存の問題を解決するためのツールです。

ピラミッドは、低いレベルのテストが書くのも維持するのも安く、実行時間も速いと説明しています。上位レベルのテストは書くのも維持するのも高価で、実行時間も遅いです。ですから、多くのユニットテスト、いくつかのサービステスト、そしてほとんどUIテストは行わないほうが良いです。

よく見かけるのが、企業のテストスイートがアイスクリームコーンのようになっている場合です。

テストアイスクリームコーン

ここでは、ごく少数のユニットテスト、いくつかのUIテスト、数多くのQAテストと手動テストがあります。

この状況ではQA部門は自動テストスイートを作成していますが、開発チームは作成していません。開発チームがスイートの構築や、テストを簡単にするためのアプリケーションのアーキテクチャの設計を手伝っていないため、実行がとても長くなり、不安定です。開発者によって頻繁に壊され、QA部門が修正を頼りにしています。

おそらく、手動のテストチームと自動化されたテストチームの両方が存在します。テストスイートに十分な信頼がないため、リグレッションが2回、一度は手動で、もう一度は自動で行われている可能性があります。この二重の作業とテストチーム間の余分な引き継ぎのせいで、このアプローチは会社のスピードを遅くしてしまいます。

テストアワーグラス

この状況では、たくさんのユニットテストとUIテストはあるものの、サービスベースのテストはほとんどありません。

これはより良い状況です。手動テストがなく、QA部門が会社が頼りにするテストスイートを作成しています。開発者は多くのユニットテスストを書いています、彼らはTDDを実践しているかもしれません。しかし、ユニットテストでテストされるロジックの多くがユーザーインターフェースのテストでもテストされているため、再び二重の作業が発生しています。QAチームは、より安価なサービスベースのテストの代わりに、主にブラウザベースのテストに頼ってリグレッションを行っています。

アワーグラスとアイスクリームコーンの両方が、QA部門と開発部門の間に協力とコミュニケーションが不足していることを示しています。彼らはおそらく組織的にも場所的にも分けられているでしょう。

III. ユニットテスト(レベル:ユニット)

ユニットテストは、個々のユニット/コンポーネントが設計どおりに機能するかを検証するソフトウェアテストのレベルです。ユニットとは、任意のソフトウェアの中で最も小さなテスト可能な部分です。通常は1つまたはほんの少数の入力を持ち、通常は1つの出力を持ちます。手続き型プログラミングでは、ユニットは個々のプログラム、関数、手続きなどになる場合があります。オブジェクト指向プログラミングでは、最小のユニットはメソッドであり、基底/スーパークラス、抽象クラス、または派生/チャイルドクラスに属する場合があります。(アプリケーションのモジュールをユニットと見なすこともありますが、そのモジュール内に多くの個々のユニットが存在する可能性があるため、これは奨励されません。)ユニットテストのフレームワーク、ドライバー、スタブ、モック/フェイクオブジェクトが、ユニットテストを支援するために使用されます。

画像

ユニットテストを行う際には、依存関係を避けるためにモックツールを使用するべきです(Javaではmockito、Pythonにはunittestにモック機能があります)。

IV. 契約テスト(レベル:ユニット)

マーチン・ファウラーのページから契約テストについて参照できます。

よく異なるチームがマイクロサービスを実行する際に使用されます。

契約テストは開発者によって行われます。

あるチームは他のチームから特定のタイプの結果(文字列、整数、または正規表現かもしれません)を期待しています。

モッキングデータを使ってテストを定義します。

実際の例を挙げると:

私はお昼休みに初めて歩くルートにある新しいスペシャルティーショップに行きたいけど、午後2時の会議までに戻る時間が十分にあるかどうか心配です。この旅行にどのくらい時間がかかるか情報が必要です。

私が持っている資源を考えると、私は2つのアプローチを取ることができます - そこまで歩いて、歩いた時間を倍にして旅の総合計を計算する。オンラインのルートマッパーでそのルートの見積もりを確認する。

一方のオプションはもう一方よりずっと速く、依存関係がなく、私が求める答えにかなり近いものですが、旅の下位レベルの詳細(風速、勾配)を省略しています。私がそれを自分自身でタイミングを取ることで学ぶでしょう。

これはまさに契約テストが行うことです。それは応答をモックするか問い合わせることによって、あなたが必要とする機能に関するいくつかの情報を得ることを可能にします。

V. APIテスト

APIはApplication Programming Interfaceの略であり、2つのアプリケーション(サービス)がお互いに通信できるようにするソフトウェアの中間者です。

良い想像力のための実世界の例:

あなたはレストランのお客さんです。

欲しい料理を手に入れるために、ウェイター/ウェイトレスを呼びたいです。

彼はあなたが欲しい料理についての情報を得て、厨房内の他のコックと話します。

料理が出来たら、ウェイター/ウェイトレスから料理を受け取ります。

私が話しているAPIはウェイター/ウェイトレスです。

画像

APIテストはGUIテストとは全く異なり、ソフトウェアアーキテクチャのビジネスロジック層に主に集中しています。このテストはアプリケーションのルックアンドフィールには集中しません。

標準のユーザー入力(キーボード)と出力を使わずに、APIテストではソフトウェアを使ってAPIへのコールを送り、出力を得て、システムのレスポンスを記録します。

APIテストには、APIと対話するアプリケーションが必要です。APIをテストするためには、

APIを駆動するテストツールを使用する
APIをテストするための独自のコードを書く

APIテストを実装するためのいくつかのツール:cURL、Postman、Jmeter、またはサービスへのHTTPリクエストをコールする独自のテストスクリプトを書きます。

VI. UIテスト

アプリケーションの機能をGUIで直接確認します。

これは顧客の実際の使用に近いですが、時間がかかり全てのテストケースを確認するのは難しいです。

VII. 手動テスト

検証を手動で行います。

行うには多くの時間とリソースが必要ですが、ほぼ全てのテストタイプを実行できます。

このためのベストプラクティスは、テストを自動化できない場合(検索エンジンのテスト、500エラーなど)のみ行うべきです。

こちらの記事はdev.toの良い記事を日本人向けに翻訳しています。
https://dev.to/cuongld2/test-pyramid-approach-for-faster-product-delivery-54ci