Recently I added few integration tests in my projects using Capybara and Selenium webdriver and ran into banging my head against inconsistencies with test database. I create some records in test DB which were completely invisible to Selenium-driven browser-based tests.

The problem is: the tests are being wrapped in database transactions, so any code running outside the actual test process (like, say, a server process servicing a Selenium-driven browser request) does not see the database records.

Here are the steps to fix this problem -

First of all, and this is very important, go into spec/spec_helper.rb and change this line:

 config.use_transactional_fixtures = true

to:

 config.use_transactional_fixtures = false

This will disable rspec-rails implicit wrapping of tests in a database transaction. Without disabling this, none of the following configuration will matter.

Now configure database_cleaner. [database_cleaner(database cleaner)][1] is a gem that abstracts away the various ORM APIs for getting the DB into a “blank slate” state.

 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

Let’s take that step by step.

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

This means: before the entire test suite runs, clear the test database completely.

 config.before(:each) do
  DatabaseCleaner.strategy = :transaction
end

This sets the default database cleaning strategy to be transactions. Transactions are very fast.

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

This line only runs before examples which have been flagged js: true. By default, these are the only tests for which Capybara fires up a test server process and drives an actual browser window via the Selenium backend. For these types of tests, transactions won’t work, so this code overrides the setting and chooses the “truncation” strategy instead.

 config.before(:each) do
  DatabaseCleaner.start
end
config.after(:each) do
  DatabaseCleaner.clean
end

These lines hook up database_cleaner around the beginning and end of each test, telling it to execute whatever cleanup strategy we selected beforehand.

And that’s it!
[1]: https://github.com/DatabaseCleaner/database_cleaner