9

I have a feature spec with Capybara for a login page, and I am using FactoryGirl + DatabaseCleaner

require 'rails_helper'

feature 'Admin signs in' do

  background do
    FactoryGirl.create(:user)
  end

  scenario 'with valid credentials' do
    visit admin_root_path
    fill_in 'user_email', :with => 'email@email.com'
    fill_in 'user_password', :with => 'testpassword'
    click_button 'Sign in'
    expect(page).to have_content('Dashboard')
  end

  scenario 'with invalid credentials' do
    visit admin_root_path
    fill_in 'user_email', :with => 'email@email.com'
    fill_in 'user_password', :with => 'wrongpassword'
    click_button 'Sign in'
    expect(page).to have_content('Admin Login')
  end

end

running the test, I get the following error:

1) Admin signs in test with invalid credentials
 Failure/Error: FactoryGirl.create(:user)
 ActiveRecord::RecordInvalid:
   Validation failed: Email has already been taken

I thought DatabaseCleaner would revert the changes, but it looks like the user record persist in the database till the second scenario block.

How can I make sure that the database is cleaned after the first scenario?

I configured Database cleaner following this post

# support/database_cleaner_spec.rb

RSpec.configure do |config|
  config.before(:suite) do
    DatabaseCleaner.clean_with(:truncation)
  end

  config.before(:each) do
    DatabaseCleaner.strategy = :transaction
  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 have also updated the spec helper file with:

config.use_transactional_fixtures = false
Carlo
  • 1,184
  • 4
  • 15
  • 31

5 Answers5

11

I was wrongly assuming that configuration files in spec/support folder were automatically loaded, but it turns out that I had to uncomment the following line in spec/rails_helper.rb

Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }

The DatabaseCleaner config file was correct, it just wasn't loaded at all.

Carlo
  • 1,184
  • 4
  • 15
  • 31
8

Make sure you have the following configuration in spec/rails_helper.rb

RSpec.configure do |config|
 config.use_transactional_fixtures = true
end

The idea is to start each example with a clean database, create whatever data is necessary for that example, and then remove that data by simply rolling back the transaction at the end of the example.

Rokibul Hasan
  • 4,078
  • 2
  • 19
  • 30
0

use these settings:

config.before(:suite) do
  DatabaseCleaner.clean_with(:truncation)
end
  • I have already that settings, I've updated my question with the DatabaseCleaner config file. The Database cleaner actually works fine, except for "after(:each)" – Carlo Apr 06 '15 at 14:57
0

If by any chance you are using MySQL and altering tables (reset auto increments or whatever DDL operation) within a method within a test, the transaction strategy will fail and your database will not be cleaned.

In order to fix, you have to declare a config block like this:

config.before(:each, :altering_database => true) do
  DatabaseCleaner.strategy = :truncation
end

And add this config to your test context:

context "when you alter the DB", :altering_database => true do...

Note: this will slow down your tests, so be careful not to abuse it.

Fab V.
  • 1,052
  • 12
  • 17
0
  config.before(:example) do
    DatabaseCleaner.clean_with(:truncation)
  end

worked for me!

Paula Muldoon
  • 17
  • 1
  • 6
  • Actually, mine used `:example`, which none of the other answers did...`before(:suite)` cleans the DB after each individual test, which I believe is what the user needed. – Paula Muldoon Jul 05 '17 at 19:46