Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Codeception, write acceptance tests with the pageObject design pattern and gherkin

I'm looking for a simple example of code with the pageObject design pattern and gherkin because when I follow the codeception BDD documentation, all examples written in the tests/support/AcceptanceTester.php. I don't understand (poor English skills --) how not concentrate all code in the AcceptanceTester.php file.

For example, I have a sample home page with two buttons A and B. If the user clicks on button A, page A is loaded else if the user clicks on button B, page B is loaded.

Currently, my AcceptanceTester :

<?php // tests/_support/AcceptanceTester.php /**  * Inherited Methods  * @method void wantToTest($text)  * @method void wantTo($text)  * @method void execute($callable)  * @method void expectTo($prediction)  * @method void expect($prediction)  * @method void amGoingTo($argumentation)  * @method void am($role)  * @method void lookForwardTo($achieveValue)  * @method void comment($description)  * @method \Codeception\Lib\Friend haveFriend($name, $actorClass = NULL)  *  * @SuppressWarnings(PHPMD)  */  class AcceptanceTester extends \Codeception\Actor {     use _generated\AcceptanceTesterActions;      /**      * @Given The home page      */     public function inHomePage()     {         $this->amOnPage("/");         $this->seeInTitle('home');     }      /**      * @When I click on the button A      */     public function goToThePageA()     {         $this->click(['name' => 'A']);     }      /**      * @Then l go to the page A      */     public function ImInPageA()     {         $this->seeInTitle('page A');     }      /**      * @When I click on the button B      */     public function goToThePageB()     {         $this->click(['name' => 'B']);     }      /**      * @Then l go to the page B      */     public function ImInPageB()     {         $this->seeInTitle('page B');     } } 

If I run the command './vendor/bin/codecept run acceptance', all works like a charm. But as I said previously, I need to learn how don't concentrate all code in the AcceptanceTester file.

So, I created three pageObjects ; one for the home page, one for the page A and one for the page B. The code :

the home pageObject :

<?php // tests/_support/Page/PageHome.php namespace Page;  class PageHome {     public static $URL = '/home';     public static $title = "home";     public static $aButton = ['name' => 'A'] ;     public static $bButton = ['name' => 'B'] ;      public static function route($param){         return static::$URL.$param;     }      /**      * @var \AcceptanceTester;      */     protected $acceptanceTester;      public function __construct(\AcceptanceTester $I){         $this->acceptanceTester = $I;     } } 

the A pageObject :

<?php // tests/_support/Page/PageA.php namespace Page;  class PageA {     public static $URL = '/home/pageA';     public static $title = "page A";      public static function route($param){         return static::$URL.$param;     }      /**      * @var \AcceptanceTester;      */     protected $acceptanceTester;      public function __construct(\AcceptanceTester $I){         $this->acceptanceTester = $I;     } } 

And the B pageObject :

<?php // tests/_support/Page/PageB.php namespace Page;  class PageB {     public static $URL = '/home/pageB';     public static $title = "page B";      public static function route($param){         return static::$URL.$param;     }      /**      * @var \AcceptanceTester;      */     protected $acceptanceTester;      public function __construct(\AcceptanceTester $I){         $this->acceptanceTester = $I;     } } 

Then, I created three stepObjects ; homeChecker, goToPageA, goToPageB

The homeChecker stepObject :

<?php // tests/_support/Step/Acceptance/HomeChecker.php  namespace Step\Acceptance; use Page\Acceotance\HomePage;  class HomeChecker extends \AcceptanceTester {     /**      * @Given The home page      */     public function main()     {         $homePage = new PageHome($this);          $this->amOnPage($homePage::URL);         $this->checkTitle($homePage);         $this->checkButtons($homePage);     }      private function checkTitle($homePage){         $this->seeInTitle($homePage::$title);     }      private function checkButtons($homePage){         $this->see($homePage::$aButton);         $this->see($homePage::$bButton);     } } 

The PageAChecker stepObject :

<?php // tests/_support/Step/Acceptance/PageAChecker.php  namespace Step\Acceptance; use Page\PageHome; use Page\PageA;  class PageAChecker extends \AcceptanceTester {     /**      * @When I click on the button A      */     public function clickButton()     {         $homePage = new PageHome($this);         $this->click($homePage::$aButton);     }      /**      * @Then l go to the page A      */     public function checkTitle()     {         $aPage = new PageA($this);         $this->seeInTitle($aPage::$title);     }  } 

And the PageBChecker stepObject :

<?php // tests/_support/Step/Acceptance/PageBChecker.php  namespace Step\Acceptance; use Page\PageHome; use Page\PageB;  class PageBChecker extends \AcceptanceTester {     /**      * @When I click on the button B      */     public function clickButton()     {         $homePage = new PageHome($this);         $this->click($homePage::$bButton);     }      /**      * @Then l go to the page B      */     public function checkTitle()     {         $bPage = new PageB($this);         $this->seeInTitle($bPage::$title);     }  } 

And now, I don't know what I must do. If I empty my AcceptanceTester file and run again the './vendor/bin/codecept run acceptance' command, the test is incomplete and I get "not found in contexts" warnings in my shell :

enter image description here

What do I do?

Update I created a post in the codeception GitHub here :

https://github.com/Codeception/Codeception/issues/5157

I describe a minimal example of reproducing my issue and a (very) ugly resolution. I'm looking to getting a good way and understand why I described does not work!

like image 454
spacecodeur Avatar asked Sep 01 '18 22:09

spacecodeur


People also ask

What is acceptance testing in PHP?

Acceptance test verifies scenarios from a user's perspective. The application tested is accessed via either PhpBrowser or a real browser. In both cases the browsers are communicating via HTTP so application should be served via web server.


1 Answers

I get "not found in contexts" warnings in my shell

Ok, how to link gherkin files execution with steps defined in my own contexts classes (PageObjects, StepObjects, ...)? We can read chapter "BDD > Configuration" in Codeception documentation:

As we mentioned earlier, steps should be defined inside context classes. By default all the steps are defined inside an Actor class, for instance, AcceptanceTester. However, you can include more contexts. This can be configured inside global codeception.yml or suite configuration file:

gherkin:     contexts:         default:             - AcceptanceTester             - AdditionalSteps             - PageHome             - HomeChekcer 

(...) This way PageObjects, Helpers and StepObjects can become contexts as well.


Better

If we continue reading:

But more preferable to include context classes by their tags or roles.

This means that, bearing in mind escalability and good organization, you will not want to overload every tests with every Page Object. Therefore you can assign Page Object (or any assistant classes) by role, by tag or by paths. See next paragraphs on documentation. Following your example, and assigning by tag:

gherkin:    contexts:       default:          - AcceptanceTester       tag:          myTagX:              - Page\Acceotance\HomePage\HomeChecker              - Page\PageHome          anotherTag:              - Page\Acceotance\another\AnotherChecker              - Page\PageAnother 

...and in gherkin files:

@myTagX Feature (...) 
like image 150
Katapofatico Avatar answered Oct 03 '22 04:10

Katapofatico