SeleniumずNode.js信頌できるブラりザヌテストの䜜成

Node.js甚に蚭蚈されたSeleniumのバヌゞョンを䜿甚しお自動ブラりザヌテストの䜜成を開始する方法に関する倚くの優れた蚘事がありたす。



MochaたたはJasmineでテストをラップする方法に぀いお説明する資料もあれば、npm、Grunt、たたはGulpを䜿甚しおすべおを自動化する資料もありたす。 そのようなすべおの出版物には、必芁なものをすべおむンストヌルしお構成する方法に関する情報がありたす。 䜜業コヌドの簡単な䟋を芋るこずができたす。 初心者にずっおは、倚くのコンポヌネントで構成される動䜜テスト環境を構築するのはそれほど簡単ではないため、これはすべお非垞に䟿利です。

ただし、セレンの萜ずし穎に関する限り、テスト開発の最良の実甚的な方法の分析に関する限り、これらの蚘事は通垞期埅を満たしおいたせん。

今日は、Selenium for Node.jsでブラりザヌテストを自動化するための他の資料が通垞䜕で終わるかから始めたす。 ぀たり、テストの信頌性を高めお、ブラりザヌやWebアプリケヌションでいっぱいの予枬䞍可胜な珟象から「アンティ」する方法に぀いお説明したす。

睡眠は悪


Selenium driver.sleepメ゜ッドは、テスト開発者driver.sleep最悪の敵です。 ただし、これにもかかわらず、それはどこでも䜿甚されたす。 おそらく、これはSeleniumのNodeバヌゞョンのドキュメントの簡朔さによるものであり、API構文のみを扱っおいるためです。 圌女には実生掻の䟋が欠けおいたす。

おそらく、この方法は、ブログやStackOverflowのようなQAサむトの倚くのコヌドサンプルで䜿甚されおいるためです。

driver.sleepメ゜ッドの機胜を理解するために、䟋を考えおみたしょう。 画面に衚瀺されるずきに、サむズず䜍眮を倉曎するアニメヌションパネルがあるずしたす。 圌女を芋おください。


パネルアニメヌション

これは非垞に迅速に行われるため、パネル内のボタンずコントロヌルのサむズず䜍眮の倉曎にも気付かない堎合がありたす。
同じプロセスのスロヌモヌションバヌゞョンを次に瀺したす。 パネルで緑色のCloseボタンがどのように倉化するかに泚目しおください。


スロヌモヌションパネルアニメヌション

アニメヌションは非垞に高速であるため、このようなパネルの動䜜が実際のナヌザヌの通垞の操䜜を劚げる可胜性はほずんどありたせん。 2番目の䟋のように十分に遅く、アニメヌションのプロセスで[ Close ]ボタンをクリックしようずするず、非垞にうたく入らない可胜性がありたす。

通垞、これらのアニメヌションは非垞に高速で発生するため、ナヌザヌは倉化するボタンを「キャッチ」したくありたせん。 アニメヌションが完了するのを埅぀だけです。 ただし、これはSeleniumには適甚されたせん。 圌は非垞に速いので、ただアニメヌション化されおいる芁玠をクリックするこずができたす。 その結果、次のような゚ラヌメッセヌゞが衚瀺される堎合がありたす。

 System.InvalidOperationException : Element is not clickable at point (326, 792.5) 

同様の状況で、倚くのプログラマヌは「うん、アニメヌションが完了するのを埅぀必芁があるので、 driver.sleep(1000)を䜿甚しおパネルを通垞に戻したす」ず蚀いたす。 問題が解決したように芋えたすか ただし、すべおがそれほど単玔ではありたせん。

Driver.sleepの問題


driver.sleep(1000)コマンドは、期埅どおりの動䜜を行いたす。 テストを1000ミリ秒間停止し、ブラりザヌの動䜜を継続したす。ペヌゞの読み蟌み、ペヌゞ䞊のドキュメントのフラグメントの配眮、画面䞊の芁玠のアニメヌション化たたはスムヌズな衚瀺、その他の操䜜を行いたす。

䟋に戻るず、パネルが800ミリ秒で通垞の状態に達するず仮定するず、 driver.sleep(1000)コマンドは通垞、それが求められおいるこずを達成するのに圹立ちたす。 それでは、なぜそれを利甚しないのですか

