BehatCakePHP3の変更点として大きく取り上げられるのが、モデル層の変更でしょう。それ以上に私たちが受けられる恩恵で大きいのが、PSR-2の採択です。PSR-2例えばCakePHP2で単体テストを実行するときは、以下のようにcakeコマンドを使って実行する必要がありました。Model/Articlescakeコマンド内でPHPUnitへの依存関係を解決し、PHPUnitからCakePHPのクラスが参照可能になるように作られていました。ところがCakePHP3からは、以下のようにphpunitコマンドを使って実行します。vendor/bin/phpunitPSR-0のオートロードに対応したことで、PHPUnitからCakePHP3のクラスが参照可能になるのです。Pluginを使ってBehatのステップ記述からCakePHPのクラスを参照可能になるようにしていました。Behatにおいても直接実行したステップ定義から、CakePHP3のクラスが参照可能になるのです。CakePHP3のアプリケーションをどのようにBehatからアクセスするのか、CakePHP3のブログチュートリアルを例にサンプルアプリを作成しました。cakephp3-bdd-exampleサンプルアプリケーションは以前記事にもしたCakeboxを使って構築しました。サンプルアプリケーションの実行にもCakeboxを使うと簡単に実行環境を構築することができます。サンプルアプリケーションのGithubページに書いてあるとおりの手順で進むことができます。本ブログでは日本語で補足します。必要なアプリケーションのインストール以下のアプリケーションをホストOSにインストールします。使ってCakePHP3アプリケーションを作ってみようの記事を参照してください。サンプルアプリケーションのインストールCakeboxのゲストOSにログインして、cakeboxコマンドでアプリケーションをインストールします。blog-tutorial.appすると、以下のように表示されます。successfully新規アプリケーションの構築と同じように、データベースやNginxの設定ファイルも生成してくれるので、すぐにアプリケーションを実行できる環境が整います。あとはアプリケーションのルートディレクトリに移動して、不足しているディレクトリを作ってcomposerでライブラリをインストールします。サンプルアプリケーションの環境設定データベース接続設定の変更config/app.phpのデータベース接続設定をCakeboxで生成された内容に変更します。以下のとおりusernameとdatabaseの部分のみ変更します(それ以外はそのまま)。Cakebox環境のチューニングCakeboxのデフォルト設定ではBehatを使ってアプリケーションをテストしようとすると、いくつか動かない箇所があったので、設定値をチューニングします。ボックスファイルのメモリを2048Mにアップします(デフォルトは1024M)。次にxdebug.iniのxdebug.maxnestinglevelの値を調整します。READMEでは500を設定しています。値は小さくても大丈夫かもしれないですが、とりあえず500あれば大丈夫です。具体的な設定例は、githubのREADMEを参照してください。Webサーバの設定Behatからアプリケーションをテストするときは、ブラウザから通常操作するのと同じようにWebサーバを通過します。そのため、アプリケーションが通常操作としてアクセスされたのか、Behatのテストでアクセスされたのかを識別して環境を切り替えてあげないと、データベースのデータがテストによって変更するので、通常操作のデータが失われてしまいます。このあたりの話(理由や手法)は、過去に何度か記事にしていたり、書籍CakePHPで学ぶ継続的インテグレーションでも詳しく解説していますので、CakePHP2の内容ですが、一度手に取ってみてください。このサンプルはnginx用の設定ファイルをblog-tutorial.app.testというファイルで用意しておいたので、これをCakeboxのnginxの設定ディレクトリにコピーして再起動するだけで大丈夫です。環境切り替え用にblog-tutorial.app.testというホスト名でアクセスされたら、nginxで環境変数CAKE_ENVにtestという文字列を設定するようにしています。CakePHP3のアプリケーションではconfig/bootstrap.phpで環境変数の設定値を見てDBの接続先がtestになるように設定します。'default');}CakePHP3ではConnectionManagerのaliasという機能でdefaultへ接続しようとしたときに、実際はtestの接続内容を参照するように設定することができるので、この機能を利用し、間違ってdefaultのテーブルが書き変わらないようにしています。詳しい手順や、設定ファイルの内容はgithubのREADMEや設定ファイルを参照してください。Behatから参照可能なホスト名としてblog-tutorial.app.testをCakeboxのVM側の/etc/hostsに追加します。データベースのマイグレーションデータベースの生成はマイグレーションコマンドで一発です。migrateBehatのテストを実行するここまで設定できれば、後はテストを実行するだけです。vendor/bin/behatおそらくすべてグリーンで成功するはずです。うまくいかなかったら、お気軽にgithubのissueに日本語で書いてください。やったのか?まずCakePHP3で最初に注目したのは、単体テストがPHPUnitのコマンドから実行できるようになっていたことです。これは過去に外部の様々なツールやアプリケーションとCakePHPを結合するときに一番悩んでいたところでした。PHPUnitからCakePHP3にどのように連動しているのか?を調べることから始めました。PHPUnitは実行すると、カレントディレクトリのphpunit.xml(もしくはphpunit.xml.dist)を参照します。PHPUnitがCakePHP3を呼び出す仕組みを知るCakePHP3ではアプリケーションスケルトンを生成すると、ルートディレクトリにphpunit.xml.distが生成されます。</listeners></phpunit>このファイルを読むと、2つ重要な箇所があるのに気がつきます。bootstrap属性にはPHPUnitが実行されるとき呼び出されるPHPコードを指定することができます。ここからCakePHP3アプリケーションをテスト用にロードする場合、このファイルを呼び出せば外部ツールからCakePHP3が操作できるようになることがわかります。実はこのファイルを実際に見てみると、以下の1行しかありません。'/config/bootstrap.php';テストとは関係なく、アプリケーションのconfig/bootstrap.phpをロードしています。将来テストに関する何か差分が必要になったときに、テスト側にだけ変更が発生すると思うので、テスト用にCakePHP3をロードする場合はtests/bootstrap.phpをロードしておいた方が良いでしょう。次に(2)のリスナー設定です。PHPUnitのリスナーはPHPUnitのフックポイントでコールバックされる処理を記述できるクラスです。CakePHP3ではフィクスチャ(DBのテストテーブルとデータを準備する仕組み)を投入するのに利用しています。以下のようにFixtureInjectorクラスのstartTestとendTestでテストケース開始/終了ごとにフィクスチャのロードとアンロードが対応するようになっています。}}BehatからCakePHP3を呼び出す仕組みに流用するここまでの内容が外部ツールからCakePHP3のアプリケーションをテストするのに重要な部分です。PHPUnitがCakePHP3を呼び出すのと同じようにする仕組みをBehatのFeatureContextクラスに用意します。features/bootstrap/FeatureContext.phpというBehatが読み込むファイルに記述します。CakePHP2とBDDプラグインによるインテグレーションではBehatのバージョンが2系でしたが、CakePHP3との連携では最新の3系を利用しています。Behat3からはBehat1系、2系で利用していたファイル構成と異なっています。従来、support/bootstrap.phpやsupport/hooks.phpあたりに書いていたコードはすべてContextクラス内に記述することになります。Behat3からはFeatureContextにブートストラップ記述を、それ以外のコンテキストは用途に応じて別のコンテキストクラスに分割する方がスマートに記述できそうです。Behat2では複数のコンテキストクラスを使う場合、FeatureContextでインクルードしないといけなかったのですが、Behat3ではbehat.yml上で記述できるのでより簡単になっています。}}(1)は、phpunit.xmlのbootstrapと同様にCakePHP3のtests/bootstrap.phpを呼び出します。(2)は、Behatのステップ定義からテストデータを投入するときに、testの接続設定を参照するようにエイリアスを設定します。(3)は、テストデータジェネレータFabricateの初期設定です。FabricateもCakePHP3対応されています。(4)は、phpunit.xmlのリスナー部分を模して、Behatのシナリオ毎にフィクスチャが動くようにFixtureInjectorのインスタンスを生成しています。BehatからCakePHP3のフィクスチャを利用する(4)で書いたとおり、FixtureInjectorのインスタンスを生成したので、Behatのフックポイントを使ってシナリオ開始時にフィクスチャをロードし、シナリオ終了時にフィクスチャをアンロードするようにします。}実際にフィクスチャを利用するためには、$this->fixtureのクラスがCakePHP3のTestCaseでなければならないので、$fixturesという利用するフィクスチャファイルの配列を定義しただけのクラスを用意してFixtureInjectorに渡すようにします。];}このあたりの話も、書籍CakePHPで学ぶ継続的インテグレーションでも詳しく解説していますので、CakePHP2の内容ですが、一度手に取ってみてください。CakePHP3になって、メソッドやクラスが一部変わりましたが、BehatとCakePHPをインテグレーションするためにおさえておかないといけないポイントはほとんど変わっていません。エンドのテストが容易に記述できるようになります。さいごにGithubのREADMEに書いた内容をすべて日本語にした訳ではないのですが、要所をかいつまんで重要な部分を解説しました。詳しい内容などはREADMEを見ていただければと思います。BDDプラグインのサンプルアプリにはあった、日本語のシナリオや、JavaScriptを使ったテストなど、Behat3になって大きく変わってはいませんが、サンプルアプリケーションに少しずつ載せられたらなぁと思っています。何かうまく動かないなどあれば、気軽にGithubのissueに投稿お願いします(日本語でOKです)。