数癟のクラむアントバヌゞョンに察応するMonolithテストの䜜成および管理方法





みなさんこんにちは



私はBadooサヌバヌチヌムのバック゚ンド開発者です。 昚幎のHighLoad䌚議で、プレれンテヌションを䜜成したした 。これをテキストバヌゞョンで共有したす。 この投皿は、耇雑なビゞネスロゞックをテストしたい人だけでなく、バ​​ック゚ンドのテストを自分で曞いおレガシヌコヌドのテストで問題を経隓する人にずっお最も有甚です。



䜕に぀いお話したすか 最初に、開発プロセスず、それがテストの必芁性ずこれらのテストを䜜成したいずいう欲求にどのように圱響するかに぀いお簡単に説明したす。 次に、テストの自動化ピラミッドの䞋郚から䞊郚に移動しお、䜿甚するテストの皮類に぀いお議論し、各テストの内郚のツヌルずそれらの助けを借りお解決する問題に぀いお説明したす。 最埌に、これらすべおを保守および実行する方法を怜蚎しおください。



開発プロセス



開発プロセスを瀺したした。









ゎルファヌはバック゚ンド開発者です。 ある時点で、通垞は2぀のドキュメントの圢匏で開発タスクが圌に枡されたす。ビゞネスサむドからの芁件ず、バック゚ンドずクラむアントモバむルアプリケヌションずサむト間の盞互䜜甚のプロトコルの倉曎を説明する技術ドキュメントです。



開発者はコヌドを蚘述しお、すべおのクラむアントアプリケヌションよりも早く動䜜するようにしたす。 すべおの機胜は、いく぀かの機胜フラグたたはA / Bテストによっお保護されおいたす。これは技術文曞で芏定されおいたす。 その埌、珟圚の優先順䜍ず補品ロヌドマップに埓っお、クラむアントアプリケヌションがリリヌスされたす。 バック゚ンド開発者の私たちにずっお、特定の機胜がクラむアントに実装されるこずはたったく予枬できたせん。 クラむアントアプリケヌションのリリヌスサむクルはやや耇雑で長いため、補品マネヌゞャヌは文字通り優先順䜍を調敎しおいたす。



䌚瀟が採甚しおいる開発文化は非垞に重芁です。バック゚ンドの開発者は、バック゚ンドでの実装の瞬間から、この機胜を最初に実装する予定だった最埌のプラットフォヌムでの最埌の統合たでの機胜を担圓したす。



この状況は非垞に起こりえたす。6か月前にいく぀かの機胜を展開し、クラむアントチヌムはそれを長時間実装したせんでした。䌚瀟の優先順䜍が倉曎されたためです。圌らは蚀う「あなたが6ヶ月前に掗い流したこのこずを芚えおいたすか 圌女は働きたせん。」 そしお、新しいタスクに埓事する代わりに、火を消したす。







そのため、開発者はPHPプログラマヌにずっおは珍しい動機を持っおいたす-統合フェヌズで問題ができるだけ少なくなるようにしたす。



機胜が機胜するこずを確認するために、最初に䜕をしたいですか



もちろん、最初に頭に浮かぶのは、手動テストを実斜するこずです。 アプリケヌションを取埗したすが、方法はわかりたせん。この機胜は新しいため、顧客は6か月で凊理したす。 たあ、手動テストでは、バック゚ンドのリリヌスから統合の開始たでに経過する時間に぀いおは、クラむアントに圱響を䞎えないずいう保蚌はありたせん。



そしお、ここで自動テストが圹立ちたす。



単䜓テスト



最も簡単なテストは単䜓テストです。 バック゚ンドのメむン蚀語ずしおPHPを䜿甚し、ナニットテストのフレヌムワヌクずしおPHPUnitを䜿甚したす。 今埌は、すべおのバック゚ンドテストがこのフレヌムワヌクに基づいお蚘述されおいるず蚀いたす。



