PhalconアプリケーションをCodeceptionでテストしてみた

先日、Codeceptionが1.8にバージョンアップされました。

1.8での変更点の詳細は本家サイトを見ていただくとして、注目すべきは以下の2点。

1つ目は説明不要と思いますが、2つ目は前回のエントリ (Codeception + Selenium2) Acceptance Testに複数種類のブラウザを利用する - think it over の最後に書いた、以下の課題に対する解決策となっています。

複数種類のブラウザを利用してAcceptance Testを実行したい場合、現状では一つのSuitesにつき一種類のブラウザしか指定ができないため、複数Suitesを用意するしかないようです。

前回からの続きで言うと2つ目を取り上げるべきなのでしょうが、Phalconが楽しそうなので先にそちらを。

0. 前提

1. Phalconアプリケーションの準備

1.1. 素材の取得

素材として phalcon/invo · GitHub を利用します。

$ git clone https://github.com/phalcon/invo.git
1.2. DBの初期化
$ echo 'CREATE DATABASE invo' | mysql -u root -p
$ cat schemas/invo.sql | mysql -u root -p invo
1.3. DB接続設定の変更

app/config/config.ini の以下の箇所を適切な接続設定となるよう編集します。

[database]
host     = localhost
username = root
password = secret
name     = invo
1.4. 基底URLの変更

ビルトインサーバーで動作確認をしたいので、
app/config/config.ini の applicationセクションのbaseUrlを以下のように変更します。

[application]
(中略)
baseUri        = /
1.5. ビルトインサーバー用のルーターファイルを作成

Using PHP Built-in webserver — Phalcon 1.2.4 documentation を参考に、invo直下に以下の内容で.htrouter.phpを作成します。

<?php
if (!file_exists(__DIR__ . '/' . $_SERVER['REQUEST_URI'])) {
    $_GET['_url'] = $_SERVER['REQUEST_URI'];
}
return false;
1.6. 動作確認

以下のコマンドでビルトインサーバーを起動します。

$ php -S localhost:8000 -t ./public .htrouter.php

ブラウザから http://localhost:8000にアクセスし、次のような画面が表示されることを確認します。


2. Codeceptionの準備

2.1. インストール・初期化

Composerは時間かかるので、今回はpharを使います。

$ curl -L -O http://codeception.com/codecept.phar

ダウンロードできたら、初期化します。

$ php codecept.phar bootstrap
2.2. DB接続設定

本来であればテスト用DBを別で用意したいところですが、PhalconにはSymfonyで言うところの「env」の概念が備わってなくようなので、今回は上で用意したDBを使います。

modules:
    config:
        Db:
            dsn: 'mysql:host=localhost;dbname=invo'
            user: 'root'
            password: 'your password'
            dump: schemas/invo.sql

dump にはテストデータ投入用のSQLを指定するのですが、invoに同梱されていたものにテストデータが入っているのでそれを使っちゃいましょう。

2.3. Functionalテスト設定の変更

tests/functional.suite.ymlを以下のように編集します。

class_name: TestGuy
modules:
    enabled: [Filesystem, TestHelper, Phalcon1, Db]
    config:
        Phalcon1:
            bootstrap: tests/phalcon_bootstrap.php
            cleanup: true
            savepoints: true

編集後、Guyをビルドします。

$ php codecept.phar build
2.4. CodeceptionがPhalconをテストするためのbootstrapファイルを作成

Phalcon1 Module - Codeception - Documentation にもbootstrapファイルに関する記述がありますが、そんな単純ではなかったです。

ちょっと悩みましたが、以下のようにするのが良いとわかりました。

public/index.phptests/phalcon_bootstrap.phpにコピーし、以下の変更を行います。

82行目付近
voltテンプレートのキャッシュの保存ディレクトリのパスを以下のように変更します。

            "compiledPath" => "../cache/volt/"

            "compiledPath" => "./cache/volt/"


141行目付近
Phalcon1 Module - Codeception - Documentation によると、

The application bootstrap file must return Application object but not call its handle() method.

だそうなので、以下のように変更します。

echo $application->handle()->getContent();

return $application;


これでPhalcon, Codeception共に準備完了です。

3. トップページをテストしてみる

以下のコマンドでテストを作成します。

$ php codecept.phar generate:cept functional IndexController/indexAction

作成された tests/functional/IndexController/indexActionCept.php を以下のように編集します。

<?php
$I = new TestGuy($scenario);
$I->wantTo('test top page');

$I->amOnPage('/');
$I->see('Welcome to INVO', 'h1');

実行します。

$ php codecept.phar generate:cept run functional -d
Codeception PHP Testing Framework v1.8.0.1
Powered by PHPUnit 3.7.28 by Sebastian Bergmann.

Functional Tests (1) -----------------------------------------------
Modules: Filesystem, TestHelper, Phalcon1
--------------------------------------------------------------------
Trying to test top (IndexController\indexActionCept.php)
Scenario:
* I am on page "/"
  [Response] 200
  [Page] http://localhost/
* I see "Welcome to INVO","h1"
 PASSED

--------------------------------------------------------------------


Time: 558 ms, Memory: 7.50Mb

OK (1 test, 1 assertion)

無事成功しました。

4. 登録フォームをテストしてみる

以下のコマンドでテストを作成します。

$ php codecept.phar generate:cept functional SessionController/registerAction

作成された tests/functional/SessionController/registerActionCept.php を以下のように編集します。

<?php
$I = new TestGuy($scenario);
$I->wantTo('test registration form');

$I->amOnPage('/session/register');
$I->fillField('Your Full Name', 'Phalcon Codeception');
$I->fillField('Username', 'phalcon_codeception');
$I->fillField('Email Address', 'demo@example.com');
$I->fillField('Password', 'demo');
$I->fillField('Repeat Password', 'demo');
$I->click("Register");

$I->seeCurrentUrlEquals('/session/register');
$I->seeRecord('Users', ['name' => 'Phalcon Codeception']);

実行します。

$ php codecept.phar run functional SessionController
Codeception PHP Testing Framework v1.8.0.1
Powered by PHPUnit 3.7.28 by Sebastian Bergmann.

Functional Tests (1) -------------------------------------------------
Trying to test registration form (\registerActionCept.php)
Scenario:
* I am on page "/session/register"
* I fill field "Your Full Name","Phalcon Codeception"
* I fill field "Username","phalcon_codeception"
* I fill field "Email Address","demo@example.com"
* I fill field "Password","demo"
* I fill field "Repeat Password","demo"
* I click "Register"
* I see current url equals "/session/register"
* I see record "Users",{"name":"Phalcon Codeception"}
 PASSED

----------------------------------------------------------------------


Time: 1.23 seconds, Memory: 8.25Mb

OK (1 test, 1 assertion)

問題なくテストにパスしました。

5. 最後に

以上、簡単ですが、PhalconアプリケーションもCodeceptionでテストできるようになりました。
フレームワークが変わっても基本的なテストの書き方は一緒。これは本当に素晴らしいです。
もう自分はCodeceptionから離れられません。

(2013/11/22 追記)
 コードを GitHubにアップしました。