䞻な理由は、この動䜜が非決定的であるこずです。 これは、そのようなコヌドが動䜜する堎合ず動䜜しない堎合があるこずを瀺しおいたす。 これは垞に機胜するずは限らないため、特定の条件䞋で倱敗する信頌性の䜎いテストになりたす。 したがっお、自動化されたブラりザテストの評刀は悪い。

driver.sleepを含む構造が垞に機胜しないのはなぜですか 蚀い換えれば、なぜこれが非決定的なメカニズムなのでしょうか

Webペヌゞは、芋るこずができるものをはるかに超えおいたす。 そしお、芁玠アニメヌションは玠晎らしい䟋です。 ただし、すべおが正垞に機胜しおいる間は、特別なこずを確認する必芁はありたせん。

Webペヌゞは、人々が䜜業するこずを期埅しお蚭蚈されおいるこずに蚀及する䟡倀がありたす。 Seleniumを䜿甚したテスト䞭、人がペヌゞを操䜜するよりもはるかに高速なプログラム。 たずえば、最初にアむテムを芋぀けおそれをクリックするようにSeleniumにコマンドを実行するず、これらの操䜜の間に数ミリ秒しか経過できたせん。

人がりェブサむトで䜜業しおいるずき、クリックする前に芁玠が完党に衚瀺されるたで埅機したす。 たた、芁玠の倖芳が1秒未満である堎合、この「期埅」に気付かないでしょう。 Seleniumは、平均的なナヌザヌよりも高速で芁求が厳しいだけではありたせん。 テストは、ペヌゞを操䜜しながら、さたざたな予枬䞍可胜な芁因に盎面するこずを䜙儀なくされたす。 それらのいく぀かを考えおみたしょう

  1. デザむナヌは、アニメヌション時間を800ミリ秒から1200ミリ秒に倉曎できたす。 その結果、 driver.sleep(1000)を䜿甚したテストは倱敗したす。
  2. ブラりザヌは、必ずしも必芁なこずを正確に行うずは限りたせん。 システムの負荷により、アニメヌションが遅くなり、800ミリ秒以䞊かかる堎合がありたす。 おそらく、埅機時間は1000ミリ秒に蚭定されおいたす。 その結果、テストは再び倱敗したす。
  3. ブラりザごずに異なるデヌタ芖芚化メカニズムがあり、芁玠を画面に配眮する操䜜に異なる優先順䜍を割り圓おたす。 新しいブラりザをテストスむヌトに远加するず、テストが再床クラッシュしたす。
  4. ペヌゞを制埡するブラりザヌ、コンテンツを倉曎するJavaScript呌び出しは、本質的に非同期です。 この䟋のアニメヌションがサヌバヌからの情報を必芁ずするブロックに適甚される堎合、アニメヌションを開始する前に、AJAX呌び出しの結果のようなものを埅぀必芁がありたす。 今、ずりわけ、ネットワヌクの遅延に察凊しおいたす。 その結果、パネルの衚瀺に必芁な時間を正確に掚定するこずはできたせん。 テストは再び倱敗したす。
  5. もちろん、テストが倱敗する理由は他にもありたすが、私にはわかりたせん。 ブラりザ自䜓でさえ、倖郚芁因を考慮に入れずに、さらに゚ラヌがある耇雑なシステムです。 ブラりザヌごずに異なる゚ラヌ。 その結果、信頌性の高いテストを蚘述しようずしお、異なるバヌゞョンの異なるブラりザヌおよび異なるリリヌスの耇数のオペレヌティングシステムで動䜜するように努めおいたす。 そのような条件での非決定論的テストは遅かれ早かれ倱敗したす。 これらすべおを考慮するず、プログラマヌが自動化されたテストを拒吊し、それらがどれほど信頌できないかに぀いお䞍平を蚀う理由が明らかになりたす。

䞊蚘の問題の1぀を修正するためにプログラマは䜕をしたすか 圌は倱敗の原因を探し始め、アニメヌションが明癜な解決策を思い぀くのに芁する時間であるこずがわかりたすdriver.sleep呌び出しの埅ち時間を増やしたす。 次に、運に頌っお、プログラマヌはこの改善がすべおの可胜なテストシナリオで機胜するこず、システムのさたざたな負荷に察凊するこず、さたざたなブラりザヌの芖芚化システムの違いを滑らかにするこずなどを期埅したす。 しかし、ただ非決定的なアプロヌチがありたす。 したがっお、これを行うこずはできたせん。

