dsa2c2255888 2018-09-01 22:40
浏览 48

Codeception,使用pageObject设计模式和小黄瓜编写验收测试

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.

By example, I have a sample home page with two buttons A and B. If the user click on the button A, the page A is loaded else if the user click on button B, the 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 want 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 for reproduce my issue and a (very) ugly resolution. I'm looking for get the good way and understand why I described does not work !

  • 写回答

1条回答 默认 最新

  • dongwei5794 2019-06-18 19:31
    关注

    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
    (...)
    
    评论

报告相同问题?

悬赏问题

  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示
  • ¥15 求三国群英传pl国战时间的修改方法
  • ¥15 matlab代码代写,需写出详细代码,代价私
  • ¥15 ROS系统搭建请教(跨境电商用途)
  • ¥15 AIC3204的示例代码有吗,想用AIC3204测量血氧,找不到相关的代码。