引き続き、baserCMS5の開発にてCakePHP2系から4系への移行を進めています。
CakePHP4.3 より、これまでのフィクスチャマネージャーが非推奨になり、フィクスチャファクトリの利用が推奨されているようです。
色々と仕組みがややこしく、ドキュメントが少ないので記録しておきます。
従来は、テスト実行時にテーブルの作成とデータ登録がされていたのですが、フィクスチャマネージャーを利用しなくなった事により、テーブルの作成処理が tests/bootstrap.php
でのマイグレーションでの生成に移行となっている様子。
つまり、 bootstrap.php
にて、マイグレーションを実行しないとテーブルが作成されない仕様。
まず、マイグレーションは tests/bootstrap.php
次のように実行します。
use Migrations\TestSuite\Migrator;
// マイグレーションが一つの場合
new Migrator->run(['plugin' => 'BaserCore']);
// マイグレーションが複数の場合
(new Migrator())->runMany([
['plugin' => 'BaserCore'],
['plugin' => 'BcFavorite']
]);
bootstrap の実行仕様
となると、プラグインのマイグレーションは、プラグイン内の bootstrap.php
で実行したいところだが、 bootstrap.php
の実行は、カレントディレクトリ内の tests/bootstrap.php
を利用する仕様となっているため、プラグイン内の bootstrap.php
を実行するは、プラグインディレクトリに移動するか、 --bootstrap
オプションを指定しなければならない。 めんどい。
# プラグインディレクトリに移動する場合
cd plugins/baser-core
../../vendor/bin/phpunit
# アプリケーションルートでオプションを指定する場合
vendor/bin/phpunit --bootstrap plugins/baser-core/tests/bootstrap.php
プラグイン単独でユニットテストを実行する
その上で、プラグイン単独でユニットテストを実行する方法を調べてみた。
まず、プラグインディレクトリ内に phpunit.xml.dist
を作成する。
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.5/phpunit.xsd"
colors="true"
bootstrap="tests/bootstrap.php"
>
<php>
<ini name="memory_limit" value="-1"/>
<ini name="apc.enable_cli" value="1"/>
</php>
<testsuites>
<testsuite name="BcFavorite">
<directory>tests/TestCase</directory>
</testsuite>
</testsuites>
<extensions>
<extension class="Cake\TestSuite\Fixture\PHPUnitExtension"/>
</extensions>
<coverage>
<include>
<directory suffix=".php">src/</directory>
</include>
</coverage>
</phpunit>
次に、tests/bootstrap.php
を作成する。
use Migrations\TestSuite\Migrator;
$findRoot = function($root) {
do {
$lastRoot = $root;
$root = dirname($root);
if (is_dir($root . '/vendor/cakephp/cakephp')) {
return $root;
}
} while($root !== $lastRoot);
throw new Exception("Cannot find the root of the application, unable to run tests");
};
$root = $findRoot(__FILE__);
unset($findRoot);
chdir($root);
require_once $root . '/vendor/autoload.php';
require $root . '/config/bootstrap.php';
(new Migrator())->runMany([
['plugin' => 'BaserCore'],
['plugin' => 'BcFavorite']
]);
ユニットテストの実行を composer 経由にする場合は、 composer.json
に次を追記する。
"scripts": {
"test": [
"Composer\\Config::disableProcessTimeout",
"../../vendor/bin/phpunit --colors=always"
]
}
ただ、この場合、プラグインディレクトリ内で実行する事が前提となる。
GitHubActionsなどのCIで、docker を使いつつ(baserCMS5の開発の場合)自動化するためには、yml ファイルにて、 --workdir
オプションを指定して次にように記述する必要がある。
(プラグインではなくアプリケーションルート側で設定する場合)
docker exec --workdir /var/www/html/plugins/bc-favorite [コンテナ名] composer run-script test
なお、特定ファイルを指定する場合のユニットテストのコマンドは次のようになる。
cd plugins/bc-favorite
../../vendor/bin/phpunit tests/TestCase/Controller/Api/FavoritesControllerTest.php
- プラグインフォルダに移動しなければならない
- 上位階層の実行ファイルを指定しなければならない
- パス指定がコンテンツルートではなくプラグインルートからのパスとなる(最近のIDEでは、指定ファイルのコンテンツルートからのパスをコピーする機能があるがそれが利用できない)
めんどい。
baserCMSコア、コアプラグイン開発の最適解
特定ファイルのパス指定が特にめんどいので、baserCMS5の開発では、ルート直下の phpunit.xml.dist
にテスト対象のプラグインを全て定義し、ルート直下の tests/bootstrap.php
に、対象プラグインのマイグレーションを全て記述することにした。
baserCMSの CakePHP4系化の開発プロジェクトのレポジトリはこちら。
https://github.com/baserproject/ucmitz
(協力者募集しています)