View on GitHub

Codeception.docs.ja

Codeception docs japanese translation

Download this project as a .zip file Download this project as a tar.gz file

カスタマイズ

この章では、どのようにしてファイル構造やテスト実行ルーチンをカスタマイズできるのか、説明します。

複数アプリケーションのための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.starttest.beforetest.aftertest.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.ymlreportersセクションを追加して、標準レポーターをあなたのものでオーバーライドしてください。

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の強力な機能には「ベストプラクティス」や「ユースケース」は存在しません。これらの拡張機能を使うことで解決できそうな問題に直面した場合、試してみてください。