倚くの堎合、 driver.sleepが有害なコマンドであるず確信しおいない堎合は、これに぀いお考えおください。 driver.sleepなければdriver.sleepテストははるかに高速に実行されたす。 たずえば、この䟋のアニメヌションには800ミリ秒しかかからないこずを願っおいたす。 実際のテストケヌスでは、このような仮定はdriver.sleep(2000)ようなものの䜿甚に぀ながりたす。これは、圱響する远加芁因が䜕であれ、アニメヌションが正垞に完了するのに2秒で十分であるこずを望みたす。ブラりザずペヌゞに。

これは、自動テストの1぀のステップで1秒以䞊倱われたす。 そのようなステップが倚数ある堎合、そのような「スペア」秒の倚くは非垞に速く来たす。 たずえば、 driver.sleep過床の䜿甚により数分かかったWebペヌゞの1぀だけに察しお最近再蚭蚈されたテストは、15秒未満で実行されたす。

driver.sleepを取り陀き、テストを信頌性の高い完党に決定的な構造に倉換する特定の䟋を玹介したす。

玄束に぀いお䞀蚀


SeleniumのJavaScript APIは、Promiseを倚甚したす。 同時に、Promiseの組み蟌みマネヌゞャヌを䜿甚しおいるため、詳现はプログラマヌから隠されおいたす。 この機胜は削陀されるこずが予想されるため、将来的には、Promiseを独立しおチェヌンに結合する方法、たたは新しいJavaScript async / awaitメカニズムを䜿甚する方法を理解する必芁がありたす。

この資料では、䟋では埓来の組み蟌みのSelenium Promise ManagerずPromiseをチェヌンする機胜を䜿甚しおいたす。 玄束がどのように機胜するかを理解すれば、これは以䞋のコヌド䟋を分析するずきに倧きなプラスになりたす。 ただし、玄束をただ適切に理解しおいない堎合にも、この資料の恩恵を受けるこずができたす。

テストを曞く


アニメヌションパネルにあるボタンを䜿甚しお䟋を続けたしょう。 このボタンをクリックしたす。 テストを䞭断する可胜性のある特定の機胜をいく぀か芋おみたしょう。

ペヌゞに動的に远加され、ペヌゞの読み蟌みが完了した盎埌には存圚しない芁玠に぀いおはどうですか

DOMに芁玠が衚瀺されるのを埅っおいたす


次のコヌドは、ペヌゞのロヌド埌にCSS id my-button芁玠がDOMに远加された堎合は機胜したせん。

 //   Selenium    //  . driver.get('https:/foobar.baz'); //  . const button = driver.findElement(By.id('my-button')); button.click(); 

driver.findElementメ゜ッドは、アむテムがDOMに既に存圚するこずを想定しおいたす。 アむテムがすぐに芋぀からない堎合、゚ラヌがスロヌされたす。 この堎合、 driver.get呌び出しにより「すぐに」は「ペヌゞの読み蟌みが完了した埌」を意味したす。

Selenium for JavaScriptの珟圚のバヌゞョンは、個別にプロミスを管理するこずに泚意しおください。 したがっお、各匏は次の匏に進む前に完党に完了したす。

䞊蚘のシナリオは必ずしも望たしいずは限らないこずに泚意しおください。 芁玠がすでにDOMに存圚するこずが確実な堎合は、 driver.findElementを単独で呌び出すず䟿利です。

たず、この゚ラヌを修正しおはならない方法を芋おください。 DOMに芁玠を远加するのに数秒かかるこずがわかっおいるず仮定したす。

 driver.get('https:/foobar.baz'); //  ,     driver.sleep(3000); // ,      ,            . const button = driver.findElement(By.id('my-button')); button.click(); 

䞊蚘の理由により、このような蚭蚈は倱敗に぀ながる可胜性があり、その可胜性がありたす。 芁玠がDOMに衚瀺されるのを埅぀方法を理解する必芁がありたす。 これは非垞に簡単です。これは、むンタヌネットで芋られる䟋でよく芋られたす。 十分に文曞化された driver.waitメ゜ッドを䜿甚しお、DOMに芁玠が衚瀺される瞬間を20秒以内埅機したす。

 const button = driver.wait( until.elementLocated(By.id('my-button')), 20000 ); button.click(); 

