暡擬詊隓ピラミッド

著者に぀いお Ham Fokkeは、ドむツのThoughtWorks開発者およびコンサルタントです。 3晩の展開にうんざりしおいた圌は、ツヌルキットに継続的な配信ず培底した自動化の手段を远加したした。 珟圚、他のチヌム向けにこのようなシステムをセットアップしお、信頌性の高い効率的な゜フトりェア配信を確保しおいたす。 そこで圌は、これらの迷惑な小さな人々が圌らのふざけた行動に費やす時間を䌁業に節玄したす。



テストピラミッドは、さたざたな詳现レベルで゜フトりェアテストをグルヌプ化するこずを意味するメタファヌです。 たた、これらの各グルヌプにいく぀のテストを行うべきかずいうアむデアも提䟛したす。 テストピラミッドの抂念は長い間存圚しおいたずいう事実にもかかわらず、倚くの開発チヌムは、それを正しく正しく実行しようずしおいたす。 この蚘事では、テストピラミッドの初期抂念に぀いお説明し、それを実珟する方法を瀺したす。 ピラミッドのさたざたなレベルでどのタむプのテストを怜玢する必芁があるかを瀺し、それらの実装方法の実甚的な䟋を瀺したす。



内容


泚釈







゜フトりェアはリリヌス前にテストする必芁がありたす。 ゜フトりェア業界が成熟するに぀れお、テスト手法が成熟したした。 無数の生きたテスタヌの代わりに、開発者はほずんどのテストの自動化に切り替えたした。 テストの自動化により、数日たたは数週間埌にではなく、コヌドに入力されおから数秒および数分でバグを芋぀けるこずができたす。



自動テストによっお匷化された劇的に短瞮されたフィヌドバックルヌプは、アゞャむル開発プラクティス、継続的デリバリヌ、DevOpsカルチャヌず密接に関連しおいたす。 効果的なテストアプロヌチにより、迅速か぀確実な開発が可胜になりたす。



この蚘事では、マむクロサヌビスアヌキテクチャ、モバむルアプリケヌション、たたはIoT゚コシステムを構築しおいるかどうかに関係なく、柔軟性、信頌性、およびサポヌトを実珟するための敎圢匏テストスむヌトの倖芳に぀いお説明したす。 たた、効果的で読みやすい自動テストの䜜成に぀いおも詳しく芋おいきたす。



自動化の重芁性テスト



゜フトりェアは、私たちが䜏んでいる䞖界の䞍可欠な郚分ずなっおいたす。 ビゞネスの効率性を高めるずいう本来の唯䞀の目的を超えたした。 今日、すべおの䌁業は䞀流のデゞタル䌁業になるこずを目指しおいたす。 私たちは毎日、たすたす倚くの゜フトりェアのナヌザヌずしお行動しおいたす。 むノベヌションの速床は増加しおいたす。



時代に遅れないようにするには、゜フトりェアの品質を犠牲にするこずなく、より迅速に゜フトりェアを提䟛する方法を探す必芁がありたす。 継続的な配信はこれに圹立ちたす。これは、゜フトりェアがい぀でも本番環境にリリヌスされるこずを自動的に保蚌するプラクティスです。 継続的な配信では、アセンブリパむプラむンを䜿甚しお゜フトりェアを自動的にテストし、テスト環境および運甚環境に展開したす。



すぐに、増え続ける゜フトりェアを手動でアセンブル、テスト、展開するこずは䞍可胜になりたす-動䜜䞭の゜フトりェアを提䟛するのではなく、日垞的なタスクを手動で行う堎合を陀きたす。 唯䞀の方法は、アセンブリからテスト、展開、むンフラストラクチャに至るたですべおを自動化するこずです。







図 1.自動で信頌性の高い゜フトりェアの詊運転にアセンブリパむプラむンを䜿甚する



埓来、テストでは、テスト環境での展開を通じお過床の手動䜜業が必芁でした。その埌、たずえば、ナヌザヌむンタヌフェむスの任意の堎所をクリックしおバグが衚瀺されるかどうかを確認するブラックボックススタむルのテストが必芁でした。 倚くの堎合、これらのテストはテストスクリプトによっお蚭定され、テスタヌがすべおを順番にテストするようにしたす。



明らかに、すべおの倉曎を手動でテストするには倚くの時間がかかり、単調で退屈です。 単調さは退屈であり、退屈は間違いに぀ながりたす。



幞いなこずに、同じタスクのための優れたツヌルがありたす  オヌトメヌション 。



統䞀されたテストを自動化するず、開発者ずしおの生掻が倉わりたす。 テストを自動化すれば、プログラムの正しい動䜜を確認するために、クリックプロトコルを無意識にたどる必芁がなくなりたす。 テストを自動化し、目を倉えずにコヌドベヌスを倉曎したす。 適切なテストセットを䜿甚せずに倧芏暡なリファクタリングを詊みたこずがあれば、これがどのような恐怖に぀ながるかを知っおいるはずです。 誀っおプロセスを間違えた堎合、どのようにしおわかりたすか さお、すべおのテストケヌスを手動でクリックする必芁がありたす。 しかし、正盎に蚀っおみたしょう。本圓に奜きですか 倧芏暡な倉曎を行った埌でも、コヌヒヌを飲みながら数秒以内にバグが珟れたすか 私の意芋では、これははるかに優れおいたす。



テストピラミッド



自動化されたテストを真剣に考えおいる堎合、重芁な抂念が1぀ありたす。 テストピラミッドです。 圌女はMike Cohnの著曞Scrum Agile Software Development Using Scrumで玹介されたした。 これは優れた芖芚的隠phorであり、さたざたなレベルのテストを瀺唆しおいたす。 たた、各レベルでのテストの量も瀺したす。









図 2.ピラミッドをテストする



マむクコヌンの元のテストピラミッドは、3぀のレベル䞋から䞊で構成されおいたす。



  1. 単䜓テスト。
  2. サヌビステスト
  3. ナヌザヌむンタヌフェむステスト


残念ながら、より培底的なコンセプトでは䞍十分のようです。 マむクコヌンのテストのピラミッドの呜名たたは抂念的な偎面のいずれかが完党ではないず䞻匵する人もいたすが、私は同意する必芁がありたす。 珟代の芳点から、テストピラミッドは過床に単玔化されおいるように芋えるため、誀解を招く可胜性がありたす。



ただし、シンプルなため、テストピラミッドの本質は、独自のテストスむヌトを䜜成する際の経隓則です。 このピラミッドから芚えおおくべき䞻なこずは、2぀の原則です。



  1. 異なる詳现のテストを䜜成したす。
  2. レベルが高いほど、テストは少なくなりたす。


ピラミッドの圢状に固執しお、健康的で高速で保守可胜なテストスむヌトを䜜成したす。 小さくお玠早い単䜓テストを たくさん曞いおください。 より䞀般的なテストをいく぀か䜜成し、アプリケヌションを最初から最埌たでテストする高レベルの゚ンドツヌ゚ンドテストをいく぀か䜜成したす。 テストアむスクリヌムコヌンになっおいないこずを確認しおください。これはサポヌトの悪倢になり、完了するのに時間がかかりすぎたす。



テストピラミッドの個々のレベルの名前にあたり執着しないでください。 実際、誀解を招く可胜性がありたす。「サヌビステスト」ずいう甚語は理解するのが難しいですCohn自身は、 倚くの開発者がこのレベルを完党に無芖しおいるこずに泚意したした。 最近、React、Angular、Ember.jsなどの単䞀ペヌゞアプリケヌションのフレヌムワヌクでは、UIテストがピラミッドの最䞊䜍に属さないこずが明らかになりたした。これらすべおのフレヌムワヌクでUIを完党にテストできたす。



ピラミッドの元の名前の欠点を考えるず、テストレベルの他の名前を思い付くのはごく普通のこずです。 䞻なものは、圌らがあなたのチヌムによっお採甚されたあなたのコヌドず甚語に察応するずいうこずです。



怜蚎するツヌルずラむブラリ





応甚䟋



ピラミッドのさたざたなレベルのテストを䜿甚しお、 簡単なマむクロサヌビスを䜜成したした。



これは兞型的なマむクロサヌビスの䟋です。 RESTむンタヌフェヌスを提䟛し、デヌタベヌスず通信し、サヌドパヌティのRESTサヌビスから情報を抜出したす。 Spring Bootで実装されおおり、 Spring Bootを䜿甚したこずがない堎合でも理解する必芁がありたす。



必ずGithubでコヌドを確認しおください。 readmeファむルには、コンピュヌタヌでアプリケヌションず自動テストを実行するための指瀺が含たれおいたす。



機胜性



アプリケヌションにはシンプルな機胜がありたす。 3぀の゚ンドポむントを持぀RESTむンタヌフェヌスを提䟛したす。



GET /hello

"Hello World" . .



GET /hello /{lastname}

. , "Hello {Firstname} {Lastname}" .



GET /weather

, .








高レベルの構造



倧たかに蚀うず、システムの構造は次のずおりです。









図 3.高レベルのマむクロサヌビス構造



圓瀟のマむクロサヌビスは、HTTP経由のRESTむンタヌフェヌスを提䟛したす。 䞀郚の゚ンドポむントでは、サヌビスはデヌタベヌスから情報を受け取りたす。 それ以倖の堎合、HTTP経由で倖郚APIにアクセスしお、珟圚の倩気を受信しお​​衚瀺したす。



むンテリア建築



内郚では、Spring ServiceにはSpringの兞型的なアヌキテクチャがありたす。









図 4.マむクロサヌビスの内郚構造





経隓豊富なSpring開発者は、頻繁に䜿甚されるレむダヌが欠萜しおいるこずに気付く堎合がありたす。 問題指向の蚭蚈に觊発された倚くの開発者は、 サヌビスクラスで構成されるサヌビスレむダヌを䜜成したす。 アプリケヌションには含めないこずにしたした。 その理由の1぀は、アプリケヌションが非垞に単玔であり、サヌビス局が䞍芁なレベルの間接化になるこずです。 別の理由は、私の意芋では、人々はしばしばこれらのレむダヌでそれをやりすぎるこずです。 倚くの堎合、サヌビスクラスがビゞネスロゞック党䜓をカバヌするコヌドベヌスを確認する必芁がありたす。 ドメむンモデルはデヌタの単なるレむダヌになり、動䜜のレむダヌではありたせん 貧血ドメむンモデル 。 すべおの重芁なアプリケヌションで、優れたコヌド構造化ずテスト容易性のための倧きな機䌚が倱われ、オブゞェクト指向の力が十分に掻甚されおいたせん。



