カスタマイズ
この章では、どのようにしてファイル構造やテスト実行ルーチンをカスタマイズできるのか、説明します。
複数アプリケーションのための1つのランナー
プロジェクトが複数のアプリケーション(frontend, admin, api)で構成されていたり、バンドルとともにSymfonyを使っている場合、すべてのアプリケーション(バンドル)に対するすべてのテストを1ランナーで実行することに興味があるのではないでしょうか。 ここではプロジェクト全体をカバーする1つのレポートを取得してみます。
codeception.yml
ファイルをプロジェクトのルートフォルダーに配置して、インクルードしたい他のcodeception.yml
へのパスを指定します。
include:
- frontend/src/*Bundle
- admin
- api/rest
paths:
log: log
settings:
colors: false
レポートやログの出力先となるlog
ディレクトリーへのパスも指定してください。
名前空間
アクタークラスとヘルパークラスの名前空間が衝突するのを避けるため、それらは名前空間に属すべきです。
名前空間を持つテストスイートを作成するためには、ブートストラップコマンドに--namespace
オプションを付与します。
$ php codecept bootstrap --namespace frontend
これにより、namespace: frontend
パラメーターを持つcodeception.yml
ファイルとともに、新しいプロジェクトが作成されます。
ヘルパークラスの名前空間はfrontend\Codeception\Module
に、アクタークラスの名前空間はfrontend
になります。
こうして、新しく作成されたテストは次のようになります。
<?php use frontend\AcceptanceTester;
$I = new AcceptanceTester($scenario);
//...
それぞれのアプリケーション(バンドル)が自身の名前空間と異なるヘルパーやアクタークラスを持つようになって、すべてのテストを1ランナーで実行できるようになります。先ほど作成したメタ設定を使って、通常どおりCodeceptionを実行します。
$ php codecept run
これにより、3つのすべてのアプリケーションのテストスイートが起動し、すべてのテストレポートがマージされます。これはつまり、継続的インテグレーションサーバー上でテストを実行し、1つのJUnitとHTML形式のレポートを取得したい場合に大変役に立ちます。コードカバレッジレポートについても同じくマージされます。
もし各アプリケーションが共通のヘルパーを利用している場合、次のセクションに従ってください。
拡張機能
Codeceptionはコアな機能を拡張する限定的な機能を持っています。 拡張機能は現在の機能をオーバーライドすることを想定していませんが、もしあなたが経験のある開発者でテストのフローをフックしたい場合にはとても便利です。
デフォルトで、RunFailed
エクステンションがすでにcodeception.yml
にて有効化されています。
これにより、-g failed
オプションをつけることで失敗したテストを再実行することができます。
php codecept run -g failed
Codeceptionにはext
ディレクトリーに配置された拡張機能が付属しています。たとえば、Monologを使ってテスト実行のログを記録するLogger拡張を有効にすることができます。
extensions:
enabled:
- Codeception\Extension\RunFailed # default extension
- Codeception\Extension\Logger # enabled extension
config:
Codeception\Extension\Logger:
max_files: 5 # logger configuration
ではいったい拡張機能とは何でしょうか?基本的に、拡張機能はSymfony Event Dispatcherコンポーネントを基盤とするイベントリスナー以上の何ものでもありません。
これらがイベントとイベントクラスです。テスト実行中に発生する順番で一覧化しています。それぞれのイベントには対応したクラスがあり、特定のオブジェクトを含んでイベントリスナーに渡されます。
イベント
イベント | いつ? | 何を含む? |
---|---|---|
suite.before |
Before suite is executed | Suite, Settings |
test.start |
Before test is executed | Test |
test.before |
At the very beginning of test execution | Codeception Test |
step.before |
Before step | Step |
step.after |
After step | Step |
step.fail |
After failed step | Step |
test.fail |
After failed test | Test, Fail |
test.error |
After test ended with error | Test, Fail |
test.incomplete |
After executing incomplete test | Test, Fail |
test.skipped |
After executing skipped test | Test, Fail |
test.success |
After executing successful test | Test |
test.after |
At the end of test execution | Codeception Test |
test.end |
After test execution | Test |
suite.after |
After suite was executed | Suite, Result, Settings |
test.fail.print |
When test fails are printed | Test, Fail |
result.print.after |
After result was printed | Result, Printer |
test.start
とtest.before
、 test.after
とtest.end
とに混乱するかもしれません。Start/endイベントはPHPUnit自身によって発生されますが、before/afterイベントはCodeceptionによって発生されます。ですので、従来の(PHPUnit_Framework_TestCase
を継承した)PHPUnitのテストではbefore/afterイベントは発生しません。test.before
イベントでは、test.start
では不可能な、スキップされたか不完全なテストを追跡することができます。Codeception internal event listenersにてより多くのことを学ぶことができます。
拡張クラスはCodeception\Platform\Extension
クラスを継承します。
<?php
class MyCustomExtension extends \Codeception\Platform\Extension
{
// list events to listen to
public static $events = array(
'suite.after' => 'afterSuite',
'test.before' => 'beforeTest',
'step.before' => 'beforeStep',
'test.fail' => 'testFailed',
'result.print.after' => 'print',
);
// methods that handle events
public function afterSuite(\Codeception\Event\SuiteEvent $e) {}
public function beforeTest(\Codeception\Event\TestEvent $e) {}
public function beforeStep(\Codeception\Event\StepEvent $e) {}
public function testFailed(\Codeception\Event\FailEvent $e) {}
public function print(\Codeception\Event\PrintResultEvent $e) {}
}
イベントハンドラーメソッドを実行することにより、渡されたオブジェクトを更新してもイベントをリッスンすることができます。 拡張クラスはいくつかの基本的なメソッドを持っています。
write
- コンソールに出力するwriteln
- 改行コードとおともにコンソールに出力するgetModule
- モジュールにアクセスするhasModule
- モジュールが有効かどうか確認するgetModuleNames
- すべての有効なモジュール一覧を取得する_reconfigure
- コンストラクターをオーバーライドする替わりに実装する
拡張機能の有効化
単純な拡張クラスを実装したら、tests/_bootstrap.php
ファイルにインクルードするか、
composer.json
に定義されたComposerのオートローダーでロードするか、もしくはtests/_support
ディレクトリーにクラスを格納します。
codeception.yml
で拡張機能を有効にします。
extensions:
enabled: [MyCustomExtension]
拡張機能の設定
拡張クラスではoptions
プロパティを介して現状渡されたオプションにアクセスすることができます。
また、\Codeception\Configuration::config()
を利用してグローバル設定にアクセスすることもできます。
もし拡張クラスにカスタムなオプションを持たせたい場合、codeception.yml
ファイルからそれを渡すことができます。
extensions:
enabled: [MyCustomExtension]
config:
MyCustomExtension:
param: value
渡された設定には次のようにconfig
プロパティを介してアクセスすることができます。$this->config['param']
とても基本的な拡張機能であるNotifierを確認してください。
カスタムコマンド
Codeceptionにあなた専用のコマンドを追加することができます。
カスタムコマンドは、コマンド名を取得するための関数が存在しなければならないため、Codeception\CustomCommandInterface
インタフェースを実装する必要があります。
codeception.yml
にコマンドを登録してください
extensions:
commands: [Project\Command\MyCustomCommand]
一つ以上のcodeception.yml
ファイルを使用しているなど、グローバルにカスタムコマンドを有効化したい場合、
プロジェクトのルートフォルダーにあるcodeception.dist.yml
にコマンドを登録してください・
完全な例はこちらを見て下さい。
グループオブジェクト
グループオブジェクトは特定のグループに属すテストのイベントをリッスンするための拡張機能です。 テストが次のグループに追加されたとき、
<?php
$scenario->group('admin');
$I = new AcceptanceTester($scenario);
このテストは次のイベントを発生させます。
test.before.admin
step.before.admin
step.after.admin
test.success.admin
test.fail.admin
test.after.admin
グループオブジェクトはこれらのイベントをリッスンするために構築されています。これは、テストに追加の設定が必要になった場合にとても便利です。admin
グループに属すテストのためにフィクスチャをロードしたいとしましょう。
<?php
namespace Group;
class Admin extends \Codeception\GroupObject
{
public static $group = 'admin';
public function _before(\Codeception\Event\TestEvent $e)
{
$this->writeln('inserting additional admin users...');
$db = $this->getModule('Db');
$db->haveInDatabase('users', array('name' => 'bill', 'role' => 'admin'));
$db->haveInDatabase('users', array('name' => 'john', 'role' => 'admin'));
$db->haveInDatabase('users', array('name' => 'mark', 'role' => 'banned'));
}
public function _after(\Codeception\Event\TestEvent $e)
{
$this->writeln('cleaning up admin users...');
// ...
}
}
グループクラスはphp codecept generate:group groupname
コマンドによって作成することができます。
グループクラスはtests/_support/Group
ディレクトリーに格納されます。
拡張クラスと同様、codeception.yml
にてグループクラスを有効にすることができます。
extensions:
enabled: [Group\AdminGroup]
これでAdminグループクラスはadmin
グループに属すテストのすべてのイベントをリッスンするようになります。
カスタムレポーター
出力をカスタマイズするため、SimpleOutput Extensionのように、エクステンションを使うことができます。
では、--xml
や--json
オプションによって出力されるXMLやJSONの結果出力を変更するためには何が必要になるのでしょうか?
CodeceptionはPHPUnitの出力機能を利用しており、そのいくつかをオーバーライドしています。もし標準のレポーターのいずれかをカスタマイズしたい場合はそれらをオーバーライドすることができます。
もし独自のレポーターを実装する場合は、codeception.yml
にreporters
セクションを追加して、標準レポーターをあなたのものでオーバーライドしてください。
reporters:
xml: Codeception\PHPUnit\Log\JUnit
html: Codeception\PHPUnit\ResultPrinter\HTML
tap: PHPUnit_Util_Log_TAP
json: PHPUnit_Util_Log_JSON
report: Codeception\PHPUnit\ResultPrinter\Report
すべてのレポーターはPHPUnitFrameworkTestListenerインターフェイスを実装します。 オーバーライドする前にオリジナルのレポーターのコードを読むことをおすすめます。
まとめ
これまでに述べてきた各機能は、いくつかについては高度なPHPの知識を必要とするかもしれませんが、規模の大きいプロジェクトのテストをCodeceptionで自動化する際に、劇的に役立つことがあります。グループや拡張機能やそのほかCodeceptionの強力な機能には「ベストプラクティス」や「ユースケース」は存在しません。これらの拡張機能を使うことで解決できそうな問題に直面した場合、試してみてください。