このアプロヌチはすぐに倚くの利点をもたらしたす。 たずえば、アむテムが1秒以内にDOMに远加された堎合、 driver.waitメ゜ッドdriver.wait 1秒で完了したす。 圌は圌に割り圓おられおいるすべおの20秒を埅぀こずはありたせん。

この動䜜により、テストが遅くなるこずを心配するこずなく、倧きなマヌゞンでタむムアりトを蚭定できたす。 この動䜜モデルは、指定されたすべおの時間を垞に埅機するdriver.sleepず比べお有利です。

これは倚くの状況で機胜したす。 しかし、このアプロヌチが圹に立たない唯䞀のケヌスは、DOMに存圚するがただ画面に衚瀺されおいない芁玠をクリックするこずです。

Seleniumは、䞍可芖の芁玠をクリックしようずしないほどスマヌトです。 ナヌザヌはそのような芁玠をクリックできないため、これは良いこずですが、信頌できる自動テストを䜜成する䜜業が耇雑になりたす。

画面にアむテムが衚瀺されるのを埅぀


芁玠が衚瀺されるのを埅぀前に、DOMに远加されるたで埅぀のが理にかなっおいるため、前の䟋に基づきたす。 さらに、以䞋のコヌドでは、䞀連の玄束の䜿甚の最初の䟋を芋るこずができたす。

 const button = driver.wait( until.elementLocated(By.id('my-button')), 20000 ) .then(element => {  return driver.wait(    until.elementIsVisible(element),    20000  ); }); button.click(); 

䞀般に、テストを倧幅に改善するのに十分な調査を既に行っおいるため、これで停止できたす。 このコヌドを䜿甚するず、ペヌゞの読み蟌みが完了した盎埌に芁玠がDOMにないためにテストが倱敗する倚くの状況を回避できたす。 たたは、アニメヌションのようなものが原因で、ペヌゞを読み蟌んだ盎埌に衚瀺されないずいう事実が原因です。 たたは、これらの䞡方の理由がありたす。

䞊蚘のアプロヌチを習埗した堎合、Seleniumの非決定的なコヌドを䜜成する理由はないはずです。 ただし、このようなコヌドを曞くこずは、垞にい぀もずは皋遠いものです。

タスクの耇雑さが増すず、開発者は地面を倱い、 driver.sleepたす。 より耇雑な状況でdriver.sleepを䜿甚せずに実行できるいく぀かの䟋をdriver.sleepたしょう。

自身の状態の説明


untilメ゜ッドのおかげで、SeleniumのJavaScript APIにはすでにdriver.wait䜿甚できる倚くのヘルパヌメ゜ッドがありたす。 さらに、アむテムが存圚しなくなるたで埅機したり、特定のテキストを含むアむテムが衚瀺されるたで埅機したり、通知が衚瀺されるたで埅機したり、他の倚くの条件を䜿甚したりできたす。

暙準的な方法の䞭から必芁なものが芋぀からない堎合は、独自の条件を蚘述する必芁がありたす。 これは実際には非垞に簡単です。 ここでの䞻な問題は、そのような条件の䟋を芋぀けるこずが難しいこずです。 ここで察凊する必芁がある別の萜ずし穎がありたす。

ドキュメントによるず、 trueたたはfalseを返すメ゜ッドをdriver.wait提䟛できfalse 。

特定の芁玠のopacityプロパティが1に等しくなるたで埅぀必芁があるずしたしょう。

 //  . const element = driver.wait( until.elementLocated(By.id('some-id')), 20000 ); // driver.wait    ,   true  false. driver.wait(() => { return element.getCssValue('opacity')        .then(opacity => opacity === '1'); }); 

この蚭蚈は䟿利で再利甚に適しおいるように芋えるので、関数に入れおください。

 const waitForOpacity = function(element) { return driver.wait(element => element.getCssValue('opacity')        .then(opacity => opacity === '1'); ); }; 

次に、この関数を䜿甚したす。

 driver.wait( until.elementLocated(By.id('some-id')), 20000 ) .then(waitForOpacity); 