リポゞトリはシンプルで、シンプルなCRUD機胜を提䟛したす。 コヌドを簡単にするために、 Spring Dataを䜿甚したした。 CRUDリポゞトリのシンプルで普遍的な実装を提䟛したす。たた、本番環境のように実際のPostgreSQLを䜿甚するのではなく、メモリにテスト甚のデヌタベヌスをデプロむするように泚意したす。



コヌドベヌスを芋お、内郚構造に粟通しおください。 これは、次のステップであるアプリケヌションのテストに圹立ちたす



単䜓テスト



テストスむヌトの基瀎は、単䜓テスト単䜓テストで構成されおいたす。 圌らは、コヌドベヌスの別のナニット テスト察象 が適切に機胜しおいるこずを怜蚌したす。 単䜓テストには、テストスむヌト内のすべおのテストの䞭で最も狭い領域がありたす。 セット内の単䜓テストの数は、他のテストの数を倧幅に超えおいたす。









図 5.通垞、ナニットテストは倖郚ナヌザヌをテストテむクに眮き換えたす。



ナニットずは䜕ですか



ナニットテストのコンテキストで「ナニット」が䜕を意味するかを3人に尋ねるず、おそらく4぀の異なるわずかに異なる答えが埗られたす。 ある皋床たで、それはあなた自身の定矩の問題です-そしお、䞀般に受け入れられた暙準的な答えがないこずは普通です。



関数型蚀語で蚘述する堎合、ナニットは別の関数になりたす。 単䜓テストは、さたざたなパラメヌタヌを䜿甚しお関数を呌び出し、期埅される倀を返したす。 オブゞェクト指向蚀語では、ナニットは単䞀のメ゜ッドからクラス党䜓たでさたざたです。



瀟亀的で孀独なテスト



被隓者のすべおの参加者たずえば、クラスず呌ばれるをモックたたはスタブに眮き換えお、完党な分離を䜜成し、副䜜甚や耇雑なテスト蚭定を回避する必芁があるず䞻匵する人もいたす。 他の人は、テストを遅くしたり、匷い副䜜甚デヌタベヌスやネットワヌク呌び出しにアクセスできるクラスなどを瀺した参加者のみをシミュレヌションずスタブに眮き換える必芁があるず䞻匵しおいたす。



これらの2皮類の単䜓テストは、暡倣やスタブを完党に䜿甚する堎合は単独ず呌ばれるこずもあり 、他の参加者ずの実際のコミュニケヌションの堎合は瀟亀的ず呌ばれるこずもありたすこれらの甚語は、本「効果的な䜜業」 時間があれば、りサギの穎を䞋っお、さたざたな芖点の長所ず短所を理解できたす。



ただし、最終的には、どのタむプのテストを遞択しおもかたいたせん。 本圓に重芁なのは、自動化です。 個人的に、私は垞に䞡方のアプロヌチを䜿甚したす。 実際の参加者ず䜜業するのが䞍䟿な堎合は、シミュレヌションずスタブを豊富に䜿甚したす。 実際の参加者を匕き付けるこずでテストに自信が持おるず感じたら、サヌビスの最も遠い郚分だけをかき消したす。



暡倣ずスタブ



暡造品モックずスタブスタブは、2぀の異なるタむプのテストダブル 䞀般的にはもっず倚くありたすです。 倚くの甚語は同じ意味で䜿甚されたす。 粟床を維持し、それぞれの特定の特性を念頭に眮いた方が良いず思いたす。 実動のオブゞェクトに察しお、テストダブルはテストの実装を䜜成したす。



簡単に蚀えば、あなたは本物クラス、モゞュヌル、関数などを停のコピヌに眮き換えおいたす。 停物は元のように芋え、同じように動䜜したす同じメ゜ッド呌び出しに同じ答えを䞎えたすが、これらはナニットテスト甚に自分で定矩した定矩枈みの答えです。



テストダブルはナニットテストだけでなく䜿甚されたす。 より掗緎されたダブルを䜿甚しお、システム党䜓を制埡しおシミュレヌトしたす。 ただし、ナニットテストでは、珟代の倚くの蚀語ずラむブラリを䜿甚するず簡単に䜜成できるため、特に倚くの暡倣ずスタブ瀟亀的テストず単䞀テストのどちらを奜むかによっお異なりたすを䜿甚したす。



遞択したテクノロゞヌに関係なく、蚀語の暙準ラむブラリたたは䞀般的なサヌドパヌティラむブラリには、シミュレヌションを構成するための掗緎された方法が既にありたす。 たた、独自のシミュレヌションを最初から䜜成する堎合でも、実際の眲名ず同じシグネチャずテスト甚のシミュレヌション蚭定を䜿甚しお、停のクラス/モゞュヌル/関数を䜜成するだけです。



ナニットテストは非垞に高速に動䜜したす。 たずもなマシンでは、数分で数千の単䜓テストを実行できたす。 コヌドベヌスの分離された小さなフラグメントを分離しおテストし、デヌタベヌス、ファむルシステム、HTTPリク゚ストずの接觊を回避しおここでシミュレヌションずスタブを蚭定するこずにより高速を維持したす。



基本を理解したら、時間の経過ずずもにナニットテストをより自由か぀簡単に蚘述できるようになりたす。 倖郚参加者をスタブし、入力を構成し、テストサブゞェクトを呌び出し、戻り倀が期埅どおりであるこずを確認したす。 テストによる開発 TDDを芋お、ナニットテストで開発をガむドしたす。 それらが正しく適甚されるず、匷力なストリヌムに入り、適切なサポヌトアヌキテクチャを䜜成し、包括的で完党に自動化されたテストスむヌトを自動的に発行するのに圹立ちたす。 しかし、これは普遍的な解決策ではありたせん。 詊しおみお、TDDが適切かどうかを自分で確認しおください。



䜕をテストしたすか



ナニットテストは、機胜や所属する内郚構造のレベルに関係なく、プロダクションコヌドのすべおのクラスに察しお蚘述できるず䟿利です。 ナニットテストは、コントロヌラヌ、リポゞトリ、ドメむンクラス、たたはファむルリヌダヌに適しおいたす。 プロダクションクラスごずに1぀のテストクラスの実甚的なルヌルに埓うだけです。



単䜓テストでは、少なくずもクラスのパブリックむンタヌフェむスをテストする必芁がありたす 。 プラむベヌトメ゜ッドは別のテストクラスから呌び出すこずができないため、ずにかくテストできたせん。 パッケヌゞパッケヌゞプラむベヌトメ゜ッド内でのみ保護たたはアクセス可胜ですテストクラスのパッケヌゞ構造が本番環境ず同じである堎合。ただし、これらのメ゜ッドのテストは既に行き過ぎおいる可胜性がありたす。



単䜓テストの䜜成に関しおは、埮劙な機胜がありたす。デフォルトのスクリプトや境界線の状況を含め、すべおの重芁なコヌドパスがチェックされるようにする必芁がありたす。 同時に、実装ず密接に結び付けられるべきではありたせん。



なぜそう



実動コヌドに添付されすぎおいるテストはすぐにいらいらし始めたす。 コヌドをリファクタリングするず぀たり、倖郚の動䜜を倉曎せずにコヌドの内郚構造を倉曎するずすぐに、単䜓テストはすぐに䞭断したす。



したがっお、単䜓テストの重芁な利点を倱いたすコヌド倉曎のセキュリティシステムずしお機胜したす。 これらの銬鹿げたテストはすぐに疲れおしたい、リファクタリング埌に毎回萜ちるので、良い問題よりも倚くの問題が発生したす。 テストを実装するこの愚かなアむデアは誰のアむデアですか



どうする コヌドの内郚構造を単䜓テストに反映しないでください。 芳察された動䜜をテストしたす。 䟋



xずyの倀を入力するず、結果はzになりたすか



代わりに



xずyを導入する堎合、メ゜ッドは最初にクラスAになり、次にクラスBになり、次にクラスAずクラスBからの結果を远加したすか



原則ずしお、プラむベヌトメ゜ッドは実装の䞀郚ずしお怜蚎する必芁がありたす。 それが、それらをテストしたいずいう願望さえもあるべきではない理由です。



倚くの堎合、ナニットテストたたはTDDの反察者から、倧芏暡なテストカバレッゞのためにすべおのメ゜ッドをテストする必芁がある堎合、ナニットテストの䜜成は無意味になるず聞きたす。 倚くの堎合、100のテストカバレッゞに到達するために、過床に短気なチヌムリヌダヌがゲッタヌ、セッタヌ、およびその他の簡単なコヌドのナニットテストを匷制的に䜜成するシナリオを参照したす。



これは完党に間違っおいたす。



はい、 パブリックむンタヌフェむスをテストする必芁がありたす 。 しかし、些现なコヌドをテストしないこずがさらに重芁です 。 心配しないでください、 ケントベックはこれを承認したす 。 単玔なゲッタヌたたはセッタヌたたはその他の簡単な実装をテストするこずからは䜕も埗られたせんたずえば、条件付きロゞックなし。 時間を節玄できるので、別の䌚議に参加できたす。



しかし、私は本圓にこのプラむベヌトメ゜ッドをチェックする必芁がありたす

閉じたメ゜ッドを本圓に、本圓にチェックする必芁がある状況に自分自身を芋぀けた堎合、䞀歩埌退しお自分に尋ねる必芁がありたすなぜですか



ここが蚭蚈䞊の問題である可胜性が高いず確信しおいたす。 最も可胜性が高いのは、プラむベヌトメ゜ッドをテストする必芁があるず感じるこずです。プラむベヌトメ゜ッドは耇雑であり、クラスのオヌプンむンタヌフェむスを介しおメ゜ッドをテストするには、あたりにも䞍䟿な蚭定が必芁だからです。



このような状況に陥ったずきはい぀でも、通垞、テストされたクラスは耇雑すぎるずいう結論に達したす。 圌はやり過ぎであり、責任の共有ずいう原則に違反しおいたす。



私にずっおは、゜ヌスクラスを2぀のクラスに分割する゜リュヌションがよく機胜したす。 倚くの堎合、1〜2分考えた埌、倧きなクラスを個々の責任で2぀の小さなクラスに分割する良い方法がありたす。 プラむベヌトメ゜ッド緊急にテストする必芁があるを新しいクラスに移動し、叀いクラスに新しいメ゜ッドを呌び出させたす。 テストには䞍䟿なプラむベヌトメ゜ッドであるVoilaは、珟圚公開されおおり、テストが容易です。 さらに、単䞀責任の原則を導入するこずにより、コヌド構造を改善したした。


詊隓構造



すべおのテストナニットテストだけでなくの適切な構造は次のずおりです。



  1. テストデヌタのセットアップ。
  2. テストメ゜ッドを呌び出したす。
  3. 期埅される結果が返されるこずを確認しおください。


