Top View


Author uchida

CakePHP4.3 でテストがかなり変わってた

2021/12/09

Table of Contents

4.2 -> 4.3 の変更点

テスト以外の点は、あまり大きな破壊的な変更はないため、既に4.2であればアップグレードすればそのまま動くとは思います。

スキーマ管理の変更

テスト実行時のスキーマ管理について、従来は Fixture の $fields にスキーマ情報を記載する。
もしくは、 $import でdefaultのDBのスキーマを読み込むようにするの2択でした。
どちらの方式にしろ、アプリケーションのMigrationsに変更・追加があると、各Fixtureにも適宜変更を入れる必要があります。

4.3.0では、フィクスチャのスキーマとデータ管理の責務が分割されました。 フィクスチャクラスやマイグレーションでスキーマを管理することは、 アプリケーションに複雑さとメンテナンスコストをもたらしていました。 4.3.0 では新しい API が追加され、既存のマイグレーションやスキーマ管理ツールを テストでより簡単に再利用できるようになりました。

4.3以降、デフォルトではアプリケーションのマイグレーションからスキーマを構築し、テストを実行するようになりました。
4.2から利用していた場合、下記の2つのファイルの変更を行うと新しい手法でスキーマを管理するようになります。

これからは、Fixtureでは純粋にデータの管理だけが行えるようになりました!
テストケースに記載する $fixture にもデータの追加が必要なテーブルだけを記載できるようになったので、すっきり書けます。

Fixture State Managers

テスト実行時のデータリセットの手法にも選択肢が増えています。

By default CakePHP resets fixture state at the end of each test by truncating all the tables in the database. This operation can become expensive as your application grows. By using TransactionStrategy each test method will be run inside a transaction that is rolled back at the end of the test. This can yield improved performance but requires your tests not heavily rely on static fixture data, as auto-increment values are not reset before each test.

CakePHPは各テストを実行時に全てのテーブルをTRUNCATEをするのが基本的な動きです。
そのため、各テストごとにデータをINSERTすると ID は 1 から始まります。

Fixture State Mangers の設定により、Truncateではなく、テストごとにTransactionによるrollbackを実行し、既存テストケースを速くできる可能性があります。
rollbackによるデータリセットのため、DBのシーケンシャルはリセットされないのが注意点です。
テストにマジックナンバーを利用しないようにしましょう。

use Cake\TestSuite\TestCase;
use Cake\TestSuite\Fixture\FixtureStrategyInterface;
use Cake\TestSuite\Fixture\TransactionStrategy;

class ArticlesTableTest extends TestCase
{
    /**
     * Create the fixtures strategy used for this test case.
     * You can use a base class/trait to change multiple classes.
     */
    protected function getFixtureStrategy(): FixtureStrategyInterface
    {
        return new TransactionStrategy();
    }
}

ハマったところ

上記の TransactionStrategy を使うにしろ、デフォルトの TruncateStrategy を使うにしろ、
各テストケースの $fixture に何か1つでも Fixture を読み込んでいないとそもそも rollback も Truncate も実行されません。
既にSchemaは構築されてるし、初期データも必要ないテストで、動的にデータを生成し、 $fixuture を何も指定していなかった場合、そのまま次のテストケースにデータは残ってしまいます...orz

終わり

TransactionStrategy により、Laravelっぽくなった、かつ実行速度も向上したのでアップグレード時に対応してよかったなと思っています。
まだ試してはいませんがfactoryもあるようなのでどこかで触ってみようと思います。

uchida

uchida

福岡でWebエンジニアやってます。PHP, クラウド, インフラあたりが好き。AWS 五冠