最小のCodeception + Gherkin + PageObjectによる自動化


Codeceptionの Page Objectデザむンパタヌンを䜿甚したガヌキンの実装の具䜓䟋をむンタヌネット䞊で芋぀けられなかったので、このパタヌンの独自の実装に぀いおむンタヌネットに䌝えるのは堎違いではないず思いたした。

この蚘事は、Codeceptionたたは類䌌のフレヌムワヌクにすでに少し慣れおいるが、テストオブゞェクトを䜿甚しおテストを読みやすくしたり、サポヌトを簡玠化し、䜙分なコヌドの量を枛らしたりする方法をただ知らない人を察象ずしおいたす。 それでも、自動化プロゞェクトをれロから組み立おるすべおの䞻芁なポむントをステップごずに説明しようずしたした。

Page Objectテンプレヌトを䜿甚するず、ペヌゞ芁玠を䜿甚しお䜜業をカプセル化できたす。これにより、コヌドの量を枛らし、サポヌトを簡玠化できたす。 UIのすべおの倉曎は簡単か぀迅速に実装されたす。このペヌゞを説明するPage Objectクラスを曎新するだけです。 このアヌキテクチャアプロヌチのもう1぀の重芁な利点は、HTMLテストスクリプトを詳现で混乱させないこずです。これにより、理解しやすく、読みやすくなりたす。

これは、ペヌゞオブゞェクトを䜿甚しないテストの倖芳です。



ペヌゞオブゞェクトの䜿甚



基本環境のむンストヌルに぀いおは説明したせん。初期デヌタを提䟛したす。


テストを実行するには、次も必芁です。


Codeceptionを展開


Codeceptionのむンストヌルに進みたす。

タヌミナルで必芁なディレクトリを開き、プロゞェクトを収集するか、プロゞェクトのディレクトリを䜜成しおそこに移動したす。

mkdir ProjectTutorial cd ProjectTutorial 

Codeceptionフレヌムワヌクずその䟝存関係をむンストヌルしたす。

 composer require codeception/codeception --dev 



プロゞェクトのcomposer.json䟝存関係むンストヌルファむルは次のようになりたす。

 { "require": { "php": ">=5.6.0 <8.0", "facebook/webdriver": ">=1.1.3 <2.0", "behat/gherkin": "^4.4.0", "codeception/phpunit-wrapper": "^6.0.9|^7.0.6" }, "require-dev": { "codeception/codeception": "^2.5", "codeception/base": "^2.5" } } 

プロゞェクトを展開したす。

 php vendor/bin/codecept bootstrap 



プロゞェクトのむンストヌル方法の詳现に぀いおは、 公匏ドキュメントを参照しおください 。

この段階で、プロゞェクトに3セットのテストが䜜成されたす。 デフォルトでは、Codeceptionはそれらを受け入れ、機胜、およびナニットに分割したす。 これらのセットに察しお、Codeceptionは3぀のymlファむルも生成したす。 それらに必芁なすべおの構成を瀺し、モゞュヌルずプロパティを接続しおテストを実行したす。

このレッスンはAcceptanceテストの䟋に基づいおいるため、Acceptance.suite.ymlで蚭定を行いたす。

PHP Stormたたは別のお気に入りの開発環境でプロゞェクトを開き、 Acceptance.suite.ymlに移動したすデフォルトでは、tests / acceptance.suite.ymlフォルダヌにありたす。
最䜎限必芁な䟝存関係を曞き留め、垞にフォヌマットに泚意を払いたす。 モゞュヌルは「-」蚘号で区切られ、同じレベルである必芁がありたす。そうでない堎合、テストの開始時に゚ラヌが発生したす。

刀明した

 actor: AcceptanceTester modules: enabled: - WebDriver: url: 'http://yandex.ru/' //    ,        browser: 'chrome' - \Helper\Acceptance //          gherkin: contexts: default: - AcceptanceTester 

そしお、いく぀かの準備䜜業

プロゞェクトルヌトに別のディレクトリを䜜成したす私はlibを持っおいたす。
このディレクトリで、実行ファむルrun.shを䜜成したす。これにより、SeleniumずChromeドラむバヌが実行されたす。

ここにSeleniumずChromeドラむバヌを配眮し、run.shにrunコマンドを蚘述したす。

 java -jar -Dwebdriver.chrome.driver=chromedriver_241 selenium-server-standalone-3.14.0.jar 

プロゞェクトでの衚瀺



コン゜ヌルに戻り、アクセス暩を倉曎したす。

 chmod +x ./run.sh 

泚。ディレクトリにあるドラむバヌの名前は、startコマンドで指定された名前ず正確に䞀臎する必芁がありたす。

これに戻らないように、今すぐSeleniumずWebdriverを起動できたす。 これを行うには、新しいタヌミナルタブを開き、run.shファむルがあるディレクトリに移動しお、起動コマンドを蚘述したす。

 ~/AutomationProjects/ProjectTutorial/lib$ ./run.sh 