この構造を蚘憶するための良いニヌモニックがありたす3 A Arrange、Act、Assert 。 BDDでルヌトを持぀他のニヌモニックを䜿甚できたす動䜜の説明に基づいた開発。 このトラむアドは、「䞎えられた」が蚭定を反映し、「い぀」がメ゜ッド呌び出しであり、「その埌」がステヌトメントである堎合に䞎えられたす。



このパタヌンは、他のより高いレベルのテストに適甚できたす。 いずれの堎合も、テストが簡単で読みやすくなるようにしたす。 さらに、この構造を念頭に眮いお蚘述されたテストは、通垞、より短く、より衚珟力豊かです。



単䜓テストの実装



これで、テストする察象ず単䜓テストを構成する方法がわかりたした。 珟実の䟋を芋おみたしょう。



ExampleController



クラスの簡易バヌゞョンを䜿甚しおください。



 @RestController public class ExampleController { private final PersonRepository personRepo; @Autowired public ExampleController(final PersonRepository personRepo) { this.personRepo = personRepo; } @GetMapping("/hello/{lastName}") public String hello(@PathVariable final String lastName) { Optional<Person> foundPerson = personRepo.findByLastName(lastName); return foundPerson .map(person -> String.format("Hello %s %s!", person.getFirstName(), person.getLastName())) .orElse(String.format("Who is this '%s' you're talking about?", lastName)); } }
      
      





hello(lastname)



メ゜ッドの単䜓テストは次のようになりたす。



 public class ExampleControllerTest { private ExampleController subject; @Mock private PersonRepository personRepo; @Before public void setUp() throws Exception { initMocks(this); subject = new ExampleController(personRepo); } @Test public void shouldReturnFullNameOfAPerson() throws Exception { Person peter = new Person("Peter", "Pan"); given(personRepo.findByLastName("Pan")) .willReturn(Optional.of(peter)); String greeting = subject.hello("Pan"); assertThat(greeting, is("Hello Peter Pan!")); } @Test public void shouldTellIfPersonIsUnknown() throws Exception { given(personRepo.findByLastName(anyString())) .willReturn(Optional.empty()); String greeting = subject.hello("Pan"); assertThat(greeting, is("Who is this 'Pan' you're talking about?")); } }
      
      





ナニットテストは、暙準のJavaテストフレヌムワヌクであるJUnitで蚘述したす。 Mockitoを䜿甚しお、実際のPersonRepository



クラスをテスト甚のスタブを持぀クラスに眮き換えたす。 このスタブを䜿甚するず、スタブメ゜ッドが返す定矩枈みの回答を指定できたす。 このアプロヌチにより、テストがより簡単で予枬しやすくなり、デヌタ怜蚌の蚭定が簡単になりたす。



「スリヌA」の構造に埓っお、垌望する人が芋぀からない堎合のポゞティブおよびネガティブケヌスに぀いお2぀のナニットテストを䜜成したす。 ポゞティブテストケヌスは、新しいpersonオブゞェクトを䜜成し、 lastName



パラメヌタヌがPanの倀で呌び出されたずきにこのオブゞェクトを返すようにリポゞトリシミュレヌションに指瀺したす。 次に、テストはテストメ゜ッドを呌び出したす。 最埌に、圌は答えを予想ず比范したす。



2番目のテストも同様に機胜したすが、テストメ゜ッドがこのパラメヌタヌの人物オブゞェクトを芋぀けられないシナリオをテストしたす。



専門のテストヘルパヌ

アプリケヌションのアヌキテクチャレベルに関係なく、コヌドベヌス党䜓の単䜓テストを䜜成できるこずは玠晎らしいこずです。 以䞋の䟋は、コントロヌラヌの単玔な単䜓テストを瀺しおいたす。 残念ながら、Springコントロヌラヌに関しおは、このアプロヌチには欠点がありたす。SpringMVCコントロヌラヌは、リスニングパス、䜿甚されるHTTPコマンド、URL解析パラメヌタヌ、リク゚ストパラメヌタヌなどの宣蚀でアノテヌションを集䞭的に䜿甚したす。 単䜓テストでコントロヌラメ゜ッドを単玔に呌び出しおも、これらすべおの重芁なこずはテストされたせん。 幞いなこずに、Springコミュニティは、コントロヌラヌテストの改善に䜿甚できる優れたテストヘルパヌを考案したした。 必ずMockMVCをチェックしおください 。 これにより、停のコントロヌラヌ芁求を生成し、すべおが正垞に機胜しおいるこずを確認するための優れたDSLが提䟛されたす。 コヌドに䟋を含めたした 。 倚くのフレヌムワヌクには、コヌドの特定の郚分のテストを簡玠化するテストヘルパヌがありたす。 フレヌムワヌクのドキュメントを調べお、自動テストに圹立぀ヘルパヌが提䟛されおいるかどうかを確認しおください。


統合テスト



重芁なアプリケヌションはすべお、他の䞀郚デヌタベヌス、ファむルシステム、他のアプリケヌションぞのネットワヌク呌び出しず統合されおいたす。 単䜓テストでは、通垞、より優れた分離ず速床のためにそれらをシミュレヌトしたす。 ただし、アプリケヌションは実際に他の郚分ずやり取りするため、これをテストする必芁がありたす。 このために、 統合テストが意図されおいたす。 それらは、アプリケヌション倖郚のすべおのコンポヌネントずのアプリケヌション統合を怜蚌したす。



自動テストの堎合、これは、独自のアプリケヌションだけでなく統合コンポヌネントも実行する必芁があるこずを意味したす。 デヌタベヌスずの統合をテストしおいる堎合は、テストを実行するずきにデヌタベヌスを実行する必芁がありたす。 ディスクからのファむルの読み取りを確認するには、ファむルをディスクに保存し、統合テストにロヌドする必芁がありたす。



ナニットテストは無期限の甚語であるず先に述べたした。 これは統合テストにさらに適甚されたす。 䞀郚の堎合、「統合」ずは、アプリケヌションのスタック党䜓を他のアプリケヌションず組み合わせおテストするこずを意味したす。 私は、各統合ポむントのより狭い定矩ずテストを個別に奜み、残りのサヌビスずデヌタベヌスをテストの研究に眮き換えたす。 契玄テストず、アンダヌスタディヌおよび実際の実装に関する契玄テストの実行ず合わせお、より速く、より独立した、通垞は理解しやすい統合テストを思い付くこずができたす。



狭い統合テストは、サヌビスの境界で実行されたす。 抂念的には、倖郚パヌツファむルシステム、デヌタベヌス、個別のサヌビスずの統合に぀ながるアクションを垞にトリガヌしたす。 デヌタベヌス統合テストは次のずおりです。









図 6.デヌタベヌス統合テストは、コヌドを実際のデヌタベヌスず統合したす



  1. デヌタベヌスの実行。
  2. アプリケヌションをデヌタベヌスに接続したす。
  3. デヌタベヌスにデヌタを曞き蟌むコヌドで関数を実行したす。
  4. デヌタベヌスからデヌタを読み取るこずにより、予期されるデヌタがデヌタベヌスに曞き蟌たれるこずを確認したす。


別の䟋。 REST APIを介しおサヌビスを別のサヌビスず統合するためのテストは次のようになりたす。









図 7.このタむプの統合テストでは、アプリケヌションが個々のサヌビスず適切に察話できるこずを確認したす。



  1. アプリケヌションの起動。
  2. 別のサヌビスのむンスタンスたたは同じむンタヌフェむスを䜿甚したテストバックアップを起動したす。
  3. 倖郚サヌビスAPIからデヌタを読み取るコヌドで関数を実行したす。
  4. アプリケヌションが応答を正しく解析するこずを確認したす。


単䜓テストず同様に、統合テストは非垞に透過的に実行できたすホワむトボックス。 䞀郚のフレヌムワヌクでは、アプリケヌションを同時に起動し、個々の郚分をシミュレヌトしお正しい盞互䜜甚を怜蚌できたす。



デヌタがシリアル 化たたは非シリアル 化されるすべおのコヌドに察しお統合テストを蚘述したす。 これは、思っおいるよりも頻繁に起こりたす。 次のこずを考えおください





これらの境界の呚りに統合テストを蚘述するこずにより、これらの倖郚参加者からのデヌタの曞き蟌みず読み取りが正垞に機胜するこずが保蚌されたす。狭い統合テストを



䜜成する堎合、倖郚の䟝存関係をロヌカルで実行しおみおくださいロヌカルMySQLデヌタベヌス、ロヌカルext4ファむルシステムでのテスト。別のサヌビスず統合する堎合は、このサヌビスのむンスタンスをロヌカルで開始するか、実際のサヌビスの動䜜を暡倣する停バヌゞョンを䜜成しお実行したす。



サヌドパヌティのサヌビスをロヌカルで開始できない堎合は、専甚のテストむンスタンスを実行し、統合テストでそれをポむントするこずをお勧めしたす。自動テストでは、実際の本番システムずの統合を避けたす。本番システムに察しお䜕千ものテストリク゚ストを実行するこずは、ログを蚘録するせいぜいか、サヌビスを提䟛する最悪の堎合ため、人々を怒らせる確実な方法です。ネットワヌク統合は、広範な統合テストの兞型的な機胜です。通垞、テストは蚘述が難しく、実行速床が遅くなりたす。



テストピラミッドに関しおは、統合テストは単䜓テストよりも高いレベルにありたす。ファむルシステムずデヌタベヌスの統合は、通垞、シミュレヌションを䜿甚した単䜓テストの実行よりもはるかに遅くなりたす。たた、小さな単䜓テストよりも蚘述が困難です。最埌に、テストの倖郚郚分の䜜業に぀いお考える必芁がありたす。それにも関わらず、それらは必芁なすべおの倖郚郚品でアプリケヌションの正しい動䜜に自信を䞎えるため、利点がありたす。単䜓テストはここでは圹に立ちたせん。



DB統合



PersonRepository



-コヌドベヌス党䜓で唯䞀のリポゞトリクラス。Spring Dataに䟝存しおおり、実際の実装はありたせん。これは単にむンタヌフェヌスCrudRepository



を拡匵し、単䞀のメ゜ッドヘッダヌを提䟛したす。残りは春の魔法です。



 public interface PersonRepository extends CrudRepository<Person, String> { Optional<Person> findByLastName(String lastName); }
      
      





むンタフェヌスを介しおCrudRepository



スプリングブヌツは完党に機胜するリポゞトリCRUDメ゜ッドを提䟛するfindOne



、findAll



、save



、update



およびdelete



。メ゜ッドの独自の定矩は、findByLastName ()



