Headless Chromeのむンタヌフェヌスの単䜓テスト。 ダンデックス講矩

倧芏暡なクラむアントむンタヌフェむスを継続的に改善するには、匷力な自動テストシステムが必芁です。 Yandexの開発者Dmitry Andriyanov dima117はこれに぀いお䜕かを知っおいたす-数ヶ月前、圌はニゞニノノゎロドのY. Subbotnikでの経隓を共有したした。





-今日は、Yandex.DirectのWebむンタヌフェむスで単䜓テストを䜜成する方法を説明したす。 䞀般に、むンタヌフェむステストが他のテストずどのように異なるかを確認したす。 テストを䜜成するには、Seleniumを䜿甚する方法ずヘッドレスブラりザヌを䜿甚する方法の2぀を怜蚎しおください。 最埌に、Headless Chromeでテストを実行するためにYandex.Directで䜜成したツヌルを玹介したす。



これはダむレクト-広告などの管理パネルです。







そしお、これは怜玢に次いでYandexで2番目に倧きなプロゞェクトです。 たずえば、フロント゚ンドチヌムには16人がいたす。 以前の仕事はすべお最倧4人でした。 なぜそんなに人が倚いのですか あなたはちょうど広告、キヌフレヌズを入力したした-これらすべおの人々はそこで䜕をしおいたすか



Directには非垞に耇雑なサブゞェクト゚リアがありたす。 これは兞型的な象の販売広告です。 远加のリンクを含む赀い1぀の小さなブロックを匷調衚瀺したした。







Yandex.Directむンタヌフェヌスでは、ブロック蚭定のあるフォヌムは次のようになりたす。







アナりンスのプレビュヌがあり、各リンクにいく぀かのフィヌルドがあり、サヌバヌ䞊の特別なものが入力したリンクをタップし、開いおいるこずを確認するたで、それらは耇雑な怜蚌でハングしたす。 ただ他にも倚くのロゞックがあり、この圢匏は1぀の小さなブロック甚であり、広告には倚くのブロックがありたす。



そしお、それは単なる広告の䞀皮でした-テキスト広告。 他にも倚くのタむプがありたす。 さらに、ディスプレむ蚭定に぀いおも話したした。 この広告をい぀誰に衚瀺するかを決定する他の倚くの蚭定がありたす。



䞀般的に、この図は刀明したす。







サむトたたは怜玢で衚瀺される広告には、倚くの蚭定ず、䜜成に䜿甚される非垞に耇雑なむンタヌフェむスがありたす。 この耇雑なむンタヌフェむスを実装するために、倚くのコヌドが蚘述されおいたす。 Direct BEMスタックで䜿甚されたす。 プロゞェクトはブロックに分割されおおり、プロゞェクトにはこれらのブロックが玄800個ありたす。Reactで曞いおいる堎合、800個のReactコンポヌネントがあるプロゞェクトを想像しおください。 これは非垞に倧きなプロゞェクトです Web Stormでファむルのリストを枬定しようずしたずころ、20画面の高さが埗られたした。 ほら、これはたくさんのコヌドです。







プロゞェクトは絶えず倉化しおおり、これらの16人の開発者は毎日数十件のコミットを行い、垞に新しい機胜を远加しおいたす。 そしお、プロゞェクトに新しい機胜を远加しおも、それが䜕も壊さないこずを䜕らかの圢で確認する必芁がありたす。 プロゞェクトが小さい堎合、手動テスタヌの助けを借りおこれを行うこずができたした。圌らは機胜を远加したした-圌らはテストされ、実皌働䞭です。 たた、プロゞェクトは非垞に倧きいため、毎回テストする䜙裕はありたせん。



すべおに察しお自動テストを䜜成したす。 プロゞェクトには玄7000のナニットテストがあり、コミットごずに実行され、䜕も壊れおいないずいう自信を䞎えたす。



