LaravelでRefreshDatabaseしているテストをどう安全に運用するか

課題

RefreshDatabaseはテストごとにデータベースをクリアしてくれる便利なトレイトで、データベースを使ったテストを書くときにはほぼ必須だが、運用をミスると消したくないデータベースを消してしまうことがある。

具体的に危険なのは、.env.testingがない場合に.envが使われることにより、.envい記載されたテスト用以外のデータベースにつないでしまい、クリアしてしまうこと。

Laravel 6.8.0以降ではphpunit.xmlSQLiteのインメモリデータベースに接続するように設定されるようになっている(参考)ため、phpunit.xmlを変更していないのであればこの問題は避けられる。

(が、LaravelはRDBMS間の差異を十分に吸収しないため、テストにSQLiteを使うのは実用的ではなく、大抵の場合はこの部分の設定を消して、.env.testingに書くことになるだろう)

解決策

本番環境では、まずそもそもPHPUnitが入っていないはずなのであまり問題ないはず。

問題は開発環境だ。.envは用意せず、.env.localを用意して、アプリケーション動作時にはAPP_ENV=localだけ別途指定する形にすれば、間違って.env.testingがない状態で自動テストを叩くようなことがあっても安全そうだ。が、まだ十分には試していない。

すべてのテストをデータベースの状態に依存させずに書ければそれがベストだと思うけど、なかなか難しいよね。

その他

RefreshDatabaseはmigrate:freshコマンドを実行することでデータベースをクリアしている。このコマンドはproduction下では実行前に確認プロンプトを出してくれるのだが、そもそもテストがproductionで実行されることは普通ない。