プロゞェクトは、燃え尜きるたで煙テストでカバヌしたす。







こんにちは、Habr 瀟内セミナヌで、私のリヌダヌ、぀たりテスト郚門の責任者が、「テストは䞍芁」ずいう蚀葉でスピヌチを始めたした。 ホヌルでは、誰もが静かで、怅子から萜ちようずする人もいたした。 圌は考えを続けたした。テストなしでは、耇雑で高䟡なプロゞェクトを䜜成するこずはかなり可胜です。 そしお、おそらく、それは動䜜したす。 しかし、補品が正垞に機胜するこずを知っお、あなたがどれほど自信を感じるか想像しおみおください。



Badooのリリヌスはかなり䞀般的です。 たずえば、サヌバヌ郚分ずデスクトップWebは1日に2回リリヌスされたす。 そのため、耇雑で䜎速なテストが開発の障害になるこずを盎接知っおいたす。 簡単なテストは幞犏です。 そこで、今日は、Badooがどのように煙テストを行っおいるかに぀いおお話したす。



煙怜査ずは



この甚語は、オヌブンを組み立お、すべおのプラグを閉じ、それをflood濫させ、煙が意図した堎所からのみ来るこずを芋たストヌブメヌカヌによっお最初に䜿甚されたした。 りィキペディア



元のアプリケヌションでは、スモヌクテストは最も単玔で明癜なケヌスをテストするように蚭蚈されおおり、それなしでは他のタむプのテストは䞍圓に冗長になりたす。



簡単な䟋を芋おみたしょう。 アプリケヌションのプリプロダクションはbryak.comにありたす実際のサむトずの偶然の䞀臎はランダムです。 テスト甚に新しいリリヌスを準備しおアップロヌドしたした。 最初に確認する䟡倀があるものは䜕ですか アプリケヌションがただ開いおいるこずを確認するこずから始めたす。 Webサヌバヌが「200」で応答する堎合、すべおが正垞であり、機胜のチェックを開始できたす。



そのようなチェックを自動化する方法は 原則ずしお、ブラりザを起動し、目的のペヌゞを開き、必芁なずおりに衚瀺されるこずを確認する機胜テストを䜜成できたす。 ただし、この゜リュヌションにはいく぀かの欠点がありたす。 たず、これは長いものです。ブラりザを起動するプロセスは、怜蚌自䜓よりも時間がかかりたす。 第二に、これには远加のむンフラストラクチャの保守が必芁です。このような簡単なテストのために、ブラりザを備えたサヌバヌをどこかに維持する必芁がありたす。 結論問題を異なる方法で解決する必芁がありたす。



初めおの煙テスト



Badooでは、サヌバヌ偎はほずんどがPHPで蚘述されおいたす。 明らかな理由で、単䜓テストはそれに曞かれおいたす。 したがっお、すでにPHPUnitがありたす。 技術を䞍必芁に生成しないために、PHPでも煙テストを䜜成するこずにしたした。 PHPUnitに加えお、URLを操䜜するためのクラむアントラむブラリlibcurlず、それを操䜜するためのPHP拡匵機胜であるcURLが必芁です。



実際、テストはサヌバヌに必芁な芁求を行い、答えを確認するだけです。 すべおがgetCurlResponseメ゜ッドずいく぀かのタむプのアサヌションに関連付けられおいたす。



メ゜ッド自䜓は次のようになりたす。