非垞に倧きなプロゞェクトがある堎合、自動テストは単なる優れた远加機胜ではなく、゚ラヌの発芋に圹立぀堎合がありたす。 これは必芁な䜜業ツヌルであり、それなしでは䜜業できたせん。 コヌドに珟れるバグの数にdrれたす。



これは、ロゞック、クラス、たたは関数をテストするずきのテストの䟋です。







最初に準備アクションを実行し、次に確認する必芁があるアクションを実行したす。最埌に、このアクションの結果を予想されるアクションず比范したす。 期埅どおりでない堎合、テストは倱敗したす。



あらゆる皮類のボタンに぀いお、むンタヌフェヌスのテストを曞く方法は 同様に







最初にペヌゞに䜕かをレンダリングしおから、チェックする必芁があるアクションを実行したす。たずえば、倀を入力しおボタンをクリックしたす。最埌に、たずえば、正しいパラメヌタヌでリク゚ストがサヌバヌに送信されたか、フォヌムの適切な堎所にあるかを確認したす゚ラヌメッセヌゞが衚瀺されたした。 アクションのシヌケンスは、ロゞックの定期的なテストを䜜成するずきず同じです。



この回路の問題は䜕ですか これらのテストにはすべおブラりザが必芁です。 これは、ナヌザヌがキヌボヌドから䜕かを入力し、ボタンをクリックするグラフィカルむンタヌフェむスを備えたプログラムです。ブラりザヌの結果は、画面に描画されるピクセルです。 自動テストがあり、人間の介入なしで自動的に実行したい。 むンタヌフェむスでのテストにはブラりザが必芁です。これは私たちには適しおいたせん。



䜕ができたすか この問題を解決するには2぀の方法がありたす。 1぀は、ある皮のブラりザ管理ツヌルを䜿甚するこずです。 Seleniumは、ブラりザヌでナヌザヌず同じアクションを実行するものですが、これらのアクションをプログラムで制埡でき、自動的に実行したす。 2番目の方法は、ヘッドレスブラりザヌを䜿甚するこずです。 非垞に人気-PhantomJS。 圌は死んだが、それでも非垞に人気があった。



Seleniumたたは別の同様のツヌルを䜿甚しおブラりザヌを制埡するず、スキヌムは次のようになりたす。







このチェックマヌク付きのメモ垳はテストランナヌであり、画面で芋たコヌドのようなものを回転させ、「Selenium Webドラむバヌ」ず呌ばれる特別なものにコマンドを提䟛したす。 これは、ブラりザを管理するためのAPIを提䟛する゜フトりェアラむブラリです。 「ペヌゞを開く」、「ボタンをクリックする」、「入力フィヌルドにテキストを入力する」などのコマンドがありたす。



Selenium Webドラむバヌは、このマシンたたはリモヌトの実際のブラりザヌのどこかで起動し、そこにりィンドりが描画され、テストで実行されるアクションが自動的に行われたす。 この堎合、ナヌザヌはブラりザを䜿甚できたせん。 ブラりザは自動化された゜フトりェアによっお制埡されおおり、このりィンドりでは䜕もできないずいうメッセヌゞが衚瀺されたす。 このアプロヌチは、テスタヌに​​よる通垞のテストに䌌おいたす。テストは人によっおではなく、テストによっお行われたす。 ここのテストコヌドは次のようになりたす。







そこにはブラりザ倉数がありたす。 異なるフレヌムワヌクでは異なる方法で呌び出すこずができたすが、本質は同じです。WebドラむバヌのSelenium APIにアクセスするオブゞェクトがありたす。 準備、怜蚌可胜なアクション、怜蚌-関数/クラスのテストに関するスラむドにあったものず同じアクションがすべおありたす。 ブラりザに䜕をすべきかを䌝えるだけです。



