前回はincubatorでUnitTestsな単体テストをしましたが、今回は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\InnerBrowser(Codeception\Module\Phalcon2の大元の継承クラス)のamOnPage等のメソッドでは$_SERVERの変数値を明示的に指定することができません。大抵この仕様が問題になることは無いとは思いますが、処理内で$_SERVER[‘REQUEST_TIMEFLOAT’]等の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日目の記事です。