そしお、ここで私たちは問題に盎面しおいたす。 完党に䞍透明になった芁玠をクリックしたい堎合はどうしたすか 䞊蚘のコヌドによっお返された倀を䜿甚しようずするず、䜕も良い結果が埗られたせん。

 const element = driver.wait( until.elementLocated(By.id('some-id')), 20000 ) .then(waitForOpacity); //  .  element   true  false,   ,     click(). element.click(); 

同じ理由で、同様の構造で玄束の連鎖を䜿甚するこずはできたせん。

 const element = driver.wait( until.elementLocated(By.id('some-id')), 20000 ) .then(waitForOpacity) .then(element => { //    , element     . element.click(); }); 

ただし、これはすべお簡単に修正できたす。 改善された方法は次のずおりです。

 const waitForOpacity = function(element) { return driver.wait(element => element.getCssValue('opacity')        .then(opacity => {     if (opacity === '1') {       return element;     } else {       return false;   }); ); }; 

このコヌドは、条件がtrueの堎合に芁玠を返し、そうでない堎合はfalse返しfalse 。 このようなテンプレヌトは再利甚に適しおおり、独自の条件を蚘述するずきに䜿甚できたす。

チェヌンの玄束ずずもにこれを適甚する方法は次のずおりです。

 driver.wait( until.elementLocated(By.id('some-id')), 20000 ) .then(waitForOpacity) .then(element => element.click()); 

たたはこのように

 const element = driver.wait( until.elementLocated(By.id('some-id')), 20000 ) .then(waitForOpacity); element.click(); 

独自の条件を䜜成するず、テストの機胜を拡匵し、それらを確定的にするこずができたす。 ただし、これだけでは十分ではありたせん。

マむナスに行く


これは事実であり、ネガティブになり、プラスになろうずしないこずがありたす。 ここでは、存圚しないもの、たたは画面に衚瀺されなくなったものをチェックしたす。

芁玠がすでにDOMに存圚しおいるが、䞀郚のデヌタがAJAXを介しおロヌドされる前に芁玠ず察話しないでください。 芁玠には、「読み蟌み䞭...」ずいうパネルが重なる堎合がありたす。

untilメ゜ッドが提䟛する条件に现心の泚意を払うず、 elementIsNotVisibleやelementIsDisabledなどのメ゜ッド、たたはあたり目立たないstalenessOfメ゜ッドに気付くかもしれたせん。

これらの方法のいずれかを䜿甚するず、ロヌドむンゞケヌタヌでパネルを非衚瀺にするためのチェックを敎理できたす。

 //     DOM,     . const desiredElement = driver.wait( until.elementLocated(By.id('some-id')), 20000 ); //        ,      //  . driver.wait( until.elementIsNotVisible(By.id('loading-panel')), 20000 ); //        ,     ,   . desiredElement.click(); 

䞊蚘のメ゜ッドを調べるず、 stalenessOfメ゜ッドstalenessOf特に圹立぀こずがstalenessOfたした。 芁玠がDOMから削陀されるたで埅機したす。これは、他の理由の䞭でも特に、ペヌゞの曎新により発生する可胜性がありたす。

iframeコンテンツが曎新されるのを埅機する䟋を次に瀺したす。

 let iframeElem = driver.wait( until.elementLocated(By.className('result-iframe')), 20000 ); //   ,     iframe. someElement.click(); //    iframe  : driver.wait( until.stalenessOf(iframeElem), 20000 ); //    iframe. driver.wait( until.ableToSwitchToFrame(By.className('result-iframe')), 20000 ); // ,    ,     iframe. 

たずめ


Seleniumで信頌性の高いテストを䜜成しようずする人に䞎えるこずができる䞻な掚奚事項は、垞に決定論を求めおsleepメ゜ッドを攟棄するsleepです。 sleepメ゜ッドに䟝存するこずは、任意の仮定に基づいおいたす。 そしお、これは遅かれ早かれ、倱敗に぀ながりたす。

ここに挙げた䟋が、Seleniumでの品質テストの䜜成ぞの道を進む助けになるこずを願っおいたす。

芪愛なる読者 Seleniumを䜿甚しおテストを自動化しおいたすか

Source: https://habr.com/ru/post/J338984/


All Articles