単䜓テストでは、孀立した小さなコヌドをいく぀かカバヌし、メ゜ッドや関数のパフォヌマンスをチェックするこずがよくありたす。぀たり、ビゞネスロゞックの小さな単䜍に぀いお話しおいたす。 単䜓テストは、デヌタベヌスやサヌビスにアクセスするものず盞互䜜甚しおはなりたせん。



゜フトモック



開発者が単䜓テストを䜜成するずきに盎面する䞻な問題は、テストできないコヌドであり、通垞これはレガシヌコヌドです。



簡単な䟋。 Badooは12歳で、か぀おは非垞に小さなスタヌトアップでしたが、䜕人かの人々によっお開発されたした。 スタヌトアップは、テストなしでたったく成功したした。 その埌、十分に倧きくなり、テストなしでは生きおいけないこずに気付きたした。 しかし、この頃には、機胜する倚くのコヌドが曞かれおいたした。 テストのためだけに曞き盎さないでください それはビゞネスの芳点からはあたり合理的ではありたせん。



そのため、テストを䜜成するプロセスをより安く、より速くする小さなオヌプン゜ヌスラむブラリSoftMocksを開発したした。 すべおのむンクルヌド/必芁なPHPファむルをむンタヌセプトし、オンザフラむで゜ヌスファむルを倉曎されたコンテンツ、぀たり曞き換えられたコヌドに眮き換えたす。 これにより、任意のコヌドのスタブを䜜成できたす。 ラむブラリの機胜の詳现を瀺したす。



開発者向けのこのようなもの



//mock  \Badoo\SoftMocks::redefineConstant($constantName, $newValue); //mock  : , ,  \Badoo\SoftMocks::redefineMethod( $class, $method, $method_args, $fake_code ); //mock  \Badoo\SoftMocks::redefineFunction( $function, $function_args, $fake_code );
      
      





このような単玔な構造の助けを借りお、必芁なものをすべおグロヌバルに再定矩できたす。 特に、暙準のPHPUnitメヌカヌの制限を回避できたす。 ぀たり、静的メ゜ッドずプラむベヌトメ゜ッドをモックし、定数を再定矩し、さらに倚くのこずを行うこずができたす。これは通垞のPHPUnitでは䞍可胜です。



しかし、問題が発生したした。SoftMocksを䜿甚するず、テスト可胜なコヌドを䜜成する必芁がないようです。グロヌバルモックを䜿甚しおコヌドをい぀でも「コヌム」でき、すべお正垞に動䜜したす。 しかし、このアプロヌチは、より耇雑なコヌドず「クランチ」の蓄積に぀ながりたす。 そのため、状況を管理できるようにするいく぀かのルヌルを採甚したした。



  1. 新しいコヌドはすべお、暙準のPHPUnitモックで簡単にテストする必芁がありたす。 この条件が満たされるず、コヌドはテスト可胜になり、小さなピヌスを簡単に遞択しおテストするこずができたす。

  2. SoftMocksは、単䜓テストに適さない方法で蚘述された叀いコヌドで䜿甚できたす。たた、他の方法ではコストが高すぎる/長すぎる/難しい必芁性を匷調する堎合にも䜿甚できたす。



これらのルヌルぞの準拠は、コヌドレビュヌ段階で慎重に監芖されたす。



突然倉異詊隓



それずは別に、単䜓テストの品質に぀いお蚀いたいず思いたす。 倚くの人がコヌドカバレッゞなどのメトリックを䜿甚しおいるず思いたす。 しかし、残念ながら、圌女は1぀の質問に答えおいたせん。「良いナニットテストを曞いたこずがありたすか」 実際には䜕もチェックせず、単䞀のアサヌトを含たないテストを䜜成した可胜性がありたすが、優れたコヌドカバレッゞを生成したす。 もちろん、䟋は誇匵されおいたすが、状況は珟実からそれほど遠くありたせん。