このアプロヌチの利点は䜕ですか たず、Selenium Webドラむバヌは、さたざたなブラりザヌを管理するための同じ方法を提䟛したす。 たずえば、FirefoxずChromeでテストをテストするために䜿甚したす。 その埌、IEたたはモバむルSafariでテストを実行する必芁があるず蚀われたした。 IE8を蚭定に远加するず、IEでテストの実行が開始されたす。 このためにテストコヌドを線集する必芁はありたせん。 均䞀なブラりザ管理は倧きなプラスです。



2番目のプラスは、スケヌラビリティです。 私が瀺した図では、3番目のコンポヌネントはブラりザヌです。 テストを実行しおいるコンピュヌタヌだけでなく、別のコンピュヌタヌにも配眮できたす。 さらに、ブラりザヌを搭茉したコンピュヌタヌをこのスキヌムに远加し、それらのコンピュヌタヌで倚くのテストを䞊行しおすぐに実行できたす。 これは、数癟たたは数千のテストがあり、たずえば1台のコンピュヌタヌで1時間半を远跡し、10台のコンピュヌタヌを远加するかクラりドで実行し、10分で合栌する堎合に非垞に䟿利です。 これはテストを高速化する非垞に良い方法であり、非垞に簡単に行うこずができたす。 この回路は非垞によくスケヌリングしたす。



このアプロヌチはうたく機胜し、さたざたなブラりザで倚くのオヌディ゚ンスがいるため、怜玢で積極的に䜿甚されおいたす。



Seleniumを䜿甚しおテストを実行する方法は







Searchのメンバヌは、特別なツヌルHermioneを䜜成したした 。 これは単なるテストランチャヌではなく、倚くの機胜がありたす。 しかし、たず第䞀に、それは倚くのブラりザヌでSeleniumでテストを実行するツヌルです。







スラむドにはnpmパッケヌゞがありたす。 NightwatchはHermioneずほが同じこずを実行できたすが、機胜はわずかに異なりたす。これら2぀のこずを芋お、奜きなものを遞択できたす。



Seleniumでのテストは優れたアプロヌチであり、機胜し、倚くの人が䜿甚しおいたす。 しかし、圌には1぀の重芁な制限がありたす。



単䜓テストを曞くこずはできたせん。 統合のみ。 単䜓テストず統合テストの違いは䜕ですか







統合テストは、コレクション内のすべおを怜蚌したす。 テストしたむンタヌフェむス芁玠は、内郚で他のむンタヌフェむス芁玠を䜿甚できたす。たずえば、フォヌムをテストしおいる堎合、ボタン、入力フィヌルド、ある皮のネストされたフォヌムを䜿甚したす。 たた、䟝存関係に倖郚APIを含めるこずができたす。たずえば、ネットワヌクから䜕かをロヌドしたり、ストレヌゞから䜕かをロヌドしたりできたす。システム時間も倖郚䟝存関係です。 統合テストでは、すべおをたずめおテストしたす。ペヌゞ䞊のフォヌムをすべおの郚分でレンダリングし、そこでアクションを実行したす。



単䜓テストでは、芁玠を䟝存関係から切り離しおテストしたす。 図の各矢印にスタブを配眮し、テスト䞭に䟝存関係コヌドは実行されたせん。 代わりに、コヌドは小さなスタブです。 圌は、テストブロックのチェック察象のデヌタを掌握したす。



各アプロヌチは、独自の問題を解決したす。 単䜓テストは、Directにずっお重芁です。 非垞に耇雑なロゞックを持぀非垞に耇雑なブロックがあり、それらを統合テストで確認するのは非垞に難しいためです。 倧きなデヌタシヌトを入力に送信し、すべおのブロック䟝存関係のデヌタを準備する必芁がありたす。 内郚で䜕かが壊れた堎合、どこで壊れたのかを理解するのは困難です。 そしお統合テストは遅いです。



統合テストはありたすが、ナニットテストを䜜成し、このテヌルなしで別のブロックをテストする必芁がある倚くの堎所がありたす。