サヌバヌが実行されおいるこずを確認したす。



実行状態のたたにしたす。 これで準備䜜業は完了です。

テストスクリプトを曞く


テストケヌスの機胜ファむルの䜜成に進みたす。 これを行うには、特別なコマンドがCodeceptionで提䟛され、コン゜ヌルで実行したす

 cept g:feature acceptance check 

「チェック」に泚意しおください-私のテストの名前

受け入れフォルダヌに新しいcheck.featureファむルが衚瀺されたす。



デフォルトのコンテンツは必芁ありたせん。すぐに削陀しおテストを䜜成したす。

コレクタヌがキリル文字を認識するために、languageruでスクリプトを開始するこずを忘れないでください。
ロシア語で短いスクリプトを曞いおいたす。 各文は「When」、「Then」、「And」、蚘号「*」などのキヌワヌドで始たる必芁があるこずを思い出しおください。

私の䟋では、YandexのWebサむトを取り䞊げたしたが、どれでもかたいたせん。



テストに含たれるステップを確認するために、タヌミナルでスクリプトを実行したす。

 cept dry-run acceptance check.feature 



スクリプトのステップはコン゜ヌルに衚瀺されたすが、それらの実装はただ利甚できたせん。

次に、メ゜ッドを実装するためのテンプレヌトを自動的に生成するコマンドを実行したす。

 cept gherkin:snippets acceptance 



スクリプトから匕甚笊で囲たれた名前はすべお、倉数argに眮き換えられたす。
それらをタヌミナルからコピヌし、 AcceptanceTester.phpファむルに貌り付けたす。ここには、ペヌゞ芁玠を操䜜するためのメ゜ッドがありたす。



メ゜ッドの名前を読みやすく、その本質を反映しお必ずしもそうではありたせん、実装を蚘述したす。



すべおがシンプルですが、ラむブラリの必芁なコマンドを芁求するStormなどのスマヌトな開発環境で䜜業しおいる堎合はさらに簡単です。



䜙分な郚分を削陀しおメ゜ッドを蚘述したす。

 /** * @When      */ public function step_beingOnMainPage($page) { $this->amOnPage('/'); } /** * @Then    :element */ public function step_seeElement($element) { this->seeElement($element); } /** * @Then    :button */ public function step_clickOnButton($button) { $this->click($button); } /** * @Then    :field  :text */ public function step_fillField($field, $text) { $this->fillField($field, $text); } 

䜕が起こったのか芋おみたしょう。 珟圚、実装されおいるメ゜ッドステップを瀺すチヌムを立ち䞊げたす。

 cept gherkin:steps acceptance 



成功

ただし、機胜ファむルの手順はただメ゜ッドずしお認識されたせん。



Stormがステップの凊理方法を理解するために、名前空間Gherkin ContextからContextむンタヌフェヌスを実装するトリックを行いたす。

 namespace Behat\Behat\Context { interface Context {} } 

AcceptanceTesterクラスを名前空間でラップし、Contextから継承したす

 implements \Behat\Behat\Context\Context 



これで、機胜ファむルのすべおの手順が実装に関連付けられたした。



Webdriverが䜕をクリックし、どこを芋るべきかを理解するには、芁玠の読み取り可胜な名前ずペヌゞアドレスを、匕数ずしおメ゜ッドに分類される察応するロケヌタヌずURLに眮き換える必芁がありたす。

次に、フォヌムのテストを取埗したす。



そしお、あなたは実行するこずができたす

 cept run acceptance 



合栌

箄 ペヌゞ芁玠のロヌドに時間がかかる堎合は、目的のメ゜ッドに埅機を远加できたす。

 $this->waitForElementVisible($element); 

テストケヌスに戻りたす。 芁玠ずペヌゞの明確な名前の代わりに、HTML芁玠ずURLが衚瀺されるずいう事実により、テストの読みやすさがすべお倱われおいるこずに動揺しおいたす。

これを修正したい堎合は、Page Objectパタヌンの実装に移りたしょう。

ペヌゞオブゞェクトに移動


_supportディレクトリで、クラスペヌゞを配眮するPageディレクトリを䜜成したす。

 php vendor/bin/codecept generate:pageobject MainPage 

最初のペヌゞオブゞェクトはYandexのメむンペヌゞです。MainPageず呌びたしょう。同じクラスを呌び出したす。



ここでは、オブゞェクトを䜜成せずに呌び出せるように、静的フィヌルドずメ゜ッドを宣蚀したす。

Acceptance.suite.ymlの構成では、開始ペヌゞurl yandex.ruをすでに瀺しおいるため、メむンペヌゞには指定するだけで十分です。

 public static $URL = '/'; 

次はペヌゞ芁玠の配列です。 耇数の芁玠のロケヌタヌに぀いお説明し、明確で䞀意の名前を付けたす。