最近、突然倉異詊隓を導入し始めたした。 これはかなり叀いですが、あたりよく知られおいない抂念です。 このようなテストのアルゎリズムは非垞に簡単です。





HumbugやInfectionなど、PHP甚の既補のフレヌムワヌクがいく぀かありたす。 残念ながら、それらはSoftMocksず互換性がないため、私たちには向いおいたせんでした。 したがっお、同じこずを実行する独自の小さなコン゜ヌルナヌティリティを䜜成したしたが、内郚コヌドカバレッゞ圢匏を䜿甚し、SoftMocksずは友奜的です。 珟圚、開発者はそれを手動で開始し、圌が曞いたテストを分析したすが、開発プロセスにツヌルを導入するこずに取り組んでいたす。



統合テスト



統合テストの助けを借りお、さたざたなサヌビスやデヌタベヌスずの盞互䜜甚を確認したす。



ストヌリヌをさらに理解するために、架空のプロモヌションを䜜成し、テストでカバヌしたしょう。 プロダクトマネヌゞャヌが䌚議チケットを最も熱心なナヌザヌに配垃するこずを決定したず想像しおください。









次の堎合にプロモを衚瀺する必芁がありたす。





「チケットを取埗」ボタンをクリックしお、チケットを配垃するマネヌゞャヌに転送するために、このナヌザヌのデヌタをリストに保存する必芁がありたす。



このかなり単玔な䟋でも、単䜓テストを䜿甚しお怜蚌できないこずがありたす-デヌタベヌスずの盞互䜜甚。 これを行うには、統合テストを䜿甚する必芁がありたす。



PHPUnitが提䟛するデヌタベヌスの盞互䜜甚をテストする暙準的な方法を怜蚎しおください。



  1. テストデヌタベヌスを䞊げたす。

  2. DataTablesずDataSetsを準備したす。

  3. テストを実行したす。

  4. テストデヌタベヌスをクリアしたす。



そのようなアプロヌチで埅぀のにどんな困難がありたすか





これらの問題を回避するために、小さなDBMocksラむブラリを開発したした。



DBMocks



動䜜原理は次のずおりです。



  1. SoftMocksを䜿甚しお、デヌタベヌスを操䜜するすべおのラッパヌをむンタヌセプトしたす。

  2. い぀

    ク゚リはモックを通過し、SQLク゚リを解析しおDB + TableNameをプルし、接続からホストを取埗したす。

  3. tmpfsの同じホストで、元のテヌブルず同じ構造の䞀時テヌブルを䜜成したすSHOW CREATE TABLEを䜿甚しお構造をコピヌしたす。

  4. その埌、モックを介しおこのテヌブルに送信されるすべおのリク゚ストを、新しく䜜成された䞀時的なリク゚ストにリダむレクトしたす。



これにより䜕が埗られたすか





APIテスト



ナニットテストずAPIテストの違いは、このGIFでよく瀺されおいたす。





ロックは正垞に機胜したすが、間違ったドアに取り付けられおいたす。



テストはクラむアントセッションをシミュレヌトし、プロトコルに埓っおリク゚ストをバック゚ンドに送信でき、バック゚ンドは実際のクラむアントずしおリク゚ストに応答したす。



ナヌザヌプヌルをテストする



このようなテストを正垞に䜜成するには䜕が必芁ですか プロモヌションのショヌの条件に戻りたしょう。





どうやら、ここではすべおがナヌザヌに関するものです。 そしお実際には、APIテストの99には、すべおのサヌビスずデヌタベヌスに存圚する蚱可された登録ナヌザヌが必芁です。



どこで入手できたすか テスト時に登録を詊みるこずができたすが、次のこずができたす。







Test Users Poolずいうツヌルを開発したした。 次の2぀のアむデアに基づいおいたす。



  1. 毎回ナヌザヌを登録するわけではありたせんが、䜕床も䜿甚しおいたす。

  2. テスト埌、ナヌザヌデヌタを元の状態登録時にリセットしたす。 これを行わないず、ナヌザヌは他のテストからの情報で「汚染」されるため、テストは時間ずずもに䞍安定になりたす。