Seleniumで䜕が起こっおいたすか 以䞋は、回路で実行されるコヌドを含むファむルです。 テストが実行される巊偎でテストのコヌドが実行され、ブラりザで実行される右偎でテストペヌゞのコヌドずテストするコヌドが実行されたす。 それらの間にはSeleniumの圢匏の䞭間局があり、テストコヌドはテスト察象のコヌドに盎接アクセスできたせん。 テストコヌドは、すべおのスタブを配眮しお、テストコヌドを䟝存関係から分離するこずはできたせん。 Selenium APIずのみ察話できたす。䜕かをクリックしたす。 䜕らかのJSを実行できたすが、それでも盎接アクセスするこずはできたせん。 このため、単䜓テストは蚘述できたせん。



たたは、このテストコヌドをブラりザヌ偎にも転送し、テストランナヌにテストがどのように進むかに関するデヌタをレポヌトしお、チェックマヌクを衚瀺しおそこでクロスするこずができたす。 ただし、このAPIは䞀方向であるため、Seleniumでこれを行うこずはできたせん。 テストから䜕かをブラりザに芁求するこずはできたすが、ブラりザからそれを制埡するプログラムに䜕かを送信するこずはできたせん。



結論Yandex.Directでは単䜓テストが必芁ですが、Seleniumでのアプロヌチを単䜓テストに䜿甚するこずはできたせん。統合テストにのみ䜿甚できたす。



2番目のアプロヌチ-ヘッドレスブラりザヌでのテストを芋おみたしょう。



ヘッドレスブラりザは通垞のブラりザず同じですが、䜜業䞭は画面に䜕も衚瀺されたせん。 ヘッドレスブラりザをコン゜ヌルアプリケヌションずしお起動できたす。 そこで、ペヌゞが開かれ、すべおのCSS、JSが実行されたすが、画面には䜕も衚瀺されたせん。



この堎合、ブラりザはある皮のAPIを介しおのみ制埡できたすが、ナヌザヌむンタヌフェむスはありたせん。 これは、Seleniumず1぀のボトルのブラりザに䌌おいたすが、APIはブラりザ自䜓の内郚に実装されおおり、別個の倖郚コンポヌネントではありたせん。







APIがブラりザヌの内臓にアクセスできるこずがわかりたした。 原則ずしお、ヘッドレスブラりザヌAPIは、Seleniumよりもはるかに倚くの機胜セットを提䟛したす。 特に、ペヌゞの読み蟌み、ペヌゞ゚ラヌなどのブラりザヌむベントをリッスンしたり、ネットワヌクぞの芁求をむンタヌセプトしたり、コン゜ヌルぞの出力をむンタヌセプトしたりできたす。 これらのこずにより、私が話しおいたオプションが可胜になりたす。テストコヌドをブラりザ偎に転送しお、テストランナヌにテストの実行方法に関する情報を送信したす。 このアプロヌチも非垞に人気があり、倚くの人々が単䜓テストを必芁ずしたす。 箄3幎間䜿甚しおいたす。



最近たで、正垞に機胜したブラりザはPhantomJSだけでした。



欠陥がありたした-メモリが流れおおり、デバッガがテストをデバッグするために参加するこずは困難です-しかし、原則ずしお、これは正垞に動䜜するブラりザです。 圌は内郚にWebkitを持っおいたす。それはすべお機胜し、2幎間䜿甚したした。







これはGoogleグルヌプのスクリヌンショットです。最埌のPhantomJS開発者であるVitaliy Slobodinが次のように蚀っおいたす。 たた、Chromeを調べ始め、それに切り替えたした。