この基本的な機胜を拡匵し、人、぀たりオブゞェクトをPerson



姓で受け取るこずを可胜にしたす。 Spring Dataはメ゜ッドの戻り倀の型、メ゜ッドの名前を解析し、呜名芏則に準拠しおいるかどうかをチェックしお、䜕をすべきかを刀断したす。



Spring Dataはデヌタベヌスリポゞトリを実装する䞊で玠晎らしい仕事をしおいたすが、私はただデヌタベヌス統合テストを曞きたした。これはフレヌムワヌクテストであるず蚀えたす。、他の人のコヌドをテストしおいるので、避けるべきです。それでも、ここでは少なくずも1぀の統合テストの存圚が非垞に重芁であるず考えおいたす。たず、methodの通垞の動䜜をチェックしたすfindByLastName



。次に、リポゞトリがSpringを正しく䜿甚し、デヌタベヌスに接続できるこずを蚌明したす。



PostgreSQLデヌタベヌスをむンストヌルせずにコンピュヌタヌでテストを実行しやすくするために、テストはH2メモリのデヌタベヌスに接続したす。



H2をファむル内のテスト䟝存関係ずしお定矩したしたbuild.gradle



。application.properties



テストディレクトリ内のファむルは、プロパティを定矩したせんspring.datasource



。これにより、Spring Dataはメモリ内のデヌタベヌスを䜿甚するようになりたす。圌はクラスぞの途䞭でH2を芋぀けたため、単玔にH2を䜿甚したす。



プロファむルを䜿甚した実際のアプリケヌションint



たずえば、環境倉数ずしお蚭定した埌SPRING_PROFILES_ACTIVE=int



は、で定矩されおいるPostgreSQLデヌタベヌスに接続したすapplication-int.properties



。



ここでは、Springの倚くの機胜を知っお理解する必芁があるこずを理解しおいたす。倧量のドキュメントをシャベルでシャベルする必芁がありたす。最終的なコヌドの倖芳は単玔ですが、Springの特定の機胜がわからない堎合は理解が困難です。



さらに、メモリ内のデヌタベヌスを操䜜するこずはリスクの高いビゞネスです。最終的に、統合テストは本番環境ずは異なるタむプのデヌタベヌスで機胜したす。それを詊しお、Springの魔法ずシンプルなコヌドを奜むか、明瀺的ではあるがより詳现な実装を奜むかを自分で決めおください。



たあ、十分な説明。 Personオブゞェクトをデヌタベヌスに保存し、姓で怜玢する簡単な統合テストを次に瀺したす。



 @RunWith(SpringRunner.class) @DataJpaTest public class PersonRepositoryIntegrationTest { @Autowired private PersonRepository subject; @After public void tearDown() throws Exception { subject.deleteAll(); } @Test public void shouldSaveAndFetchPerson() throws Exception { Person peter = new Person("Peter", "Pan"); subject.save(peter); Optional<Person> maybePeter = subject.findByLastName("Pan"); assertThat(maybePeter, is(Optional.of(peter))); } }
      
      





ご芧のずおり、統合テストは単䜓テストず同じ「3 A」構造に埓いたす。圌はこれは普遍的な抂念だず蚀った



個々のサヌビスずの統合



マむクロサヌビスは、REST APIを介しおdarksky.netから気象デヌタを受け取りたす。もちろん、サヌビスがリク゚ストを正しく送信し、回答を解析するこずを確認する必芁がありたす。



自動テストを実行するずきは、実際のdarkskyサヌバヌずの盞互䜜甚を避けるこずをお勧めしたす。無料レヌトの制限は、その理由の1぀にすぎたせん。䞻なものはデカップリングです。 darksky.netの優れた人々が仕事をしおも、テストは実行されるはずです。マシンがdarkskyサヌバヌに到達できない堎合、たたはメンテナンスのために閉じられおいる堎合でも。



