Behat Mink跑js

2016-08-05

准备工作

composer.json 文件需要安装:

{
    "require-dev": {
        "behat/behat": "^3.1",
        "behat/mink": "^1.7",
        "behat/mink-extension": "^2.2",
        "behat/mink-goutte-driver": "^1.2",
        "behat/mink-selenium2-driver": "^1.3",
    }
}

laravel框架需要

        "laracasts/behat-laravel-extension": "^1.0",

要测试网页,一般来说可安装数个driver,不同的driver可适用于不同的场景。

Goutte Driver速度快,不能执行js。
Selenium2 Driver可以执行js,但略慢。
Zombie Dirver可以执行js,且快,要跑起来需要安装node.js。有点麻烦,暂时忽略。

这里用Selenium2 Driver,先下载selenium server,是个jar包,启动它,当做背景放着它就行。

java -jar ~/Downloads/selenium-server-standalone-3.0.0-beta2.jar > /dev/null &

默认Selenium2会启动firefoxDriver,随jar包一起,不知道我为什么不行,这里用了chromeDriver,用brew安装

brew install chromedriver

安装成功后,在跑behat的时候,会自动打开一个chrome浏览器,自动执行操作。

配置

behat.yml配置文件1

#behat.yml
default:
    extensions:
        Behat\MinkExtension:
            base_url: http://xfcrm.zhangshan.dev.anhouse.com.cn
            browser_name: chrome
            goutte: ~
            selenium2:
                wd_host: 'http://127.0.0.1:4444/wd/hub'
  • base_url - 默认主页。
  • goutte - 驱动
  • selenium2 - 驱动,需要一些定制化
  • browser_name - 这里用的是chrome
    其它MinkExtension配置用到的参数可参考:url

.feature文件里,会涉及到js的Scenario前加上tag @javascript 如:

    @javascript
    Scenario: 订单列表页表单表头
        When I press button "查询"
        Then I should see "客户姓名"
        Then I should see "客户手机"
        Then I should see "项目名称"

在测试到这个场景的时候,会自动打开chromedriver自行进行测试。

代码

FeatureContext文件需要继承MinkContext

#FeatureContext.php
<?php
use Behat\MinkExtension\Context\MinkContext;

/**
 * Features context.
 */
class FeatureContext extends MinkContext
{
}

js执行有时差,需要页面载入完全后才能触发js,这时可以发送命令等待5秒后再执行。如:

/**
 * @Then /^I wait for the suggestion box to appear$/
 */
public function iWaitForTheSuggestionBoxToAppear()
{
    $this->getSession()->wait(5000,
        "$('.suggestions-results').children().length > 0"
    );
}

也可以用 2(钩子), 在需要执行js的步骤前后发送请求,令其等待。

如下:

    /**
     * @AfterStep
     */
    public function afterStep($event)
    {
        // 点击链接,等待异步加载
        $text = $event->getStep()->getText();
        if (preg_match('/(follow|press|click|submit)/i', $text)) {
            sleep(5);
        }
    }

其中sleep(5) 和 下面wait(5000) 的效果是一样的,都是强制等待5秒。

$this->getSession()->wait(5000);

而以下这种等到是5秒或者 $('.suggestions-results').children().length > 0 的条件为true。可以避免每个页面都等待5秒。

    $this->getSession()->wait(5000,
        "$('.suggestions-results').children().length > 0"
    );

References & Further Readings