これは CakePHP Advent Calendar 2017 の 22 日目の記事です。

プラグインのテスト

今回は CakePHP 2 のプラグインを開発する際に便利な、Travis CI 上でテストを実行するためのスクリプト「FriendsOfCake/travis」を紹介します。

CakePHP にはプラグインの機構が搭載されていますが、公式の Cookbook にも基本的な機能の説明がなされているのみで特にテストの手法については具体的な記述がありません。基本的には標準的なアプリケーションと同じようにしてテストを作成することが可能ですが、プラグインのリポジトリー単独でテストを実行することができるように設計されていないためテストの呼び出しにやや難があります。拙作の CakePHP 2 向けプラグイン「lampager-cakephp2」では当初、テストにのみ用いられるコードをプラグイン本体にも含めていましたが、読み込むアプリケーションとの競合や、プラグイン自体のメンテナビリティーの問題があったため別の手法を取ることにしました。

プラグインの作成 – 2.x(CakePHP 2.x Cookbook)

FriendsOfCake/travis

FriendsOfCake/travis は Travis CI 上で動作させるためのプラグインテスト向けスクリプト群で、CakePHP の新規リポジトリーをセットアップしてプラグインの配置を行ったり、Codecov に対してカバレッジを送信したりするためのスクリプトを含んでいます。

プラグイン側で必要な作業は Test ディレクトリーに標準的なアプリケーションと同様の構成でファイルを配置し、プラグインを読み込む側から見たコードと同じようにしてテストを記述することです。たとえば lampager-cakephp2 では読み込まれる際のディレクトリーの名称を Lampager としているので、テストにおいてプラグインの機能を使うときにはすべて次のようなコードで呼び出します。

<?php
// モデルの LampagerPaginator クラスを読み込む例
App::uses('LampagerPaginator', 'Lampager.Model');
class LampagerPaginatorTest extends CakeTestCase
{
public $fixtures = [
// プラグインのフィクスチャーを参照する例
'plugin.Lampager.Post',
];
}

こうすることでプラグイン本体から直接テストを実行する場合と異なり、プラグインの読み込みに関しても自動化されたプロセスで検証することが可能になります。

実際の実行例は Build #52 - lampager/lampager-cakephp2 - Travis CI で見られます。

Composer のオートローダー

現代的な PHP の開発においては基本的に Composer のようなパッケージ管理が採用されていますが、CakePHP 2 は既定でオートローダーが呼び出されることはありません。プラグインが何らかの Composer パッケージに依存している場合は、app/Config/bootstrap.php の末尾等で呼び出す処理を追加しておくとアプリケーション側がそれを呼び出している状況と同じように設定できます(設定例は次章のコード参考)

PHPUnit のバージョン

CakePHP 2 ではバージョン 2.10 以上から、テスト実行に使用できる PHPUnit のバージョンが 3.7.x から 5.x まで引き上げられました。しかしながら FriendsOfCake/travis は自動でインストールされる PHPUnit のバージョンが 3.7.x に決め打ちされています。

もしテスト対象のプラグインが PHPUnit 4.x/5.x 環境下でテストされる場合は、次のように Composer を直接呼び出して必要なバージョンを再インストールすることで対応できます。

before_script:
- git clone https://github.com/FriendsOfCake/travis.git --depth 1 ../travis
- ../travis/before_script.sh
- composer global remove "phpunit/phpunit"
- composer global require "phpunit/phpunit:<6.0.0"
- echo "require_once '$PWD/vendor/autoload.php';" >> ../cakephp/app/Config/bootstrap.php

CakePHP のバージョン

プラグインを呼び出す CakePHP のバージョンは .travis.yml で環境変数を使用して設定する必要があります。 FriendsOfCake/travis 側の実装では GitHub API を呼び出すことでバージョンが一致する CakePHP を取得できるようになっていましたが、API トークンが設定できるようになっていないことに加えて Travis CI では多数の GitHub API を使用するアプリケーションが動作しているため、これを使うことはできませんでした。

次のように CAKE_REF 変数を使って有効なブランチ名を指定することで 2.x の最新版を使うといったことはできますが、もしバージョンを厳密に指定したい場合は注意が必要です。

env:
global:
- PLUGIN_NAME=Lampager
- CODECOVERAGE=1
- CAKE_REF=2.x
- DB=mysql
view raw env.yml hosted with ❤ by GitHub

環境変数ではほかに次のような値が指定できます。

  • PLUGIN_NAME: プラグインディレクトリーの名称
  • CODECOVERAGE: カバレッジを出力するかどうか(1 なら出力)
  • DB: テストに使用するデータベースの種類(mysql または pgsql)

コードカバレッジ

FriendsOfCake/travis では Codecov へのカバレッジ送信をサポートしていますが、Codecov は使用していないのでスクリプトは確認していません。

lampager-cakephp2 では次のように php-coveralls/php-coveralls を使って Coveralls にカバレッジを反映するように構成しています。

after_success:
- cd ../cakephp/app/Plugin/$PLUGIN_NAME
- mkdir -p build/logs
- mv ../../clover.xml build/logs
- travis_retry $TRAVIS_BUILD_DIR/vendor/bin/coveralls

最後に

この記事で紹介した lampager/lampager はページ単位ではなくカーソルを使用したページネーションを行うためのライブラリーで、 lampager-cakephp2 はそれを CakePHP 2 のモデルやコントローラーから呼び出すためのプラグインです。

現在 Lampager では CakePHP 3 やそれ以外の各種フレームワークも含めてアダプター/プラグインの実装を募集しています。あわせて @mpyw さんの「OFFSETを使わない高速ページネーションを任意のPHPフレームワークで超簡単に実現する - Qiita」もご覧ください。

長い記事でしたがお読みいただきありがとうございました。
明日の担当は @yuzoiwasaki さんです。