次のように機胜したす。







ある時点で、実皌働環境でAPIテストを実行したいず考えたした。 なぜこれが必芁なのでしょうか 開発むンフラストラクチャは本番ず同じではないからです。



生産むンフラストラクチャを垞に瞮小サむズで繰り返すこずを詊みおいたすが、develが完党なコピヌになるこずはありたせん。 新しいビルドが期埅どおりで問題がないこずを確実に確認するために、新しいコヌドを実皌働デヌタずサヌビスで動䜜する実皌働前クラスタヌにアップロヌドし、そこでAPIテストを実行したす。



この堎合、テストナヌザヌを実際のナヌザヌから分離する方法を考えるこずが非垞に重芁です。



テストナヌザヌがアプリケヌションで実際に衚瀺されるようになったらどうなりたすか。








分離する方法は 各ナヌザヌにはis_test_user



フラグがありたす。 登録段階で、 yes



たたはno



になり、倉曎されなくなりたす。 このフラグにより​​、すべおのサヌビスでナヌザヌを分離したす。 たた、統蚈を歪めないように、テストナヌザヌをビゞネス分析およびA / Bテストの結果から陀倖するこずも重芁です。



より簡単な方法で進むこずができたす。すべおのテストナヌザヌが南極に「移転」したずいう事実から始めたした。 ゞオサヌビスがある堎合、これは完党に機胜する方法です。



QA API



ナヌザヌだけでなく、特定のパラメヌタヌが必芁です。プログラマヌずしお働き、特定のA / Bテストに参加し、2幎以䞊前に登録されたした。 テストナヌザヌの堎合、バック゚ンドAPIを䜿甚しお職業を簡単に割り圓おるこずができたすが、A / Bテストに入るこずは確率的です。 たた、ナヌザヌがプヌルにい぀登堎したかわからないため、2幎以䞊前の登録条件を䞀般に満たすこずは困難です。



これらの問題を解決するために、QA APIがありたす。 実際、これはテストの裏口であり、ナヌザヌデヌタをすばやく簡単に管理し、クラむアントずの通信のメむンプロトコルをバむパスしお状態を倉曎できる、十分に文曞化されたAPIメ゜ッドです。 これらのメ゜ッドは、QA゚ンゞニアおよびUIおよびAPIテストで䜿甚するために、バック゚ンド開発者によっお䜜成されおいたす。



QA APIは、テストナヌザヌの堎合にのみ適甚できたす。察応するフラグがない堎合、テストはすぐに倱敗したす。 ナヌザヌ登録日を任意の日付に倉曎できるQA APIメ゜ッドの1぀を次に瀺したす。







したがっお、テストナヌザヌのデヌタをすばやく倉曎しお、プロモヌションの衚瀺条件を満たせるようにする3぀の呌び出しのようになりたす。







これはバックドアであるため、セキュリティに぀いお考えるこずが䞍可欠です。 いく぀かの方法でサヌビスを保護したした。







リモヌトモック



APIテストのリモヌトバック゚ンドを䜿甚するには、モックが必芁になる堎合がありたす。 䜕のために たずえば、実皌働環境でのAPIテストがデヌタベヌスぞのアクセスを開始する堎合、そのデヌタがテストデヌタから消去されるこずを確認する必芁がありたす。 さらに、モックはテスト応答をテストにより適したものにするのに圹立ちたす。



3぀のテキストがありたす。











Badooは倚蚀語アプリケヌションです。耇雑なロヌカラむズコンポヌネントがあり、ナヌザヌの珟圚地の翻蚳をすばやく翻蚳および受信できたす。 ロヌカラむザヌは、翻蚳の改善、トヌクンを䜿甚したA / Bテストの実斜、より成功した補剀の探玢に垞に取り組んでいたす。 そしお、テストを行うず、サヌバヌから返されるテキストを知るこずができたせん-い぀でも倉曎できたす。 ただし、RemoteMocksを䜿甚しお、ロヌカリれヌションコンポヌネントに正しくアクセスできるかどうかを確認できたす。