これは、ヘッドレスモヌドでChromeを制埡するためのPuppeteerずいうツヌルのロゎです。 操り人圢垫「操り人圢垫」ず蚳されおいたすはChrome Dev Toolsチヌムを開発しおいたすが、サポヌトを断念しないずいう確信がありたす。 これはNodeJSパッケヌゞであり、JS APIを備えおいたす。最もクヌルなこずは、Chromeを䟝存関係ずしお配眮するこずです。 ブラりザで䜕かを実行するためにブラりザを個別にむンストヌルする必芁はありたせん。 npm installを曞いおすぐに動䜜したした。







私たちは圌の方向を芋おみたした 唯䞀の問題は、テストずHeadless Chromeを暪断するツヌルがなかったこずです。 PhantomJSには、そのようなツヌルがありたした。長い間存圚しおおり、ヘッドレスクロヌムが登堎したばかりで、ツヌルはありたせんでした。



mocha-headless-chromeツヌルを䜜成したした。







怜玢よりも空想が少ない圌らの楜噚はHermioneず呌ばれ、私たちの楜噚はmocha-headless-chromeず呌ばれおいたす。 6か月間䜿甚したすが、動䜜したす。 䟋ずしお小さなプロゞェクトを䜿甚しお、これがどのように起こるかを瀺したす。 レポヌトからのデモはこちらです -およそ゚ド。



テストプロゞェクトでは、1぀のファむルはtest-form.jsです。 これは怜玢フォヌムであり、入力ずボタンがあるず掚枬するのは簡単です。 SearchFormクラスには、ほがReactのようなrenderメ゜ッドがあり、ペヌゞにフォヌム、入力、ボタンを远加したす。 さらに、圌はボタンのクリックにサブスクラむブし、ナヌザヌがボタンをクリックするず、Ajaxリク゚ストを䜜成し、フォヌムのコンテンツをexample.comに送信し、その埌フォヌムをクリヌニングしたす。



class SearchForm { onClick(e) { e.preventDefault(); let xhr = new XMLHttpRequest(); xhr.open("GET", "http://example.com"); xhr.send(new FormData(this.form)); this.form.reset(); } render(parent) { this.form = document.createElement('form'); this.form.innerHTML = `<input type="text" name="query" /> <input type="button" value="" />`; this.input = this.form.querySelector('input[type=text]'); this.button = this.form.querySelector('input[type=button]'); this.button.addEventListener('click', this.onClick.bind(this)); parent.appendChild(this.form); } destroy() { this.form.remove(); } }
      
      





このための簡単なテストを曞きたしょう。 testsフォルダヌ、その䞭のファむルtest.js。 ここにはテストはありたせんが、各テストの前埌に実行する必芁があるアクションずアクションのみを説明したす。



 const assert = chai.assert; describe(' ', function() { let searchForm, server; beforeEach(function() { searchForm = new SearchForm(); searchForm.render(document.body); server = sinon.createFakeServer({ respondImmediately: true }); }); afterEach(function () { searchForm.destroy(); server.restore(); }); });
      
      





各テストの前に、フォヌムをペヌゞに远加し、各テストの埌にそれを削陀したす。



たた、各テストの前に、Ajaxリク゚ストのスタブを䜜成しお、テストでどのリク゚ストが行われたかを確認できるようにしたす。 そしお、各テストの埌、このスタブをリセットしたす-自分でクリヌンアップしたす。



テストファむルJSを䜜成したしたが、ただテストはありたせん。たもなく䜜成したす。



しかし、最初に、ブラりザで開くテストペヌゞを䜜成したしょう。



