はじめに
Rails アプリ開発でテスト環境の設定を行う際によく出てくるのものの一つにdatabase_cleanerが挙げられます。
過去の Rails のテスト関連の本やネット記事を見るとdatabase_cleanerを使うのが作法かのように説明するものが多いです。
しかしながら、中には「database_cleanerって要る?」と疑問を投げかけている人も少なからずいます。
ん、どっち? 現代の Rails アプリにdatabase_cleaner は必要なのでしょうか?
氣になったので調査してみました。
結論
Railsの標準機能use_transactional_tests
(初期設定: true
)を使えば、通常はdatabase_cleanerが不要であることのようです。
また、database_cleanerの作者自身も、database_cleanerを作った動機の一つに、Railsのuse_transactional_tests
みたいなことをRails以外のアプリでやりたいことだったと言っています。
Rails のuse_transactional_tests
実は Rails にはかなり前からdatabase_cleanerと同様の機能(Rails のバージョンにより use_transactional_tests
または use_transactional_fixtures
)を備えてました。また、 rspec-rails も use_transactional_fixtures
でそれをサポートしています。
use_transactional_fixtures
という名称が紛らわしかったため、あまり知られてなかったらしいです。Rails 4までuse_transactional_fixtures
という名称だったので、Rails 標準の fixture を使わない人(例: FactoryBot を使う人)が使えないと勘違いして無効化にする傾向があったそうです。そのため、Rails 5からはuse_transactional_tests
へと名称が変更されたとのことです。
database_cleaner
実はdatabase_cleaner の作者は元々Rails にあったuse_transactional_fixtures
のような機能をRailsを使わないアプリで使いたいというのが動機の一つであったとのことです。
One of my motivations for writing this library was to have an easy way to turn on what Rails calls "transactional_fixtures" in my non-rails ActiveRecord projects.
以下はGoogle Translate の翻訳です。
このライブラリを作成した動機の 1 つは、Rails 以外の ActiveRecord プロジェクトで Rails が「transactional_fixtures」と呼ぶものを簡単に有効にできるようにすることでした。
Rails PR #19282
This is pretty embarrassing, but I've been using Rails almost since 1.0 and I had no idea that transactional fixtures were running on my tests. I don't use fixtures so I just erroneously assumed that feature didn't work for me. I've been using Database Cleaner unnecessarily for like the last four years. I know, it seems ridiculous, but I talked to a few other fairly savvy Rails users and they had no idea either. I'm beginning to think my misunderstanding is fairly common.
以下はGoogle Translate の翻訳です。
かなり恥ずかしい話ですが、私は Rails をほぼ 1.0 から使っていますが、テストでトランザクション フィクスチャが実行されていることを知りませんでした。私はフィクスチャを使用していないので、その機能が動作しないものと誤って想定していました。私は過去 4 年間ほど、Database Cleaner を不必要に使用していました。馬鹿げているように思われるかもしれませんが、他のかなり詳しい Rails ユーザー数名と話しましたが、彼らもまったく知りませんでした。私の誤解はかなり一般的であると思い始めています。
本PRはマージされRails5に導入されました。
Rail system spec
Rails 5.1でシステムテストが導入される以前は、Capybara を使用して外部ブラウザで JavaScript テストを実行した場合に外部ドライバーが別のプロセスで実行されていたためデータベースが期待どおりにクリーンアップされないという問題が存在し、それを軽減するためにdatabase_cleaner が一定の役割を果たしていたようです。
Rails システムテストでは、Railsプロセスでドライバーを実行するため、これらの問題は発生しないとのことです。
おわりに
database_cleanerをインストールしなくても、Railsのデフォルト機能で同じようなことをRailsがいい感じにやってくれることがわかりました。
他に何か良い情報があれば、ぜひお便りください!