LaravelのPHPUnitの拡張機能にIlluminate\Foundation\Testing\DatabaseTransactions
トレイトというものがあります。
これはsetUpでbeginTransaction
し、tearDownでrollback
することでテスト毎にデータを捨ててクリーンにデータベースを保ちながらテストコードを書くことができる機能です。(大げさ)
この機能を利用しているのでsetUpでSeederを利用してテストデータを挿入していたので後続のテストには影響がない前提でテストを書いていたにもかかわらずrollbackされなくて後続のテストに影響が出てしまったケースがありました。
そのコードが以下
use DatabaseTransactions;
protected function setUp(): void
{
parent::setUp();
\DB::table('クリアにしたいテーブル')->truncate();
$this-seed('テストケースデータ');
}
setUp内で特定のテーブルに対してtruncateを実行しています。
これには以下の背景がありました。
- MySQLではrollbackしてもautoincrementのカウンタは戻らない
- 特定のautoincrementの値であることを検証したい(そんなテストもどうかと思うというツッコミは控えてほしい)
なので、truncateでもともと入ってるデータはきれいにしてしまえ、という思案です。
ですが先述の通りこのコードには問題があります。
それは、**MySQLはtransaction中にtruncateを実行すると暗黙的にcommitする**ということです。
ということでtruncateコード後のseedは無事コミットされているという具合ですね。
こういうケースではIlluminate\Foundation\Testing\RefreshDatabase
トレイトを利用することでDBを空っぽにしてくれます。
まとめ
- MySQLはtransaction中にtruncateを実行すると暗黙的にcommitする
-
Illuminate\Foundation\Testing\RefreshDatabase
を使おう