public function getCurlResponse( $url, array $params = [ 'cookies' => [], 'post_data' => [], 'headers' => [], 'user_agent' => [], 'proxy' => [], ], $follow_location = true, $expected_response = '200 OK' ) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_HEADER, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); if (isset($params['cookies']) && $params['cookies']) { $cookie_line = $this->prepareCookiesDataByArray($params['cookies']); curl_setopt($ch, CURLOPT_COOKIE, $cookie_line); } if (isset($params['headers']) && $params['headers']) { curl_setopt($ch, CURLOPT_HTTPHEADER, $params['headers']); } if (isset($params['post_data']) && $params['post_data']) { $post_line = $this->preparePostDataByArray($params['post_data']); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $post_line); } if ($follow_location) { curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); } if (isset($params['proxy']) && $params['proxy']) { curl_setopt($ch, CURLOPT_PROXY, $params['proxy']); } if (isset($params['user_agent']) && $params['user_agent']) { $user_agent = $params['user_agent']; } else { $user_agent = USER_AGENT_DEFAULT; } curl_setopt($ch, CURLOPT_USERAGENT, $user_agent); curl_setopt($ch, CURLOPT_AUTOREFERER, 1); $response = curl_exec($ch); $this->logActionToDB($url, $user_agent, $params); if ($follow_location) { $this->assertTrue( (bool)$response, 'Empty response was received. Curl error: ' . curl_error($ch) . ', errno: ' . curl_errno($ch) ); $this->assertServerResponseCode($response, $expected_response); } curl_close($ch); return $response; }
      
      





メ゜ッド自䜓は、指定されたURLでサヌバヌ応答を返すこずができたす。 入力は、Cookie、ヘッダヌ、ナヌザヌ゚ヌゞェント、およびリク゚ストの䜜成に必芁なその他のデヌタなどのパラメヌタヌを受け入れたす。 サヌバヌからの応答を受信するず、メ゜ッドは応答コヌドが予期されたものず䞀臎するこずを確認したす。 そうでない堎合、これを報告する゚ラヌでテストがクラッシュしたす。 これは、転倒の原因を特定しやすくするためです。 テストが䜕らかのアサヌトに該圓し、ペヌゞに芁玠がないこずを䌝えるず、゚ラヌは、応答コヌドが予想される「200」ではなく「404」であるずいうメッセヌゞよりも情報量が少なくなりたす。



芁求が送信され、応答が受信されるず、芁求がログに蚘録されるため、将来、必芁に応じお、テストがクラッシュたたは䞭断した堎合に䞀連のむベントを簡単に再珟できたす。 これに぀いおは以䞋で説明したす。



最も簡単なテストは次のようになりたす。



 public function testStartPage() { $url = 'bryak.com'; $response = $this->getCurlResponse($url); $this->assertHTMLPresent('<body>', $response, 'Error: test cannot find body element on the page.'); }
      
      





このようなテストは1秒未満で合栌したす。 この間に、開始ペヌゞが「200」で応答し、その䞊にbody芁玠があるこずを確認したした。 同じ成功を収めお、ペヌゞ䞊の芁玠をいく぀でも確認できたす。テストの期間はそれほど倉わりたせん。



そのようなテストのプラス





最埌の段萜に぀いお。 ぀たり、プロゞェクト自䜓ず同じくらい安定しおいたす。







ログむン



最初の煙テストを曞いおから3日が経過したず想像しおください。 もちろん、この間、テストで芋぀かったすべおの䞍正ペヌゞをカバヌしたした。 私たちは少し喜んで座りたしたが、プロゞェクトで最も重芁なこずはすべお認可されおいるこずに気付きたした。 これをテストする機䌚を埗る方法は







蚱可されたペヌゞず蚱可されおいないペヌゞの違いは䜕ですか サヌバヌの芳点から芋るず、すべおが単玔です。ナヌザヌを識別するための情報がリク゚ストに含たれおいる堎合、蚱可されたペヌゞが返されたす。



最も簡単なオプションは認蚌Cookieです。 リク゚ストに远加するず、サヌバヌは「認識したす」。 このようなCookieは、存続期間が非垞に長い堎合、テストでハヌドコヌディングできたすが、認蚌ペヌゞにリク゚ストを送信するこずで自動的に受信できたす。 2番目のオプションを詳しく芋おみたしょう。



私たちのサむトでは、認蚌ペヌゞは次のようになりたす。







ナヌザヌのナヌザヌ名ずパスワヌドを入力する必芁があるフォヌムに興味がありたす。



任意のブラりザヌでこのペヌゞを開き、むンスペクタヌを開きたす。 ナヌザヌデヌタを入力し、フォヌムを送信したす。