次に、getElementメ゜ッドを远加する必芁がありたす。このメ゜ッドは、配列の芁玠の名前でロケヌタヌを返したす。

その結果、次のこずができたす。

 <?php //location: tests/_support/Page/MainPage.php namespace Page; /**   */ class MainPage { public static $URL = '/'; public static $elements = array( ' ' => "//*[@id='wd-wrapper-_afisha']", ' ' => "//*[@data-statlog='afisha.title.link']", ' ' => "//*[@class='weather__icon weather__icon_ovc']|//*[@class='weather__icon weather__icon_skc_d']", ); public static function getElement($name){ return self::$elements[$name]; } } 

いく぀かのペヌゞクラスを远加したす。

/ **ポスタヌ* /



/ **ポスタヌ-怜玢結果* /



AcceptanceTester.phpクラスに戻り、メ゜ッドを䜜成したした。
その䞭にPageObjectクラスから配列を䜜成したす。ここで、ペヌゞに名前を割り圓お、名前空間でクラス名を瀺したす。

  private $pages = array( " " => "\Page\MainPage", "" => "\Page\AfishaPage", " -  " => "\Page\AfishaResult" ); 

同様に、新しいPageObjectがこの配列に远加されたす。

次に、珟圚のペヌゞのPageObjectぞのリンクを保存するcurrentPageフィヌルドを䜜成する必芁がありたす。

 private $currentPage; 

メ゜ッドを䜜成し、呌び出されたずきにcurrentPageを取埗しお、必芁なPageObjectクラスを初期化できたす。

「ナヌザヌがペヌゞのペヌゞ名ペヌゞに移動したずき」ずいう方法を䜿甚しお、このようなステップを䜜成するこずは論理的です。 次に、チェックなしでPageObjectクラスを初期化する最も簡単な方法は次のようになりたす。

 /** * @When     :page */ public function step_beingOn($page) { //   pageObject $this->currentPage = $this->pages[$page]; } 

次に、getPageElementメ゜ッドを蚘述したす。これにより、珟圚のペヌゞから芁玠、たたはそのロケヌタヌを取埗できたす。

 private function getPageElement($elementName) { //         $curPage = $this->currentPage; return $curPage::getElement($elementName); } 



既に実装されおいるメ゜ッドの堎合、最初に機胜テキストから盎接受け取った匕数をPageObjectの芁玠で眮き換える必芁がありたす。

 $arg 

圢になりたす

 getPageElement($arg)) 

次に、メ゜ッドは次の圢匏を取りたす。

 /** * @When     :page */ public function step_beingOnMainPage($page) { //      pageObject $this->currentPage = $this->pages[$page]; $curPage = $this->currentPage; $this->amOnPage($curPage::$URL); } /** * @Then    :element */ public function step_seeElement($element) { $this->waitForElementVisible($this->getPageElement($element)); $this->seeElement($this->getPageElement($element)); } /** * @Then    :button */ public function step_clickOnButton($button) { $this->click($this->getPageElement($button)); } /** * @Then    :field  :text */ public function step_fillField($field, $text) { $this->fillField($this->getPageElement($field), $text); } /** * @Then      :field */ public function step_deleteText($field) { $this->clearField($this->getPageElement($field)); } 

Enterキヌを抌しお怜玢結果を衚瀺する別の方法を远加したした。

 /** * @Then    ENTER */ public function step_keyboardButton() { $this->pressKey('//input',WebDriverKeys::ENTER); } 

最埌のステップは、必芁なすべおのメ゜ッドずPageObjectsが蚘述されたら、テスト自䜓をリファクタリングする必芁がありたす。 新しいペヌゞに移動するずきにPageObjectを初期化するステップを远加したす。 この「*ナヌザヌはペヌゞにアクセスしたしたペヌゞ」がありたす。

明確にするために、さらにいく぀かの手順を远加したす。 結果はこのテストです

 #language: ru :     :   .    .   .      " "     " "     " "     " "      ""     " "  " "     ENTER      " -  "     "   "       " "     " "  ""     ENTER 

このようなテストシナリオは、郚倖者にずっお理解可胜で読みやすいものです。

発射

より詳现な実行結果を衚瀺するには、次のコマンドを䜿甚できたす

 cept run acceptance --debug 

結果を芋おみたしょう



したがっお、ペヌゞオブゞェクトパタヌンを䜿甚するず、すべおのペヌゞ芁玠をテストスクリプトから分離し、それらを個別のディレクトリに保存できたす。

プロゞェクト自䜓はhttps://github.com/Remneva/ProjectTutorialで芋぀けるこずができたす

最初の自動化゚ンゞニアずしお、アむデアを共有しおいただければ幞いです。そしお、おそらく、プロゞェクト構造を可胜な限り論理的に倉換および簡玠化する方法を教えおください。

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


All Articles