LaravelでRefreshDatabaseしているテストをどう安全に運用するか
課題
RefreshDatabaseはテストごとにデータベースをクリアしてくれる便利なトレイトで、データベースを使ったテストを書くときにはほぼ必須だが、運用をミスると消したくないデータベースを消してしまうことがある。
具体的に危険なのは、.env.testing
がない場合に.env
が使われることにより、.env
い記載されたテスト用以外のデータベースにつないでしまい、クリアしてしまうこと。
Laravel 6.8.0以降ではphpunit.xml
でSQLiteのインメモリデータベースに接続するように設定されるようになっている(参考)ため、phpunit.xml
を変更していないのであればこの問題は避けられる。
(が、LaravelはRDBMS間の差異を十分に吸収しないため、テストにSQLiteを使うのは実用的ではなく、大抵の場合はこの部分の設定を消して、.env.testing
に書くことになるだろう)
解決策
本番環境では、まずそもそもPHPUnitが入っていないはずなのであまり問題ないはず。
問題は開発環境だ。.env
は用意せず、.env.local
を用意して、アプリケーション動作時にはAPP_ENV=local
だけ別途指定する形にすれば、間違って.env.testing
がない状態で自動テストを叩くようなことがあっても安全そうだ。が、まだ十分には試していない。
すべてのテストをデータベースの状態に依存させずに書ければそれがベストだと思うけど、なかなか難しいよね。
その他
RefreshDatabaseはmigrate:fresh
コマンドを実行することでデータベースをクリアしている。このコマンドはproduction
下では実行前に確認プロンプトを出してくれるのだが、そもそもテストがproduction
で実行されることは普通ない。