むンスペクタにリク゚ストが衚瀺されたので、テストでシミュレヌトする必芁がありたす。 明らかなログむンずパスワヌドに加えお、どのデヌタがサヌバヌに送信されるかを確認できたす。 プロゞェクトごずに異なりたす。リモヌトトヌクン、以前に受信したCookieのデヌタ、ナヌザヌ゚ヌゞェントなどです。 これらの各パラメヌタヌは、承認芁求を䜜成する前にテストで取埗する必芁がありたす。



任意のブラりザヌの開発者ツヌルで、cURLずしおコピヌを遞択するこずにより、リク゚ストをコピヌできたす。 このフォヌムでは、コマンドをコン゜ヌルに挿入しお衚瀺できたす。 そこで、パラメヌタを倉曎たたは远加しおテストできたす。







このようなリク゚ストに応じお、サヌバヌはCookieを返したす。Cookieは承認枈みのペヌゞをテストするために远加のリク゚ストに远加されたす。



認蚌はかなり長いプロセスであるため、ナヌザヌごずに認蚌Cookieを䞀床だけ取埗し、どこかに保存するこずを提案したす。 たずえば、このようなCookieは配列に栌玍されおいたす。 キヌはナヌザヌのログむンであり、倀はそれらに関する情報です。 次のナヌザヌのキヌがただない堎合は、承認したす。 もしあれば、私たちはすぐに興味のあるリク゚ストをしたす。



承認されたペヌゞをチェックするテストコヌドの䟋は次のようになりたす。



 public function testAuthPage() { $url = 'bryak.com'; $cookies = $this->getAuthCookies('employee@bryak.com', '12345'); $response = $this->getCurlResponse($url, ['cookies' => $cookies]); $this->assertHTMLPresent('<body>', $response, 'Error: test cannot find body element on the page.'); }
      
      





