RSpec2 + Capybara-Webkitでの注意点
昨日の記事 id:sandmark:20120324 に不備があったので補足です。
参考サイト: kinopyo blog - Learning through Writing
RSpec2はテストをそれぞれ実行するときデータベースをクリアしてくれますが、
capybara-webkit を使ったとき(it "hoge", :js => trueのとき)は
データが渡されない+クリアされない=テストが動かないので、何とかしてやる必要があります。
gem 'database_cleaner' を使ってRSpec2に設定をしてやります。
Gemfile:
group :test, :development do gem "database_cleaner" end
spec/spec_helper.rb:(2012-04-03: 間違いです。後述。)
RSpec.configure do |config| # ... # # If you're not using ActiveRecord, or you'd prefer not to run each of your # examples within a transaction, remove the following line or assign false # instead of true. config.use_transactional_fixtures = false # true から false へ修正 # 以下 DatabaseCleaner 用の設定を追記 config.before(:suite) do DatabaseCleaner.strategy = :truncation end config.before(:each) do DatabaseCleaner.start end config.after(:each) do DatabaseCleaner.clean end end
これによってテストのたびに DatabaseCleaner が実行され、
テスト用データベースをクリーンに保つことができます。
2012-04-03: 追記
テスト用データベースがクリーンに保たれるのは実に素晴らしいことなんですが、
ひとつひとつのテストのたびにデータを保存・クリアしているとやたら遅くなります。
90個弱あるテストが50秒弱で終わったので、ひとつのテストにつき2秒近くかかっている計算になります。
それはあんまりにもあんまりなので、DatabaseCleanerには必要なときだけ動いてもらいます。
というわけで上記 spec/spec_helper.rb の設定は間違い*1で、
現時点(database_cleaner0.7.2)では以下のコードが最適解のようです。
RSpec.configure do |config| # ... # # If you're not using ActiveRecord, or you'd prefer not to run each of your # examples within a transaction, remove the following line or assign false # instead of true. config.use_transactional_fixtures = true # true のままにしておく # If true, the base class of anonymous controllers will be inferred # automatically. This will be the default behavior in future versions of # rspec-rails. config.infer_base_class_for_anonymous_controllers = false # database_cleaner config.before :suite do DatabaseCleaner.strategy = :truncation DatabaseCleaner.clean_with :truncation # 追記 end config.before :each do if example.metadata[:js] # example.metadata で it ディレクティブへの引数を参照できる # JavaScriptを使うテストではデータの受け渡しが不可欠なので、 # 一時的にフィクスチャがクリアされないようにする。 self.use_transactional_fixtures = false # ←重要 DatabaseCleaner.start end end config.after :each do if example.metadata[:js] DatabaseCleaner.clean # データをクリアし、 self.use_transactional_fixtures = true # フィクスチャの受け渡しも元へ戻す end end Capybara.javascript_driver = :webkit end
それでは改めて、みなさん快適なテスト駆動開発を!
*1:厳密には間違いではなく動作します。致命的に遅いだけ。