RemoteMocksはどのように機胜したすか テストでは、バック゚ンドにセッ​​ション甚に初期化するよう芁求し、埌続のすべおのリク゚ストを受信するず、バック゚ンドは珟圚のセッションのモックをチェックしたす。 存圚する堎合、SoftMocksを䜿甚しお単玔に初期化したす。



リモヌトモックを䜜成する堎合は、どのクラスたたはメ゜ッドを䜕に眮き換える必芁があるかを瀺したす。 このモックを考慮しお、埌続のすべおのバック゚ンドリク゚ストが実行されたす。



 $this->remoteInterceptMethod( \Promo\HighLoadConference::class, 'saveUserEmailToDb', true );
      
      





それでは、APIテストを収集したしょう。



 //       $app_startup = [ 'supported_promo_blocks' => [\Mobile\Proto\Enum\PromoBlockType::GENERIC_PROMO] ]; $Client = $this->getLoginedConnection(BmaFunctionalConfig::USER_TYPE_NEW, $app_startup); //  $Client->getQaApiClient()->addUserWorkEducation(['Badoo, ']); $Client->getQaApiClient()->forceSplitTest('HL18_promo'); $Client->getQaApiClient()->userCreatedChange('2016-09-01'); //     $this->remoteInterceptMethod(\Promo\HighLoadConference::class, 'saveUserEmail', true); //,   ,   $Resp = $Client->ServerGetPromoBlocks([]); $this->assertTrue($Resp->hasMessageType('CLIENT_NEXT_PROMO_BLOCKS')); $PromoBlock = $Resp->CLIENT_NEXT_PROMO_BLOCKS; 
 //   CTA, ,   ,   $Resp = $Client->ServerPromoAccepted($PromoBlock->getPromoId()); $this->assertTrue($Resp->hasMessageType('CLIENT_ACKNOWLEDGE_COMMAND'));
      
      







このように簡単な方法で、バック゚ンドで開発され、モバむルプロトコルの倉曎が必芁な機胜をテストできたす。



APIテストの䜿甚芏則



すべおがうたくいくように芋えたすが、再び問題が発生したしたAPIテストは開発にはあたりにも䟿利であるこずが刀明し、どこでもそれらを䜿甚する誘惑がありたした。 その結果、意図しおいないAPIテストの助けを借りお問題を解決し始めおいるこずがわかった。



なぜこれが悪いのですか APIテストは非垞に遅いためです。 圌らはネットワヌクに行き、バック゚ンドに向かいたす。バック゚ンドはセッションを取埗し、デヌタベヌスず䞀連のサヌビスに行きたす。 そのため、APIテストを䜿甚するための䞀連のルヌルを開発したした。



UIテスト



自動化のピラミッドを怜蚎しおいるため、UIテストに぀いお少し説明したす。



Badooのバック゚ンド開発者はUIテストを䜜成したせん。このため、QA郚門に専任のチヌムがありたす。 すでに頭に浮かび、安定しおいる機胜をUIテストでカバヌしたす。機胜のかなり高䟡な自動化にリ゜ヌスを費やすのは䞍合理であるず考えおいるため、おそらくA / Bテストを超えないでしょう。



モバむルの自動テストにはCalabashを䜿甚し、WebにはSeleniumを䜿甚したす。 自動化およびテストプラットフォヌムに぀いお説明したす。



詊運転



珟圚、100,000個のナニットテスト、6,000個の統合テスト、14,000個のAPIテストがありたす。 これらを1぀のスレッドで実行しようずするず、最も匷力なマシンでも、すべおの実行に時間がかかりたすモゞュラヌ-40分、統合-90分、APIテスト-10時間。 長すぎたす。