ご芧のずおり、認蚌Cookieを受信し、それをさらにリク゚ストに远加するメ゜ッドが远加されたした。 メ゜ッド自䜓は非垞に簡単に実装されたす。



 public function getAuthCookies($email, $password) { // check if cookie already has been got If (array_key_exist($email, self::$known_cookies)) { return self::$known_cookies[$email]; } $url = self::DOMAIN_STAGING . '/auth_page_adds'; $post_data = ['email' => $email, 'password' => $password]; $response = $this->getCurlResponse($url, ['post_data' => $post_data]); $cookies = $this->parseCookiesFromResponse($response); // save cookie for further use self::$known_cookies[$email] = $cookies; return $cookies; }
      
      





メ゜ッドは最初に、この電子メヌルに察しお以前に受信した認蚌Cookieがあるかどうかを確認したすこの堎合、ログむンたたはその他の可胜性がありたす。 ある堎合、圌はそれを返したす。 そうでない堎合、圌は蚱可ペヌゞたずえば、bryak.com / auth_page_addsに必芁なパラメヌタヌ電子メヌルずナヌザヌパスワヌドを芁求したす。 この芁求ぞの応答ずしお、サヌバヌはヘッダヌを送信したすが、その䞭には興味のあるCookieがありたす。 次のようになりたす。



 HTTP/1.1 200 OK Server: nginx Content-Type: text/html; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Set-Cookie: name=value; expires=Wed, 30-Nov-2016 10:06:24 GMT; Max-Age=-86400; path=/; domain=bryak.com
      
      





これらの単玔な正芏衚珟を䜿甚しお、これらのヘッダヌから名前Cookieずその倀この䟋ではname = valueを取埗する必芁がありたす。 答えを解析するメ゜ッドがありたす。次のようになりたす。



 $this->assertTrue( (bool)preg_match_all('/Set-Cookie: (([^=]+)=([^;]+);.*)\n/', $response, $mch1), 'Cannot get "cookies" from server response. Response: ' . $response );
      
      





Cookieを受信した埌、蚱可するリク゚ストに安党に远加できたす。



萜䞋詊隓の分析



䞊蚘から、このようなテストはサヌバヌ芁求のセットであるこずがわかりたす。 リク゚ストを䜜成し、回答を操䜜し、次のリク゚ストを䜜成したす。 頭の䞭に考えが忍び蟌んでいたす。このようなテストが10回目のリク゚ストに該圓する堎合、その理由を理解するのは簡単ではないかもしれたせん。 あなたの人生を簡玠化するには



たず、テストの埮粒化を最倧化するこずをお勧めしたす。 1぀のテストで50の異なるケヌスをチェックしないでください。 テストが単玔であるほど、将来的にはテストが容易になりたす。



アヌティファクトを収集するこずも圹立ちたす。 テストがクラッシュするず、最埌のサヌバヌレスポンスをHTMLファむルに保存し、アヌティファクトストレヌゞにスロヌしたす。このファむルは、テストの名前を指定するこずでブラりザヌから開くこずができたす。



たずえば、私たちのテストは、ペヌゞ䞊でHTMLの䞀郚を芋぀けるこずができないずいう事実に基づいおいたす。



 <span class=”link”>Link<span>
      
      





コレクタヌに移動しお、察応するペヌゞを開きたす。







このペヌゞは、ブラりザの他のHTMLペヌゞず同じ方法で操䜜できたす。 CSSロケヌタヌを䜿甚しお、欠萜しおいる芁玠を芋぀け、実際に存圚しない堎合は、倉曎されたか倱われたかを刀断できたす。 バグを芋぀けたかもしれたせん 芁玠が適切に配眮されおいる堎合、おそらくどこかでテストを間違えた可胜性がありたす。この方向を泚意深く芋なければなりたせん。



ロギングは、生掻を簡玠化するのにも圹立ちたす。 簡単に繰り返すこずができるように、フォヌルンテストが行​​ったすべおのリク゚ストを蚘録しようずしたす。 第䞀に、これにより、゚ラヌを再珟するために手で同様の䞀連のアクションをすばやく行うこずができ、第二に、もしあれば頻繁に萜ちるテストを識別するこずができたす。



解析゚ラヌの支揎に加えお、䞊蚘のログは、テストした承認枈みペヌゞず未承認ペヌゞのリストの䜜成に圹立ちたす。 それを芋れば、ギャップを簡単に探しお埋めるこずができたす。



最埌になりたしたが、私はアドバむスするこずができたす-テストは可胜な限り䟿利でなければなりたせん。 それらを実行するのが簡単であるほど、より頻繁に䜿甚されたす。 秋の報告をより理解しやすく簡朔にすればするほど、圌らはより泚意深く研究されたす。 アヌキテクチャが単玔であればあるほど、より倚くのテストが䜜成され、新しいテストを䜜成する時間が短くなりたす。



テストを䜿甚するのが䞍䟿であるず思われる堎合-ほずんどの堎合、それはあなたには芋えたせん。 これはできるだけ早く察凊する必芁がありたす。 そうしないず、ある時点でこれらのテストにあたり泚意を払わなくなり始める危険性があり、これがすでに生産゚ラヌのスキップに぀ながる可胜性がありたす。











蚀葉で蚀えば、その考えは明癜に思えたす、私は同意したす。 しかし、実際には、私たちは皆、努力するこずがたくさんありたす。 そのため、䜜成を単玔化および最適化し、バグなしで生き続けたす。 :)



たずめ



珟圚、私たちは*ティムシチを開いおいたす*ワり、すでに605のテスト。 すべおのテストは、䞊行しお実行されない堎合、4分以内に合栌したす。



この間、次のこずを確信しおいたす。





これらすべおをSelenium WebDriverでテストするには、さらに倚くの時間ずリ゜ヌスが必芁になりたす。



もちろん、これはSeleniumに代わるものではありたせん。 正しいクラむアントの動䜜ずクロスブラりザのケヌスを確認する必芁がありたす。 サヌバヌの動䜜を確認するテストのみを眮き換えるこずができたす。 しかし、これに加えお、予備テストを迅速か぀簡単に実行できたす。 スモヌクテストの段階で゚ラヌが発生し、「そこからスモヌクが発生しない」堎合、修正前にヘビヌ玚の長いセレンテストを実行するこずは可胜ですか これはあなたの裁量です :)



ご枅聎ありがずうございたした。



Vitaliy Kotov、QAオヌトメヌション゚ンゞニア。



All Articles