Did a quick benchmark last week to find the optimal way to configure Rspec on our projects that use Postgres and DatabaseCleaner

One of our test suites takes 3.5 minutes to run when we do NOT use DatabaseCleaner, the default rspec setup:

# spec_helper.rb
#config.use_transactional_examples = false 
#config.before(:suite) do 
# DatabaseCleaner.strategy = :transaction 
# DatabaseCleaner.clean_with(:truncation) 
#end 
#config.before(:each) do 
# DatabaseCleaner.start 
#end 
#config.after(:each) do 
# DatabaseCleaner.clean 
#end

When we enabled database cleaner (with default .strategy = :transaction), the test still took 3.5 minutes, but we got lots of warnings:**WARNING: there is already a transaction in progress
NOTICE: there is no transaction in progress
**

# spec_helper.rb
 #config.use_transactional_examples = false 
config.before(:suite) do 
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation) 
end 
config.before(:each) do 
DatabaseCleaner.start 
end 
config.after(:each) do 
DatabaseCleaner.clean 
end

However, when we changed the .strategy to :trunctation, it eliminated the warnings, but slowed the tests down to 8 minutes!# spec_helper.rb

#config.use_transactional_examples = false 
config.before(:suite) do 
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.clean_with(:truncation) 
end 
config.before(:each) do 
DatabaseCleaner.start 
end 
config.after(:each) do 
DatabaseCleaner.clean 
end

The best results were to leave the strategy set to :transaction, but set config.use_transactional_examples = false. That yielded a runtime of about 3.5 minutes.

# spec_helper.rb
 config.use_transactional_examples = false 
config.before(:suite) do 
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation) 
end 
config.before(:each) do 
DatabaseCleaner.start 
end 
config.after(:each) do 
DatabaseCleaner.clean 
end

We used the following addition spec to verify that the database was being cleaned. (run this with –order default )

#dbclean_spec.rb

require "spec_helper" 
Refer.destroy_all 
describe Refer do 
it "has none to begin with" do 
  Refer.count.should == 0 
end 
it "has one after adding one" do 
Refer.create 
Refer.count.should == 1 
end 
it "has none after one was created in a previous example" do Refer.count.should == 0 
end 
end