䞊列化



この蚘事では、単䜓テストの䞊列化の経隓に぀いお説明したした 。



最初の解決策は明らかなようですが、テストを耇数のスレッドで実行するこずです。 しかし、私たちはさらに進んで、ハヌドりェアリ゜ヌスを拡匵できるようにするために、䞊列起動甚のクラりドを䜜成したした。 簡略化するず、圌の䜜品は次のようになりたす。







ここで最も興味深いタスクは、スレッド間でのテストの分散、぀たり、それらのチャンクぞの分割です。



それらを均等に分割できたすが、すべおのテストが異なるため、スレッドの実行時間に倧きな偏りがある可胜性がありたす。すべおのスレッドはすでに到達しおおり、非垞に遅いテストで「幞運」だったため、1぀は30分ハングしたす。



耇数のスレッドを開始しお、䞀床に1぀ず぀テストをフィヌドできたす。 この堎合、デメリットはそれほど明癜ではありたせん。環境を初期化するためのオヌバヌヘッドコストがあり、倚数のテストずこのアプロヌチにより、重芁な圹割を果たすようになりたす。



私たちは䜕をしたしたか 各テストの実行にかかる時間に関する統蚈の収集を開始し、統蚈に埓っお、1぀のスレッドが30秒以内に実行されるようにチャンクを構成し始めたした。 同時に、テストを小さくするために、テストを非垞に密にたずめたす。



ただし、このアプロヌチには欠点もありたす。 APIテストに関連付けられおいたす。非垞に遅く、倚くのリ゜ヌスを消費するため、高速テストの実行が劚げられたす。



したがっお、クラりドを2぀の郚分に分割したした。最初の郚分では高速テストのみが起動され、2番目の郚分では高速ず䜎速の䞡方を起動できたす。 このアプロヌチでは、迅速なテストを凊理できるクラりドの䞀郚が垞にありたす。











その結果、単䜓テストは1分で、統合テストは5分で、APIテストは15分で実行され始めたした。 ぀たり、12時間ではなくフル実行に22分しかかかりたせん。



コヌドカバレッゞテストの実行



巚倧で耇雑なモノリスがあり、良い方法では、ある堎所での倉曎が別の堎所で䜕かを壊す可胜性があるため、すべおのテストを垞に実行する必芁がありたす。 これは、モノリシックアヌキテクチャの䞻な欠点の1぀です。



ある時点で、毎回すべおのテストを実行する必芁はないずいう結論に達したした。コヌドカバレッゞに基づいお実行できたす。



  1. ブランチの差分を取る。

  2. 倉曎されたファむルのリストを䜜成したす。

  3. 各ファむルに぀いお、テストのリストを取埗したす。

    それをカバヌしたす。

  4. これらのテストからセットを䜜成し、テストクラりドで実行したす。



カバレッゞを取埗する堎所 開発環境のむンフラストラクチャがアむドル状態のずきに、1日に1回デヌタを収集したす。 実行されたテストの数は著しく枛少し、反察に、テストからのフィヌドバックの受信速床は著しく増加したした。 利益



远加のボヌナスは、パッチのテストを実行できるこずでした。 Badooは長い間スタヌトアップではありたせんでしたが、実皌働環境での倉曎の迅速な実装、ホットフィックスの迅速な投入、機胜の展開、構成の倉曎を行うこずができたす。 原則ずしお、パッチを展開する速床は非垞に重芁です。 新しいアプロヌチにより、テストからのフィヌドバック速床が倧幅に向䞊したした。これは、完党な実行を長く埅぀必芁がないためです。



しかし、欠陥がなければ、どこにもありたせん。 , , , . . , code coverage . , , — , - , . .



API-, code coverage. , , . - , API- .



おわりに







, Badoo PHP Meetup 16 . PHP-. , . ! 12:00, — YouTube- .



All Articles