php - Codeception,使用 pageObject 设计模式和小 cucumber 编写验收测试

标签 php codeception gherkin pageobjects

我正在寻找带有 pageObject 设计模式和小 cucumber 的简单代码示例,因为当我遵循 the codeception BDD documentation 时,所有示例都写在 tests/support/AcceptanceTester.php 中。我不明白(糟糕的英语水平 --)如何不将所有代码集中在 AcceptanceTester.php 文件中。

例如,我有一个包含两个按钮 A 和 B 的示例主页。如果用户单击按钮 A,则加载页面 A,否则如果用户单击按钮 B,则加载页面 B。

目前,我的验收测试员:

<?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');
    }
}

如果我运行命令“./vendor/bin/codecept run acceptance”,一切都非常有效。但正如我之前所说,我需要了解如何不将所有代码都集中在 AcceptanceTester 文件中。

因此,我创建了三个 pageObjects;一个用于主页,一个用于页面 A,一个用于页面 B。代码:

主页对象 :

<?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;
    }
}

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;
    }
}

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;
    }
}

然后,我创建了三个 stepObjects ; homeChecker、goToPageA、goToPageB

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);
    }
}

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);
    }

}

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);
    }

}

现在,我不知道我必须做什么。如果我清空我的 AcceptanceTester 文件并再次运行“./vendor/bin/codecept run acceptance”命令,则测试不完整并且我在 shell 中收到“未在上下文中找到”警告:

enter image description here

我该怎么办?

更新 我在这里的 codeception GitHub 中创建了一个帖子:

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

我描述了一个重现我的问题的最小示例和一个(非常)丑陋的解决方案。我正在寻找一个好的方法并理解为什么我描述的不起作用!

最佳答案

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

好的,如何将 gherkin 文件的执行与我自己的上下文类(PageObjects、StepObjects 等)中定义的步骤联系起来?我们可以阅读 Codeception 文档中的章节“BDD > Configuration”:

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.


更好

如果我们继续阅读:

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

这意味着,考虑到可扩展性和良好的组织,您不希望每个页面对象的每个测试都过载。因此,您可以按角色、标签或路径分配页面对象(或任何辅助类)。请参阅有关文档的下一段。按照您的示例,并按标签分配:

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

...在小 cucumber 文件中:

@myTagX
Feature
(...)

关于php - Codeception,使用 pageObject 设计模式和小 cucumber 编写验收测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52132683/

相关文章:

javascript - php返回带有angularjs错误的json

linux - 如何在 Linux 终端中使用 Python Behave 创建 Hello World 测试?

cucumber - 如何创建 cucumber 数据表?

php - PHP解析错误: syntax error, unexpected T_ECHO in

php - 如何将我的数据库特定列值插入 View 页面中的列表

如果超过 5mb,PHP 将停止远程文件下载

php - 我可以使用Codeception在首页上查找损坏的资源吗?

php - 如何在Codeception\Util\Stub中正确使用atLeastOnce方法?

testing - Codeception Cest 继承

Java-Maven- cucumber : Feature file is not able to run