JenkinsでCakeBehat

Behat/Minkのテストはブラウザでアクセスされるので、テスト時はtestデータソースを使用するように工夫が必要。
The Opera blog
あと、アクセス先のテスト用DBの初期化、後始末が必要。

も一つ、ciサーバ内で完結するなら、ciサーバ上でのwebサーバ設定が必要。
もしくは、ciサーバ上から別サーバ上にアクセスする場合、git hook時に別サーバ上のソースの更新とDBの(ry
面倒なので、ciサーバで完結できるようにする


phantomjs, Migrasionsプラグイン

実装

ホスト名がtestから始まっていた場合は、testデータソースを使用する。
app/Config/database.php

<?php
    public function __construct()
    {
        $env = env('CAKE_ENV');
        if ($this->__isCakeBehatAccess()) {
            $env = 'test';
        }

        if (property_exists(__CLASS__, $env)) {
            $this->default = $this->{$env};
        } else {
            $this->default = $this->production;
        }
    }

    private function __isCakeBehatAccess()
    {
        $server = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : '';
        if (strpos($server, 'test') === 0) {

            return true;
        }

        return false;
    }


テスト用DBの初期化、後始末を行う
app/Test/features/bootstrap/FeatureContext.php

<?php

    /**
     * @BeforeSuite
     */
    public static function setup($event)
    {
        $fmt = '(cd %s && bash ./Console/cake Migrations.migration run all -c test)';
        $cmd = sprintf($fmt, APP);
        exec($cmd);
    }

    /**
     * @AfterSuite
     */
    public static function teardown($event)
    {
        $tables = array();
        $db = ConnectionManager::getDataSource('test');
        $db->cacheSources = false;
        $usePrefix = empty($db->config['prefix']) ? '' : $db->config['prefix'];
        if ($usePrefix) {
            foreach ($db->listSources() as $table) {
                if (!strncmp($table, $usePrefix, strlen($usePrefix))) {
                    $tables[] = substr($table, strlen($usePrefix));
                }
            }
        } else {
            $tables = $db->listSources();
        }

        $fmt = 'DROP TABLE %s;';
        foreach ($tables as $t) {
            $sql = sprintf($fmt, $db->fullTableName($t));
            $db->execute($sql);
        }
    }

設定とか

app/Config/behat.yaml

default:
  context:
    parameters:
      # TODO base_urlがDRYじゃない
      base_url: 'http://test.example.com/'
  extensions:
    Behat\MinkExtension\Extension:
      base_url: 'http://test.example.com/'
      goutte:    ~
      selenium2:
        wd_host: "http://localhost:8643/wd/hub"

build.xml

<?xml version="1.0" encoding="utf-8"?>
<project name="project" default="behat">

    <target name="behat" depends="init, start_phontomjs, submodule_update, cakebehat, stop_phontomjs"></target>

    <target name="init" >
        <delete dir= "./reports" includeemptydirs= "true" />
        <mkdir dir= "./reports" />
    </target>

    <target name="submodule_update">
        <exec executable="git" >
            <arg line="submodule update --init --recursive" />
        </exec>
    </target>

    <target name="cakebehat" depends= "install_behat, change_tmp_permision">
        <exec executable="./lib/Cake/Console/cake" >
            <arg line=" CakeBehat.bdd
                --config ./app/Config/behat.yml
                --profile default
                --format junit
                --out ./reports/" />
        </exec>
    </target>

    <target name="change_tmp_permision">
        <exec command="find tmp -type d | xargs chmod 0777" dir="./app/" />
    </target>

    <target name="install_behat" depends= "install_composer">
        <exec command="php composer.phar install" dir="./app/Plugin/CakeBehat" />
    </target>

    <target name="install_composer">
        <exec command="curl http://getcomposer.org/installer | php" dir="./app/Plugin/CakeBehat" />
    </target>

    <target name="start_phontomjs">
        <exec command="/usr/local/bin/phantomjs --webdriver=8643 >/dev/null 2>&amp;1 &amp;" />
    </target>

    <target name="stop_phontomjs">
        <exec command="killall phantomjs" />
    </target>
</project>


全体的にかなり力技。もっとスマートなやり方があるんじゃまいか?

他のテストでphantomjsが走ってたら、killallはまずい。。