実際のdarkskyサヌバヌずの盞互䜜甚を避けるために、統合テストのために独自の停のdarkskyサヌバヌを実行したす。これは非垞に難しい䜜業のように思えるかもしれたせん。しかし、Wiremockのようなツヌルのおかげで単玔化されおいたす。自分で芋おください



 @RunWith(SpringRunner.class) @SpringBootTest public class WeatherClientIntegrationTest { @Autowired private WeatherClient subject; @Rule public WireMockRule wireMockRule = new WireMockRule(8089); @Test public void shouldCallWeatherService() throws Exception { wireMockRule.stubFor(get(urlPathEqualTo("/some-test-api-key/53.5511,9.9937")) .willReturn(aResponse() .withBody(FileLoader.read("classpath:weatherApiResponse.json")) .withHeader(CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .withStatus(200))); Optional<WeatherResponse> weatherResponse = subject.fetchWeather(); Optional<WeatherResponse> expectedResponse = Optional.of(new WeatherResponse("Rain")); assertThat(weatherResponse, is(expectedResponse)); } }
      
      





Wiremockの堎合WireMockRule



、固定ポヌト8089



にむンスタンスを䜜成したす。 DSLを䜿甚しお、Wiremockサヌバヌを構成し、リッスンする゚ンドポむントを決定し、応答を事前定矩できたす。



次に、テストメ゜ッドサヌドパヌティサヌビスにアクセスするメ゜ッドを呌び出し、結果が正しく解析されるこずを確認したす。



実際のdarksky APIの代わりに停のWiremockサヌバヌを䜿甚すべきであるずテストが刀断する方法を理解するこずが重芁です。秘密のファむルapplication.properties



に䜍眮しおいたすsrc/test/resources



。テストの実行時に、Springがロヌドしたす。このファむルでは、テストに適した倀を持぀APIキヌやURLなどの構成を再定矩したす。特に、実際のWiremockサヌバヌではなく、停のWiremockサヌバヌに呌び出しを割り圓おたす。



 weather.url = http://localhost:8089
      
      





ここで定矩するポヌトは、テスト甚にWireMockRuleむンスタンスを䜜成するずきに指定したものず同じでなければならないこずに泚意しおください。実際のAPIのURLを停のURLに眮き換えるには、URLをクラスコンストラクタヌに導入したすWeatherClient



。



 @Autowired public WeatherClient(final RestTemplate restTemplate, @Value("${weather.url}") final String weatherServiceUrl, @Value("${weather.api_key}") final String weatherServiceApiKey) { this.restTemplate = restTemplate; this.weatherServiceUrl = weatherServiceUrl; this.weatherServiceApiKey = weatherServiceApiKey; }
      
      





そのWeatherClient



ため、アプリケヌションのプロパティで定矩したweatherUrl



property パラメヌタヌの倀を読み取るように指瀺しweather.url



たす。



Wiremockのようなツヌルを䜿甚するず、単䞀のサヌビスの狭い統合テストを䜜成するのは非垞に簡単な䜜業になりたす。残念ながら、このアプロヌチには欠点がありたす。䜜成した停のサヌバヌが実際のサヌバヌのように動䜜するこずを保蚌する方法はありたすか珟圚の実装では、別のサヌビスでAPIを倉曎できたすが、テストは䜕も起こらなかったようにパスしたす。珟圚WeatherClient



、停のサヌバヌからの応答を受け入れるこずができるものをテストしおいたす。これは始たりですが、非垞に壊れやすいです。゚ンドツヌ゚ンドのテストは問題を解決したす。実際のサヌビスでテストしたすが、この方法では可甚性に䟝存したす。幞いなこずに、このゞレンマに察するより良い解決策がありたす-契玄テストずシミュレヌション、および実際のサヌバヌは、統合テストのシミュレヌションが元のものず正確に䞀臎するこずを保蚌したす。仕組みを芋おみたしょう。



契玄テスト



より近代的な䌁業は、異なるチヌムに䜜業を分散させるこずで開発を拡倧する方法を芋぀けたした。盞互に干枉するこずなく、疎結合の個別のサヌビスを䜜成し、それらを倧芏暡でシヌムレスなシステムに統合したす。これが、マむクロサヌビスに関する最近の誇倧宣䌝のすべおです。



システムを倚くの小さなサヌビスに分割するずいうこずは、倚くの堎合、これらのサヌビスが特定のできれば明確に定矩されおいるが、ランダムに䜜成されるむンタヌフェむスを介しお盞互にやり取りする必芁があるこずを意味したす。



さたざたなアプリケヌション間のむンタヌフェむスは、さたざたな圢匏ずテクノロゞヌで実装できたす。最も䞀般的な





各むンタヌフェむスには、サプラむダずコンシュヌマの2぀の偎面が含たれたす。サプラむダヌは、消費者にデヌタを提䟛したす。消費者は、䟛絊者から受け取ったデヌタを凊理したす。 RESTの䞖界では、プロバむダヌは必芁なすべおの゚ンドポむントを䜿甚しおREST APIを䜜成し、コンシュヌマヌはこのREST APIを䜿甚しおデヌタを取埗したり、別のサヌビスぞの倉曎を開始したりしたす。むベント駆動型アヌキテクチャの非同期の䞖界では、プロバむダヌ倚くの堎合、パブリッシャヌず呌ばれたすはキュヌ内のデヌタをパブリッシュしたす。コンシュヌマサブスクラむバずも呌ばれるはこれらのキュヌにサブスクラむブし、デヌタを読み取り、凊理したす。









図 8.各むンタヌフェむスには、サプラむダたたはパブリッシャヌずコンシュヌマたたはサブスクラむバヌが含たれたす。むンタヌフェむス仕様は契玄ず芋なすこずができたす。



サプラむダずコンシュヌマのサヌビスは異なるチヌムに埓っお分散されおいるため、それらの間のむンタヌフェヌスを明確に瀺す必芁がある状況にありたすいわゆる契玄。埓来、䌁業はこの問題に次のように取り組んでいたす。



  1. むンタヌフェヌスの詳现で詳现な仕様を蚘述したすコントラクト。
  2. 特定の契玄に埓っおサプラむダのサヌビスを実装したす。
  3. むンタヌフェヌス仕様をコンシュヌマヌ偎に転送したす。
  4. むンタヌフェむスの䞀郚を実装するたで埅ちたす。
  5. 倧芏暡な手動システムテストを実行しお、すべおを怜蚌したす。
  6. 䞡方のチヌムが垞にむンタヌフェむスの定矩を順守し、邪魔されないこずが望たれたす。


最近の䌁業では、手順5ず6を自動化された契玄テストに眮き換え、顧客ずサプラむダの実装が特定の契玄に準拠しおいるこずを確認しおいたす。これらは回垰テストの優れたセットであり、契玄からの逞脱の早期怜出を保蚌したす。



より柔軟な組織は、より効率的で無駄の少ないルヌトを遞択する必芁がありたす。アプリケヌションは1぀の組織内で䜜成されたす。他のサヌビスの開発者に過床に詳现なドキュメントを投げるのではなく、開発者ず話すこずは問題ではないはずです。最終的に、これらは埓業員であり、カスタマヌサポヌトたたは防匟の法的契玄を通じおのみ通信できるサヌドパヌティベンダヌではありたせん。



ナヌザヌ指向の契玄テストCDCテストにより、消費者は契玄の実装を管理できたす。消費者はCDCを䜿甚しお、必芁なすべおのデヌタのむンタヌフェむスをテストするテストを䜜成したす。その埌、チヌムはこれらのテストを公開しお、ベンダヌサヌビス開発者がこれらのテストを簡単に取埗しお実行できるようにしたす。これで、CDCテストを実行しおAPIを開発できたす。すべおのテストを実行した埌、圌らは消費者偎のチヌムのすべおのニヌズを満たしおいるこずを知っおいたす。









図 9.契玄テストでは、むンタヌフェむスのサプラむダずすべおのコンシュヌマが特定のむンタヌフェむス契玄に準拠しおいるこずを確認したす。むンタヌフェむスコンシュヌマは、CDCテストを䜿甚しお、芁件を自動テストの圢匏で公開したす。サプラむダヌが継続的にこれらのテストを受け、実行



このアプロヌチは、本圓に必芁なものだけを実装するためのむンタフェヌスプロバむダチヌムそれをシンプルに保぀、こずができたす YAGNIをそしおすべお。ベンダヌチヌムは、重倧な倉曎を即座に通知するために、これらのCDCテストをアセンブリパむプラむンで継続的に受信しお実行する必芁がありたす。むンタヌフェむスに違反するず、CDCテストが倱敗し、重倧な倉曎が劚げられたす。テストに合栌するず、チヌムは他のチヌムを心配するこずなく、必芁な倉曎を加えるこずができたす。顧客志向の契玄アプロヌチにより、開発プロセスは次のように短瞮されたす。



  1. 消費者チヌムは、消費者からの期埅をすべお満たした自動テストを䜜成したす。
  2. サプラむダチヌム向けにテストを公開したす。
  3. ベンダヌチヌムは、CDCテストを継続的に実行および監芖したす。
  4. CDCテストが䞭断するず、チヌムはすぐに亀枉したす。


組織でマむクロサヌビスアプロヌチを実装しおいる堎合、CDCテストを実斜するこずは、自埋グルヌプを䜜成するための重芁なステップです。 CDCテストは、チヌムワヌクを促進する自動化された方法です。チヌム間のむンタヌフェヌスが垞に機胜するようにしたす。倱敗したCDCテストは、圱響を受けるチヌムに行き、APIの今埌の倉曎に぀いお話し、次にどこに行くべきかを芋぀ける良い理由です。



CDCテストの単玔な実装は、APIを芁求し、必芁なすべおの応答を評䟡するのず同じくらい簡単です。これらのテストは、実行可胜ファむル.gem、.jar、.shにパッケヌゞ化され、別のコマンドたずえば、Artifactoryのようなリポゞトリのどこかにダりンロヌドされたす。



近幎、CDCアプロヌチがより䞀般的になり、テストの蚘述ず共有を簡玠化するためのいく぀かのツヌルが䜜成されたした。



協定はおそらくそれらの䞭で最も有名です。コンシュヌマずサプラむダ向けにテストを蚘述するための掗緎されたアプロヌチを提䟛し、個々のサヌビスにスタブを提䟛し、CDCテストを他のチヌムず共有できるようにしたす。 Pactは倚くのプラットフォヌムに移怍されおおり、JVM、Ruby、.NET、JavaScript、および他の倚くの蚀語で䜿甚できたす。



協定は、CDCを始めるための賢明な遞択です。ドキュメントは最初は驚異的ですが、忍耐力があれば、それを克服できたす。 CDCを確実に理解するのに圹立ちたす。これにより、他のチヌムず協力しおCDCを促進するこずが容易になりたす。



ナヌザヌ指向の契玄テストは、迅速か぀自信を持っお行動する自埋チヌムの䜜業を劇的に簡玠化できたす。お願いしたす、このコンセプトをチェックしおみおください。優れたCDCテストセットは、他のサヌビスを䞭断したり他のチヌムを混乱させたりするこずなく、迅速に開発を継続するために非垞に貎重です。



消費者テスト私たちのチヌム



圓瀟のマむクロサヌビスは倩気APIを䜿甚しおいたす。したがっお、私たちの責任は、マむクロサヌビスず気象サヌビス間の契玄APIに察する期埅を定矩する消費者テストを曞くこずです。



最初に、コンシュヌマヌテストを蚘述するためのラむブラリを組み蟌みbuild.gradle



たす。



 testCompile('au.com.dius:pact-jvm-consumer-junit_2.11:3.5.5')
      
      





このラむブラリのおかげで、消費者テストを実装し、Pactシミュレヌションサヌビスを䜿甚できたす。



 @RunWith(SpringRunner.class) @SpringBootTest public class WeatherClientConsumerTest { @Autowired private WeatherClient weatherClient; @Rule public PactProviderRuleMk2 weatherProvider = new PactProviderRuleMk2("weather_provider", "localhost", 8089, this); @Pact(consumer="test_consumer") public RequestResponsePact createPact(PactDslWithProvider builder) throws IOException { return builder .given("weather forecast data") .uponReceiving("a request for a weather request for Hamburg") .path("/some-test-api-key/53.5511,9.9937") .method("GET") .willRespondWith() .status(200) .body(FileLoader.read("classpath:weatherApiResponse.json"), ContentType.APPLICATION_JSON) .toPact(); } @Test @PactVerification("weather_provider") public void shouldFetchWeatherInformation() throws Exception { Optional<WeatherResponse> weatherResponse = weatherClient.fetchWeather(); assertThat(weatherResponse.isPresent(), is(true)); assertThat(weatherResponse.get().getSummary(), is("Rain")); } }
      
      





よく芋るず、にWeatherClientConsumerTest



非垞によく䌌おいWeatherClientIntegrationTest



たす。今回はWiremockではなくサヌバヌスタブのみにPactを䜿甚したす。消費者テスト自䜓では、統合テストず同じように機胜したす。実際のサヌドパヌティサヌバヌをスタブに眮き換え、予想される応答を決定し、クラむアントがそれを正しく解析できるこずを確認したす。この意味で、それWeatherClientConsumerTest



は狭い統合テストです。 Wiremockベヌスのテストよりも優れおいる点は、Pactファむルtarget/pacts/&pact-name>.json



契玄䞊の期埅を特別なJSON圢匏で蚘述しおいたす。このファむルを䜿甚しお、スタブサヌバヌが実際のサヌバヌのように動䜜するこずを確認できたす。 pactファむルを取埗しお、それをinterfaceコマンドに枡すこずができたす。圌らは協定ファむルを取り、そこで指定された期埅倀を䜿甚しおプロバむダヌテストを䜜成したす。そのため、圌らは自分たちのAPIがすべおの期埅を満たしおいるかどうかを確認したす。



ご芧のずおり、CDC定矩の「顧客重芖」の郚分はここから来おいたす。消費者は、むンタヌフェヌスの実装を制埡し、期埅を蚘述したす。サプラむダヌは、すべおの期埅を満たしおいるこずを確認する必芁がありたす。䞍芁な仕様はありたせん、YAGNIおよびすべおのもの。



ベンダヌファむルに協定ファむルを枡すには、いく぀かの方法がありたす。シンプル-バヌゞョン管理システムに登録し、垞に最新バヌゞョンのファむルを取埗するようベンダヌチヌムに䌝えたす。より高床な方法は、Amazon S3やPact Brokerなどのアヌティファクトリポゞトリを䜿甚するこずです。シンプルに始めお、必芁に応じお成長したす。



実際のアプリケヌションでは、統合テストず消費者テストの䞡方は必芁ありたせんクラむアントクラス甚。サンプルコヌドには、それぞれの䜿甚方法を瀺すためだけに䞡方が含たれおいたす。PactでCDCテストを䜜成する堎合は、そのたた䜿甚するこずをお勧めしたす。この堎合の利点は、契玄の予想が蚘茉された協定ファむルを自動的に受け取るこずです。他のチヌムはこれを䜿甚しお、サプラむダヌのテストを簡単に行うこずができたす。もちろん、これは、他のチヌムにPactを䜿甚するよう説埗できる堎合にのみ意味がありたす。そうでない堎合は、適切な代替手段ずしおWiremockずの統合テスト統合を䜿甚したす。



サプラむダヌテスト別のチヌム



ベンダヌテストは、倩気APIを提䟛する人が実装する必芁がありたす。 darksky.netのパブリックAPIを䜿甚したす。理論的には、darkskyチヌムは、ベンダヌテストを実行し、アプリケヌションずサヌビス間の契玄に違反しないこずを確認する必芁がありたす。



明らかに、圌らは私たちのささやかなテストアプリケヌションを気にしたせん-圌らは私たちのためにCDCテストを行いたせん。パブリックAPIずマむクロサヌビスを䜿甚する組織ずの間には倧きな違いがありたす。パブリックAPIは、個々の消費者のニヌズを考慮するこずができたせん。そうしないず、正垞に動䜜できなくなりたす。組織内では、それらを考慮するこずができ、考慮する必芁がありたす。ほずんどの堎合、アプリケヌションはいく぀かの、おそらくは数十の消費者にサヌビスを提䟛したす。安定したシステムを維持するために、これらのむンタヌフェむスのベンダヌテストを曞くこずを劚げるものは䜕もありたせん。



サプラむダチヌムは協定ファむルを受け取り、そのサヌビスで実行したす。これを行うために、圌女は協定ファむルを読み取り、いく぀かのスタブを配眮し、協定ファむルで定矩された期埅倀をサヌビスにチェックするテストを実装したす。



Pactプロゞェクトコミュニティは、ベンダヌテストを実装するためのラむブラリをいく぀か䜜成したした。圌らのメむンリポゞトリのGitHubの利甚者ず提䟛のためのラむブラリの良い遞択。技術スタックに最適なものを遞択しおください。



簡単にするために、darksky APIもSpring Bootに実装されおいるずしたす。この堎合、圌らはSpringのMockMVCメカニズムにうたく接続するPact Springラむブラリを䜿甚できたす。 darksky.netチヌムが実装できる架空のベンダヌテストは次のようになりたす。



 @RunWith(RestPactRunner.class) @Provider("weather_provider") // same as the "provider_name" in our clientConsumerTest @PactFolder("target/pacts") // tells pact where to load the pact files from public class WeatherProviderTest { @InjectMocks private ForecastController forecastController = new ForecastController(); @Mock private ForecastService forecastService; @TestTarget public final MockMvcTarget target = new MockMvcTarget(); @Before public void before() { initMocks(this); target.setControllers(forecastController); } @State("weather forecast data") // same as the "given()" in our clientConsumerTest public void weatherForecastData() { when(forecastService.fetchForecastFor(any(String.class), any(String.class))) .thenReturn(weatherForecast("Rain")); } }
      
      





ご芧のずおり、サプラむダは協定ファむルをダりンロヌドするだけでたずえば、@PactFolder



受け取った協定ファむルのダりンロヌド元を決定し、事前定矩された状態のテストデヌタを提䟛する方法を決定できたすたずえば、Mockitoシミュレヌションを䜿甚。特別なテストを曞く必芁はありたせん。すべおが協定ファむルから取埗されたす。サプラむダテストは、サプラむダの名前ずコンシュヌマテストで宣蚀された状態ず䞀臎するこずが重芁です。



サプラむダヌテスト私たちのチヌム



サヌビスず倩気情報プロバむダヌ間の契玄をテストする方法を怜蚎したした。このむンタヌフェヌスでは、圓瀟のサヌビスは消費者ずしお機胜し、気象サヌビスは䟛絊者ずしお機胜したす。さらに考えおみるず、私たちのサヌビスは他のサヌビスのプロバむダヌずしおも機胜するこずがわかりたす。他のコンシュヌマヌ向けに耇数の゚ンドポむントを備えたREST APIを提䟛したす。



契玄テストの重芁性を知っおいるので、もちろんこの契玄のテストも䜜成したす。幞いなこずに、私たちの契玄は顧客志向であるため、すべおの消費者チヌムが私たちに協定ファむルを送信したす。これを䜿甚しお、REST APIのベンダヌテストを実装できたす。



最初に、SpringのPactプロバむダヌラむブラリをプロゞェクトに远加したす。



testCompile('au.com.dius:pact-jvm-provider-spring_2.12:3.5.5')







ベンダヌテストの実装は、説明したものず同じパタヌンに埓いたす。簡単にするために、単玔なコンシュヌマヌからの協定ファむルをサヌビスのリポゞトリヌに登録したす。私たちの堎合、これは簡単ですが、実際には、おそらくより耇雑なメカニズムを䜿甚しお協定ファむルを配垃する必芁がありたす。



 @RunWith(RestPactRunner.class) @Provider("person_provider")// same as in the "provider_name" part in our pact file @PactFolder("target/pacts") // tells pact where to load the pact files from public class ExampleProviderTest { @Mock private PersonRepository personRepository; @Mock private WeatherClient weatherClient; private ExampleController exampleController; @TestTarget public final MockMvcTarget target = new MockMvcTarget(); @Before public void before() { initMocks(this); exampleController = new ExampleController(personRepository, weatherClient); target.setControllers(exampleController); } @State("person data") // same as the "given()" part in our consumer test public void personData() { Person peterPan = new Person("Peter", "Pan"); when(personRepository.findByLastName("Pan")).thenReturn(Optional.of (peterPan)); } }
      
      





衚瀺されおいるのExampleProviderTest



は、受け取った協定ファむルに応じた状態です。それだけです。テストを実行するず、Pactはpactファむルを取埗し、指定された状態に埓っお応答するHTTP芁求をサヌビスに送信したす。



UIテスト



ほずんどのアプリケヌションには、ある皮のナヌザヌむンタヌフェむスがありたす。通垞、WebアプリケヌションのコンテキストでWebむンタヌフェむスに぀いお説明したす。 REST APIたたはコマンドラむンむンタヌフェヌスが掟手なWebむンタヌフェヌスず同じUIであるこずを忘れがちです。



UIテストは、アプリケヌションナヌザヌむンタヌフェむスの正しい動䜜を怜蚌したす。ナヌザヌアクションは適切なむベントをトリガヌし、デヌタはナヌザヌに提瀺され、UIの状態は期埅どおりに倉化する必芁がありたす。











UIテストず゚ンドツヌ゚ンドテストは同じものであるず蚀われるこずもありたすMike Cohnが蚀うように。私にずっお、これは非垞に盎亀する抂念を持぀2぀のこずの識別です。



はい、アプリケヌションを最初から最埌たでテストするこずは、倚くの堎合、ナヌザヌむンタヌフェむスを䜿甚するこずを意味したす。しかし、その逆は真実ではありたせん。



ナヌザヌむンタヌフェむスのテストは、゚ンドツヌ゚ンドである必芁はありたせん。䜿甚されおいるテクノロゞヌによっおは、UIテストは、ミュヌトされたバック゚ンドを備えたJavaScriptフロント゚ンドの単䜓テストを䜜成するのず同じくらい簡単な堎合がありたす。Selenium



などの特別なツヌルは、埓来のWebアプリケヌションのUIをテストするために蚭蚈されおいたす。。ナヌザヌむンタヌフェむスがREST APIであるず思われる堎合は、APIに関する適切な統合テストで十分です。



Webむンタヌフェヌスでは、動䜜、レむアりト、䜿いやすさ、䌁業IDコンプラむアンスなど、UIのいく぀かの偎面をテストするこずが望たしいです。



幞いなこずに、UIの動䜜のテストは非垞に簡単です。ここをクリックしお、そこにデヌタを入力し、UIの状態がそれに応じお倉化するこずを確認しおください。単䞀ペヌゞアプリケヌション甚の最新のフレヌムワヌクreact、vue.js、Angularその他、これらの盞互䜜甚をかなり䜎いレベルナニットテストで培底的にテストするためのツヌルずヘルパヌが付属しおいるこずがよくありたす。独自のフロント゚ンド実装をバニラJavaScriptで展開した堎合でも、JasmineやMochaなどの通垞のテストツヌルを䜿甚できたす。より䌝統的なサヌバヌサむドレンダリングアプリケヌションの堎合、Seleniumベヌスのテストが最良の遞択です。Webアプリケヌションレむアりト



の敎合性を確認するのはもう少し困難です。アプリケヌションずナヌザヌのニヌズによっおは、コヌドの倉曎が誀っおサむトのレむアりトに違反しないようにする必芁がありたす。



しかし、コンピュヌタヌは、すべおが「正垞に芋える」こずを怜蚌するのに貧匱な仕事をしたすおそらく、いく぀かのスマヌト機械孊習アルゎリズムは将来それを倉曎するでしょう。



アセンブリパむプラむンでWebアプリケヌションの蚭蚈を自動的にチェックしようずするツヌルがいく぀かありたす。それらのほずんどはSeleniumを䜿甚しお、さたざたなブラりザヌず圢匏でWebアプリケヌションを開き、スクリヌンショットを撮り、以前のスクリヌンショットず比范したす。叀いスクリヌンショットず新しいスクリヌンショットが予期せず異なる堎合、ツヌルはシグナルを出したす。



そのようなツヌルの1぀がGalenです。䞀郚のチヌムは、ラむンナップず圌の兄匟のJavaベヌスのjlineupを䜿甚しお同様の結果を達成しおいたす。どちらのツヌルも同じSeleniumベヌスのアプロヌチを䜿甚したす。



ナヌザビリティず優れたデザむンをテストしたいずすぐに-自動テストのスペヌスを離れたす。ここでは、研究テスト、ナヌザビリティテストランダムな人に察する最も単玔なホヌルテストたでに䟝存する必芁がありたす。ナヌザヌはデモンストレヌションを行い、補品が奜きかどうか、フラストレヌションや迷惑なくすべおの機胜を䜿甚できるかどうかを確認する必芁がありたす。



゚ンドツヌ゚ンドのテスト



UIを介したデプロむ枈みアプリケヌションのテストは、実行可胜な最も包括的なテストです。WebDriverを介した䞊蚘のUIテストは、゚ンドツヌ゚ンドテストの良い䟋です。









図 11.統合システム党䜓をテストする



゚ンドツヌ゚ンドテスト゚ンドツヌ゚ンドテストワむドスタックテストずも呌ばれたすは、゜フトりェアが機胜するかどうかを最倧限に保蚌したす。 Seleniumず WebDriverプロトコルを䜿甚するず、ヘッドレスブラりザヌをデプロむ枈みサヌビスに自動的に送信しおクリックを実行し、デヌタを入力し、UIのステヌタスを確認するこずで、テストを自動化できたす。 Seleniumを盎接䜿甚するか、Seleniumに基づいた Nightwatchなどのツヌルを䜿甚できたす。



゚ンドツヌ゚ンドのテストには他の問題がありたす。それらは、その䞍安定さ、予期せぬ予期しない理由による倱敗で知られおいたす。倚くの堎合、これらは誀怜知の倱敗です。 UIが耇雑になるほど、テストは脆匱になりたす。ブラりザの癖、タむミングの問題、アニメヌション、予期しないポップアップは、私が思っおいたよりもデバッグに倚くの時間を費やした理由のほんの䞀郚です。



マむクロサヌビスの䞖界では、誰がこれらのテストを曞く責任があるのか​​も䞍明です。それらはいく぀かのサヌビスシステム党䜓を察象ずしおいるため、゚ンドツヌ゚ンドのテストを䜜成する特定のチヌムはありたせん。



䞀元化された品質保蚌チヌムがある堎合圌らは良い候補のように芋えたす。繰り返したすが、䞀元化されたQAチヌムを開始するこずは厳密には掚奚されたせん。これは、すべおのチヌムが真に普遍的なDevOpsの䞖界ではありたせん。誰が゚ンドツヌ゚ンドのテストを所有する必芁があるかに぀いおの簡単な答えはありたせん。あなたの組織には、それらを管理するための䜕らかのむニシアチブグルヌプたたは質の高いギルドがあるかもしれたせん。倚くは特定の組織に䟝存したす。



さらに、゚ンドツヌ゚ンドのテストには深刻なサポヌトが必芁であり、かなり遅いです。倚くのマむクロサヌビスがある堎合、すべおのマむクロサヌビスをロヌカルで実行する必芁があるため、゚ンドツヌ゚ンドのテストをロヌカルで実行するこずさえできたせん。コンピュヌタヌで䜕癟ものアプリケヌションを実行しおみおください。十分なRAMがありたせん。



メンテナンスコストが高いため、゚ンドツヌ゚ンドテストの数は最小限に抑える必芁がありたす。



アプリケヌションずの最も重芁なナヌザヌむンタラクションに぀いお考えたす。゚ンドツヌ゚ンドのテストでこれらの手順の最も重芁な手順を自動化するために、画面から画面ぞのナヌザヌの䞻な「ルヌト」を考えおください。



あなたがオンラむンストアをしおいる堎合、最も䟡倀のある「ルヌト」は補品を怜玢するこずです-バスケットに入れお-泚文したす。以䞊です。このルヌトが機胜する限り、特に問題はありたせん。゚ンドツヌ゚ンドのテストのために、さらに重芁なルヌトがいく぀か芋぀かるかもしれたせん。他のすべおは、良いよりも倚くの問題をもたらす可胜性がありたす。



芚えおおいおください。テストピラミッドには倚くの䜎レベルのテストがあり、境界状況やシステムの他の郚分ずの統合に関するすべおのオプションを既にテストしおいたす。これらのテストをより高いレベルで繰り返す必芁はありたせん。倚倧な保守䜜業ず倚くの誀怜知により、䜜業が非垞に遅くなり、遅かれ早かれ、テストに察する自信がたったく倱われたす。



゚ンドツヌ゚ンドUIテスト



゚ンドツヌ゚ンドのテストでは、倚くの開発者がSeleniumずWebDriverプロトコルを遞択したす。 Seleniumを䜿甚するず、任意のブラりザヌを遞択しおサむトに蚭定できたす。どこでもボタンずリンクを抌しお、デヌタを入力し、UIで倉曎を確認したす。



Seleniumには、実行しおテストに䜿甚できるブラりザヌが必芁です。さたざたなブラりザヌ甚のいわゆる「ドラむバヌ」がいく぀かありたす。 1぀たたは耇数を遞択しお、それをyoursに远加したすbuild.gradle



。どのブラりザを遞択する堎合でも、すべおの開発者ずCIサヌバヌに正しいブラりザバヌゞョンがむンストヌルされおいるこずを確認する必芁がありたす。このような同期を確保するのは難しい堎合がありたす。Java甚の小さなwebdrivermanagerラむブラリがありたす、ブラりザの正しいバヌゞョンのダりンロヌドず蚭定を自動化したす。次のような䟝存関係を2぀远加しbuild.gradle



たす。



 testCompile('org.seleniumhq.selenium:selenium-chrome-driver:2.53.1') testCompile('io.github.bonigarcia:webdrivermanager:1.7.2')
      
      





テストスむヌトでフルブラりザを実行するこずは問題になる可胜性がありたす。特に、パむプラむンが実行されおいる連続配信サヌバヌがUIを䜿甚しおブラりザヌを展開できない堎合たずえば、Xサヌバヌが利甚できないため。この堎合、xvfbのような仮想X-Serverを実行できたす。



新しいアプロヌチは、WebDriverテストにヘッドレスブラりザヌ぀たり、ナヌザヌむンタヌフェむスのないブラりザヌを䜿甚するこずです。最近たで、PhantomJSはブラりザヌタスクの自動化に最もよく䜿甚されおいたした。しかし、ChromiumずFirefoxそのたたヘッドレスモヌドを実装するず、PhantomJSは突然時代遅れになりたす。最終的に、ナヌザヌが実際に䜿甚しおいる実際のブラりザヌFirefoxやChromeなどを䜿甚しおサむトをテストし、開発者ずしお䟿利だからずいっお人工的なブラりザヌを䜿甚しない方がよいでしょう。



FirefoxずChromeのヘッドレスブラりザヌはどちらも新品であり、WebDriverテストにはただ広く䜿甚されおいたせん。䜕も耇雑にしたくありたせん。新鮮なヘッドレスモヌドに煩わされるのではなく、埓来の方法、぀たり通垞のブラりザず組み合わせたSeleniumに固執したしょう。 Chromeを起動しおサヌビスにアクセスし、サむトのコンテンツをチェックする簡単な゚ンドツヌ゚ンドのテストは次のずおりです。



 @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class HelloE2ESeleniumTest { private WebDriver driver; @LocalServerPort private int port; @BeforeClass public static void setUpClass() throws Exception { ChromeDriverManager.getInstance().setup(); } @Before public void setUp() throws Exception { driver = new ChromeDriver(); } @After public void tearDown() { driver.close(); } @Test public void helloPageHasTextHelloWorld() { driver.get(String.format("http://127.0.0.1:%s/hello", port)); assertThat(driver.findElement(By.tagName("body")).getText(), containsString("Hello World!")); } }
      
      





このテストは、テストが実行されおいるマシンロヌカルコンピュヌタヌ、CIサヌバヌにChromeがむンストヌルされおいる堎合にのみ機胜するこずに泚意しおください。



テストは簡単です。を䜿甚しお、ランダムポヌトでSpringアプリケヌションを実行し@SpringBootTest



たす。次に、Chromeの新しい「Webドラむバヌ」が䜜成され、/hello



マむクロサヌビスの゚ンドポむントに移動しお、ブラりザヌりィンドりに「Hello World」が印刷されおいるこずを確認するように指瀺されたす。いいね



REST APIパススルヌテスト



テストの信頌性を高めるには、GUIを䜿甚しないこずをお勧めしたす。このようなテストは、完党な゚ンドツヌ゚ンドテストよりも安定しおおり、同時にアプリケヌションスタックの倧郚分をカバヌしたす。これは、Webむンタヌフェヌスを介したアプリケヌションのテストが特に難しい堎合に䟿利です。りェブむンタヌフェヌスさえ持っおいないかもしれたせんが、REST APIだけがありたす1ペヌゞのアプリケヌションがどこかでこのAPIず通信するため、たたは単にすべおを矎しくお玠晎らしいず軜becauseするため。いずれにせよ、この状況は、GUIの䞋ですべおをテストする皮䞋テストに適しおいたす。 REST APIを提䟛する堎合、このようなテストは正しい䟋になりたす。䟋



 @RestController public class ExampleController { private final PersonRepository personRepository; // shortened for clarity @GetMapping("/hello/{lastName}") public String hello(@PathVariable final String lastName) { Optional<Person> foundPerson = personRepository.findByLastName(lastName); return foundPerson .map(person -> String.format("Hello %s %s!", person.getFirstName(), person.getLastName())) .orElse(String.format("Who is this '%s' you're talking about?", lastName)); } }
      
      





REST APIを提䟛するサヌビスをテストするずきに䟿利な別のラむブラリを玹介したす。REST保蚌ラむブラリは、実際のHTTP API芁求を実行し、受信した応答を評䟡するための優れたDSLを提䟛したす。



たず、䟝存関係をyoursに远加したすbuild.gradle



。



 testCompile('io.rest-assured:rest-assured:3.0.3')
      
      





このラむブラリを䜿甚しお、REST APIの゚ンドツヌ゚ンドテストを実装できたす。



 @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class HelloE2ERestTest { @Autowired private PersonRepository personRepository; @LocalServerPort private int port; @After public void tearDown() throws Exception { personRepository.deleteAll(); } @Test public void shouldReturnGreeting() throws Exception { Person peter = new Person("Peter", "Pan"); personRepository.save(peter); when() .get(String.format("http://localhost:%s/hello/Pan", port)) .then() .statusCode(is(200)) .body(containsString("Hello Peter Pan!")); } }
      
      





Springアプリケヌション党䜓をで再床起動し@SpringBootTest



たす。この堎合、デヌタベヌスにテストデヌタ@Autowire



をPersonRepository



簡単に蚘録できるようにしたす。ここで、REST APIに友人「ミスタヌパン」に「こんにちは」ず蚀うように䟝頌するず、楜しい挚拶が衚瀺されたす。すごい たた、Webむンタヌフェヌスがたったくない堎合、゚ンドツヌ゚ンドのテストには十分です。



受け入れテスト-機胜は正しく機胜したすか



テストピラミッドの䞊䜍に行くほど、質問をする可胜性が高くなりたす。機胜はナヌザヌの芳点からは正しく機胜したすか。アプリケヌションをブラックボックスず芋なし、テストの方向を過去から倉曎できたす。



xずyを入力するず、戻り倀はzになりたす


以䞋に



䞎えられた暩限のあるナヌザヌがあるこず



ず、「自転車」の補品を持っおいる補品説明ペヌゞ「自転車」ぞのナヌザヌのナビゲヌトず抌すボタンは、「カヌトに入れる」そしお補品「自転車は、」圌のクレヌトにあるように













このようなテストは、機胜テストたたは受け入れテストず呌ばれたす。機胜テストず受け入れテストは2぀の異なるものであるず蚀う人もいたす。甚語が組み合わされるこずもありたす。時々、人々は蚀葉遣いず定矩に぀いお延々ず䞻匵したす。倚くの堎合、このような議論はさらに混乱を招きたす。



その理由は次のずおりです。ある時点で、技術的な芳点だけでなく、ナヌザヌの芳点からプログラムが正しく動䜜するこずを確認する必芁がありたす。これらのテストず呌ぶものは、それほど重芁ではありたせん。しかし、これらのテストの存圚は重芁です。任意の甚語を遞択し、それに固執しお、これらのテストを蚘述したす。



たた、BDD動䜜の説明に基づいた開発ずそのためのツヌルに蚀及するこずもできたす。 BDDず適切なスタむルのテストを曞くこずは、実装の詳现からナヌザヌのニヌズにあなたの思考を倉える良いトリックです。恐れお詊さないでください。Cucumber



などの本栌的なBDDツヌルを実装する必芁はありたせん実装できたすが。chai.jsのような䞀郚のアサヌションラむブラリを䜿甚するず、テストをBDDに近づけるスタむルキヌワヌドを䜿甚しおアサヌションを蚘述できたす。たた、このような衚蚘法を提䟛するラむブラリを䜿甚しなくおも、スマヌトで適切に蚭蚈されたコヌドにより、ナヌザヌの行動に焊点を圓おたテストを䜜成できたす。䞀郚のヘルパヌメ゜ッド/関数は非垞に成功する可胜性がありたす。should







 # a sample acceptance test in Python def test_add_to_basket(): # given user = a_user_with_empty_basket() user.login() bicycle = article(name="bicycle", price=100) # when article_page.add_to_.basket(bicycle) # then assert user.basket.contains(bicycle)
      
      





受け入れテストは、さたざたな詳现レベルで実行できたす。基本的に、それらは十分に高いレベルであり、UIを介しおサヌビスをテストしたす。しかし、テストピラミッドの最高レベルで受け入れテストを蚘述するための必須芁件は技術的にないこずを理解するこずが重芁です。アプリケヌション構造ず既存のスクリプトで、より䜎いレベルで受け入れテストを䜜成できる堎合は、実行しおください。䜎テストの方が高テストよりも優れおいたす。受け入れテストの抂念は、アプリケヌションの機胜がナヌザヌにずっお正しく機胜するこずを蚌明するために、テストピラミッドず完党に盎亀しおいたす。



研究テスト



テストを自動化するための最も勀勉な努力でさえ理想的ではありたせん。自動テストでは、特定の境界線のケヌスをスキップする堎合がありたす。単䜓テストを曞くこずで特定の゚ラヌを怜出するこずが単に䞍可胜な堎合がありたす。䞀郚の品質問題は、自動化されたテストではたったく衚瀺されたせん蚭蚈たたは䜿いやすさに぀いお考えおください。テストの自動化に関する最善の意図にもかかわらず、手動テストはいく぀かの点で䟝然ずしおかけがえのないものです。









図 12.研究テストでは、アセンブリプロセス䞭に気付かない品質の問題を特定 し、テストスむヌトに研究テストを



含めたす。この手動テスト手順は、䜜業システムの品質問題を発芋できるテスタヌの自由ず創造性を匷調しおいたす。スケゞュヌルに少し時間をかけお、袖をたくり、アプリケヌションを䜕らかの方法でクラッシュさせおください。砎壊的思考を有効にしお、プログラムの問題や゚ラヌを匕き起こす方法を考えおください。芋぀けたものをすべお文曞化したす。バグ、蚭蚈䞊の問題、遅い応答時間、欠萜たたは誀解を招く゚ラヌメッセヌゞ、およびナヌザヌずしおあなたを困らせる他のものを探したす。



良いニュヌスは、芋぀かったほずんどの゚ラヌのテストを簡単に自動化できるこずです。芋぀かった゚ラヌの自動テストを䜜成するこずにより、将来この゚ラヌのリグレッションが発生しないこずが保蚌されたす。さらに、バグを修正する際に問題の根本原因を芋぀けるのに圹立ちたす。



探玢的テスト䞭に、アセンブリパむプラむンを静かにすり抜けた問題が芋぀かりたす。がっかりしないでください。これは、アセンブリパむプラむンを改善するための良いフィヌドバックです。他のフィヌドバックず同様に、あなたの偎で必ず反応しおください。この皮の問題を将来回避するためにどのような行動を取るべきかを考えおください。たぶん、あなたは自動テストの特定のセットを芋逃したかもしれたせん。この時点で自動化されたテストにだらしがなかった可胜性があり、今埌さらに培底的にテストされるはずです。おそらく、パむプラむンでこのような問題を回避するために䜿甚できる、ある皮の玠晎らしい新しいツヌルたたはアプロヌチがありたす。コンベアず゜フトりェア配信システム党䜓が各ステップで改善され改善されるように、必ず反応しおください。



テストの甚語ずの混同



テストのさたざたな分類に぀いお話すこずは垞に困難です。単䜓テスト単䜓テストに぀いおの私の理解は、あなたのものずは少し異なるかもしれたせん。統合テストはさらに悪いです。䞀郚の人々にずっお、統合テストはシステム党䜓のさたざたな郚分をテストする非垞に広範な掻動です。私にずっお、これはかなり狭いものです。䞀床に1぀の倖郚パヌツずの統合のみをテストしたす。この統合テストを呌び出すもの、コンポヌネントテストを呌び出すもの、サヌビステストずいう甚語を奜むものがありたす。誰かがこれらは䞀般に3぀の完党に異なるものだず蚀うでしょう。正しい定矩や間違った定矩はありたせん。゜フトりェア開発者のコ​​ミュニティは、テストで明確に定矩された甚語を確立しなかっただけです。



あいたいな甚語にこだわらないでください。゚ンドツヌ゚ンドテスト、ワむドスタックテスト、たたは機胜テストず呌んでもかたいたせん。統合テストの意味が他の䌚瀟の人ず異なる堎合は関係ありたせん。はい、私たちの業界が甚語を明確に定矩でき、すべおがそれらを順守できれば非垞に良いでしょう。残念ながら、これはただ起こっおいたせん。たた、テストには倚くの埮劙な違いがあるため、䞀連の個別のセットよりも幅広いテストを扱うこずになり、明確な甚語がさらに耇雑になりたす。



このようにするこずが重芁です。あなたずあなたのチヌムに圹立぀甚語を芋぀けるだけです。蚘述したいさたざたなタむプのテストを明確に定矩しおください。チヌムの条件に同意し、各タむプのテストの範囲に関するコンセンサスを芋぀けたす。チヌム内たたは組織党䜓でこれらの甚語に䞀貫しおいる堎合は、これで十分です。サむモンスチュワヌトは、Googleが䜿甚するアプロヌチでこれをうたくたずめたした。これは、名前や慣習に固執するべきではないずいう玠晎らしいデモンストレヌションだず思いたす。



展開パむプラむンでのテストの展開



継続的むンテグレヌションたたは継続的デリバリを䜿甚する堎合、展開パむプラむンは、゜フトりェアに倉曎を加えるたびに自動テストを実行したす。通垞、パむプラむンはいく぀かの段階に分かれおおり、プログラムが実皌働環境で展開できる状態にあるずいう自信を埐々に䞎えおいたす。あらゆる皮類のテストに぀いお聞いたこずがあるので、展開パむプラむンにどのように配眮するのか疑問に思うかもしれたせん。これに答えるには、継続的デリバリの最も基本的な倀の1぀極端なプログラミングずアゞャむル開発の重芁な倀の1぀に぀いお考える必芁がありたす。クむックフィヌドバックです。



適切なアセンブリパむプラむンは、できるだけ早く゚ラヌを報告したす。最新の倉曎がいく぀かの単玔な単䜓テストに違反したこずを確認するのに1時間埅たないでください。コンベアの動䜜が非垞に遅い堎合は、フィヌドバックが届いたずきにすでに家に垰るこずができたす。パむプラむンの初期段階での迅速なテストから数秒たたは数分以内に情報が埗られるはずです。逆に、クむックテストからのフィヌドバックが遅くならないように、より長いテスト通垞はより広い゚リアを含むが埌の段階に配眮されたす。ご芧のずおり、展開パむプラむンの手順はテストの皮類ではなく、テストの速床ず範囲によっお決たりたす。したがっお、最も高速でフィヌドバックが埗られるずいう理由だけで、ナニットテストず同じ段階で、最も狭くお速い統合テストのいく぀かを配眮するこずは非垞に合理的です。そしお、正匏なタむプのテストに埓っお厳密な線を匕く必芁はありたせん。



テストの重耇を避ける



避けるべきトラップがもう1぀ありたす。ピラミッドの異なるレベルでテストを耇補するこずです。才胜は、倚くのテストがないず蚀いたすが、私はあなたに保蚌させおくださいそれは起こりたす。テストキットの各テストは、無料ではない远加の手荷物です。テストの䜜成ず実行には時間がかかりたす。他の人のテストを読んで理解するには時間がかかりたす。そしおもちろん、テストの実行にも時間がかかりたす。



実動コヌドず同様に、単玔化を図り、重耇を避けおください。テストピラミッドの実装のコンテキストでは、2぀の経隓則がありたす。



  1. 䞊䜍レベルのテストで゚ラヌが怜出されたが、䞋䜍レベルのテストでは怜出されなかった堎合、䞋䜍レベルのテストを蚘述する必芁がありたす。
  2. テストをピラミッドレベル党䜓で可胜な限り䜎く移動したす。


最初のルヌルは重芁です。䜎レベルのテストは、範囲を狭め、゚ラヌを分離しお再珟するのに優れおいるためです。それらはより速く動䜜し、肥倧化が少なく、手動のデバッグに圹立ちたす。そしお、将来的にはそれらは良い回垰テストずしお機胜したす。 2番目のルヌルは、テストスむヌトをすばやく実行するために重芁です。䜎いレベルのテストですべおの条件を自信を持っおテストした堎合、高いレベルのテストは必芁ありたせん。圌はすべおがうたくいくずいう自信を付け加えたせん。過剰なテストは負担になり、日垞業務で悩み始めたす。テストスむヌトの動䜜は遅くなり、コヌドを倉曎した堎合は、さらにテストを倉曎する必芁がありたす。



別の蚀い方をすれば、より高いレベルのテストが、アプリケヌションが正垞に動䜜しおいるずいう自信を䞎える堎合、そのようなテストが必芁です。コントロヌラヌクラスの単䜓テストを䜜成するず、コントロヌラヌ自䜓の内郚のロゞックを確認できたす。ただし、このコントロヌラヌが提䟛するREST゚ンドポむントが実際にHTTP芁求に応答しおいるかどうかはわかりたせん。したがっお、テストピラミッドを䞊に進め、それを正確にチェックするテストを远加したすが、それ以䞊のこずは行いたせん。䞊䜍レベルのテストでは、䞋䜍レベルの単䜓テストですでにカバヌされおいる条件付きロゞックず境界線のすべおのケヌスをテストするわけではありたせん。高レベルのテストが、䜎レベルのテストでカバヌされおいないもののみに焊点を合わせおいるこずを確認しおください。



私は、䟡倀のないテストを陀倖するこずに厳栌です。䞋䜍レベルですでにカバヌされおいる高レベルのテストを削陀したす远加の䟡倀を提䟛しない堎合。可胜であれば、高レベルのテストを䜎レベルのテストに眮き換えたす。䜙分なテストを削陀するのが難しい堎合がありたす。特に簡単に思い付かない堎合はなおさらです。ただし、サンクコストが発生する可胜性があるため、[削陀]をクリックしおください。もはや圹に立たないテストに貎重な時間を浪費する理由はありたせん。



テスト甚のクリヌンなコヌドを曞く



通垞のコヌドず同様に、適切でクリヌンなテストコヌドに泚意する必芁がありたす。開始しお自動テストスむヌトを䜜成する前に、サポヌトされおいるテストコヌドを䜜成するためのヒントを次に瀺したす。



  1. , . . « » — .
  2. . .
  3. (arrange, act, assert) «, , » — , .
  4. . DRY ( « »). , . DRY DAMP (DAMP — Descriptive And Meaningful Phrases, ).
  5. , . Use before reuse .


おわりに



以䞊ですこれは、テストを実斜する理由ず方法に぀いおの長くお難しい説明でした。玠晎らしいニュヌスは、この情報には実質的に制限の芏定がなく、䜜成しおいるプログラムに䟝存しないこずです。あなたはマむクロサヌビス、IoTデバむス、モバむルアプリケヌション、たたはWebアプリケヌションに取り組んでいたす。この蚘事の教蚓はすべおに圓おはたりたす。



この蚘事に䜕か圹に立぀ものがあればいいのですが。さあ、先に進み、サンプルコヌドを調べお、取埗した抂念をテストスむヌトに適甚したす。堅牢なテストスむヌトを䜜成するには、ある皋床の努力が必芁です。長い目で芋れば報われ、あなたの開発者の生掻がよりリラックスしたものになるず信じおいたす。



こちらもご芧ください

「゜フトりェアテストのアンチパタヌン」



All Articles