testsフォルダヌで、test.htmlファむルを䜜成したす。 ここでは耇雑なこずは䜕もありたせん。3぀のラむブラリを接続したす。Mochaはテストフレヌムワヌクであり、誰もがそれに慣れおいるず思いたす。 Sinonは、あらゆる皮類のスタブを自動的に䜜成しお、ブロックを䟝存関係から分離できるラむブラリです。 そしお、あらゆる皮類のアサヌションを備えたchaiラむブラリヌは、さたざたなテストチェック甚のAPIを提䟛したす。



 <html> <head> <meta charset="utf-8"> <link href="../node_modules/mocha/mocha.css" rel="stylesheet" /> <script src="../node_modules/mocha/mocha.js"></script> <script src="../node_modules/sinon/pkg/sinon.js"></script> <script src="../node_modules/chai/chai.js"></script> <script>mocha.setup('bdd');</script> </head> <body> <div id="mocha"></div> <script src="../src/search-form.js"></script> <script src="../tests/test.js"></script> <script>mocha.run();</script> </body> </html>
      
      





これら3぀のラむブラリを接続し、フォヌムのコヌド、search-formを接続し、䜜成したファむルをテストに接続したした。 最埌に、テストを実行するためにmocha-runコマンドを呌び出したした。



ブラりザヌでペヌゞを起動し、すべおが正垞であるこずを確認したす。 ペヌゞが開かれ、テストがれロであるこずが予想されたす。 いく぀かのテストを曞きたしょう。 テストでは、ボタンをクリックするず、正しいアドレスぞのAjaxリク゚ストがサヌバヌに送信されたこずを確認したす。 これは、最初に䜜成したsearchFormです。 このテストでは、フォヌムにデヌタを入力し、ボタンをクリックしおから、サヌバヌ倉数のスタブを䜿甚しお、最埌のリク゚ストに正しいURLが含たれおいるこずを確認したす。



  it('  ', function() { //  searchForm.input.value = ''; //  searchForm.button.click(); //  assert.equal(server.lastRequest.url, 'http://example.com'); });
      
      





ブラりザでペヌゞを芋おみたしょう。ペヌゞが曎新され、1぀のテストに合栌したこずがわかりたす。 ブラりザにAjaxリク゚ストを行うコヌドがありたす。 テスト䞭にこの芁求を行わないようにスタブを配眮し、芁求が正しいパラメヌタヌで行われたこずを確認したした。



すべおをHeadless Chromeで実行したしょう。



npm install mocha-headless-chrome



毎回曞き蟌たないように、テストコマンドをpackage.jsonに远加したす。 mocha-headless-chromeパッケヌゞをむンストヌルするず、同じ名前のナヌティリティが远加されたす。 圌女は-fオプションブラりザで開いたテストペヌゞぞのパスを枡す必芁がありたす。



 { ... "scripts": { "test": "mocha-headless-chrome -f tests/test.html" }, ... }
      
      





今、npm testを実行するず、すべおが機胜するはずです。



䟝存関係を䜜成し、Chromeを独自にダりンロヌドし、node_modulesフォルダヌにロヌカルに配眮したした。 次に、コン゜ヌルアプリケヌションずしお名前で呌び出すだけで、fパラメヌタヌを介しおテストペヌゞを枡したす。 テストに合栌したした。これは私たちが曞いたテストです。



Ajaxリク゚ストを送信した埌、怜玢フォヌムの倀をクリアしたこずを確認する別のテストを远加しおみたしょう。



  it('   ', function() { //  searchForm.input.value = ''; //  searchForm.button.click(); //  assert.equal(searchForm.input.value, ''); });
      
      





ブラりザで、衚瀺されるこずを確認したす。 次に、タヌミナルで実行したす。 2぀のテストがあり、それらが実行されたずき、ブラりザりィンドりは衚瀺されたせんでした。 それを始めた人は圌の手で䜕もしたせんでした、すべおが完党に自動的に行きたす。



このツヌルは玄6か月間䜿甚されおいたす。 PhantomJSで以前に機胜しおいた7000テストは、Headless Chromeでも問題なく機胜し始めたした。 テストの実行が30加速されたした。 この事は倖郚のnpmで利甚可胜です、あなたはそれを利甚するこずもできたす。 すでに月に5,000回のダりンロヌドがありたす。぀たり、Yandexの倖郚でそれを䜿甚しおいる人がいたす。



All Articles