2015-12-14

codeceptionでphalconの単体テストしてみた【FunctionalTests編】

前回はincubatorUnitTestsな単体テストをしましたが、今回はFunctionalTestsの方でトライしてみます。 codeceptionのインストールは前回の記事を参照してください。

codeceptionの設定

Phalconアプリケーションを返すようなbootstrapファイルを作成する必要があります(_bootstrapとは別)。tests内にapi_boostrap.phpを以下の内容で作成してください。
<?php
$config = include APP_PATH . "/app/config/config.php";
include APP_PATH . "/app/config/loader.php";
include APP_PATH . "/app/config/services.php";
return new \Phalcon\Mvc\Application($di);
?>

APP_PATHはルートの_bootstrapファイルに定義しています。ここで定義したDIコンテナやアプリケーションがテスト内で利用されることになります。

APIのテスト

PhalconでAPIを作成する際のテスト方法を説明していきます。

まずは、以下のコマンドでsuiteを作成します。

$ codecept generate:suite api

tests/api.suite.ymlを以下のように書き換えます。

class_name: ApiTester
modules:
    enabled:
      - \Helper\Api
      - REST:
          depends: Phalcon2
      - Phalcon2:
          bootstrap: 'tests/api_bootstrap.php'

RESTのモジュールを使いつつも、Phalconのフレームワークでテストをする、という設定になります。

設定ファイルから実際のApiTesterクラスのビルドをする必要があります。ビルドしないと設定したモジュールが反映されません。

$ codecept build

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

$ codecept generate:cept api {class_name}

あとは、tests/api/{class_name}Cept.phpにコードを書いていけばOKです。以下はサンプル。

<?php 

$I = new \ApiTester($scenario);
$I->wantTo('POST /api/hoge');
$I->haveHttpHeader('Content-Type', 'application/json; charset=UTF-8');
$I->sendPOST('/api/hoge', '{"hoge":"fuga"}');
$I->seeResponseCodeIs(200);
$I->seeResponseContainsJson(['result' => 'ok']);
$I->seeHttpHeader('Content-Type', 'application/json; charset=UTF-8');

Webサイトのテスト

Webアプリ(サイト)の方法を説明します。

以下のようにしてsuiteを作成します。

$ codecept generate:suite functional

tests/functional.suite.ymlはこんな感じで。

class_name: FunctionalTester
modules:
    enabled:
        - \Helper\Functional
        - Phalcon2:
            bootstrap: 'tests/api_bootstrap.php'

APIのときと同じように以下のコマンドでビルド

$ codecept build

あとはテストコードを書くだけ。

$ codecept generate:cept functional {class_name}

tests/functional/{class_name}Cept.php

<?php

$I = new FunctionalTester($scenario);
$I->wantTo('POST /hoge');
$I->amOnPage('/hoge');
$I->seeResponseCodeIs(200);
$I->seeInTitle('hoge title');
$I->seeLink('fugalink', '/fuga');

Phalconモジュールを利用する際の注意

Codeception\Module\RESTモジュールのsendGET, sendPOSTやCodeception\Lib\InnerBrowserCodeception\Module\Phalcon2の大元の継承クラス)のamOnPage等のメソッドでは$_SERVERの変数値を明示的に指定することができません。大抵この仕様が問題になることは無いとは思いますが、処理内で$_SERVER['REQUEST_TIME_FLOAT']等のcodeceptionのモジュール内で暗黙的にセットされないヘッダ以外(HTTP_*変数)の変数を利用する場合、codeceptionを走らせた時に"Undefined index"のエラーが発生します。

これを回避するためには、Codeception\Lib\InnerBrowserに実装されている_requestメソッドを利用します。具体的には以下のようなコードをHelperクラス(tests/_support/Helper内のクラス)に実装します。

<?php
namespace Helper;

class Api extends \Codeception\Module
{
    public function sendPOSTWithServer($url, $content, $server) {
        return $this->getModule('Phalcon2')->_request(
            'POST', $url, [], [], $server, $content
        );
    }
}

あとはcodecept buildしてから以下のようにして利用します。

$response = $I->sendPOSTWithServer(
    '/hoge', 
    '{"hoge":"fuga"}',
    [
        'REQUEST_TIME_FLOAT' => time()
    ]
);

HTTPヘッダをセットしたい場合は、ハイフンをアンダースコアに置換してアッパーケースにしてプレフィックスのHTTP_を付与してから、$serverに格納します。例えば、Authorizationヘッダの場合はHTTP_AUTHORIZATIONになります。

 

この投稿はPhalcon Advent Calendar 2015の 14日目の記事です。

このエントリーをはてなブックマークに追加