In the test suite for my app, I use DatabaseCleaner to clear things out for each test. I’ve got a strange situation where one test fails roughly every other time I run the test suite, although that test passes when run individually. I’ve seen this occasionally with other tests in the suite.
Here’s the failure:
1) FactoryGirl creates a valid user record
Failure/Error: user = FactoryGirl.create :user, :login => 'joe', :password => 'password', :email => 'joe@example.com'
ActiveRecord::RecordInvalid:
Validation failed: Email has already been taken, Email has already been taken, Login has already been taken
# ./spec/factories/factories_spec.rb:5:in `block (2 levels) in <top (required)>'
Here’s the test currently failing; I don’t think the problem is with this particular test.
require 'spec_helper'
describe FactoryGirl do
it "creates a valid user record" do
user = FactoryGirl.create :user, :login => 'joe', :password => 'password', :email => 'joe@example.com'
expect(user.login).to eq 'joe'
end
end
Here’s my DatabaseCleaner setup, stored in ./spec/support/database_cleaner.rb. I’ve turned off several options trying to stabilize my tests:
require 'database_cleaner'
RSpec.configure do |config|
# From Avdi Grimm: http://devblog.avdi.org/2012/08/31/configuring-database_cleaner-with-rails-rspec-capybara-and-selenium/
config.before(:suite) do
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do
#DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with :truncation
end
#config.before(:each, :js => true) do
# DatabaseCleaner.strategy = :truncation
#end
#config.before(:each) do
# DatabaseCleaner.start
#end
#config.after(:each) do
# DatabaseCleaner.clean
#end
end
I also have config.use_transactional_fixtures = false in my spec_helper.rb file.
config.use_transactional_fixtures = false
config.before(:suite) do
DatabaseCleaner.clean_with :truncation
DatabaseCleaner.strategy = :transaction
end
config.before(:each) do |group|
case group.example.metadata[:type]
when :request
DatabaseCleaner.strategy = :truncation
else
DatabaseCleaner.strategy = :transaction
end
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
Thanks, @charlieanna, but it gave even stranger results :=) I ran rspec spec repeatedly and got the following results in terms of number of errors reported:
Not using guard / spork. I removed that FactoryGirl spec and now all my specs run reliably… quite frankly, I have no idea why that worked… but thank you! Maybe you or someone else can explain the internal machinations going on here.
I just figured something today abt using FactoryGirl along with the database_cleaner and the integration tests. I am not sure what you are doing but still I would like to explain what I learned.
First, when you run things using the integration tests, your browser is evoked which makes the browser start a new thread on which the a new connection is established to the database. So if you were using FactoryGirl along with it then FactoryGirl and your browser both would be trying to access the database at the same time which makes your database to get locked. To avoid this you use truncation strategy. What that does is that after each test it deletes the whole database and creates one new again, so this happens for each test and thus avoiding the database from getting locked because the tests are somehow getting cleaned after each tests. Or is simpler words
truncation removes all data from the database and transaction rollbacks all changes that has been made by the running scenario.
Or in transaction whatever records were created when a test ran are simply deleted whereas in truncation all the data are deleted and tables are created again.
Because of this you can use FactoryGirl.create along with integration tests by using transactional strategy. You have to use truncation. You can transaction with models and controller specs.
I am not sure how your factories.rb look like but I think you are failing validations there.
Maybe if you could show your file here I might be able to help.