Getting RSpec, Postgres, DatabaseCleaner to play nicely together
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