When using a library like Selenium (via Capybara) the browser process will execute on a thread separate from the actual test environment and because database transactions aren't always supported across threads you can find yourself in a problem spot when the occasional test fails but test data still lingers.
Under normal circumstances your specs execute in the same thread as everything else, making database transactions the ideal way to clean up test data - simply roll back the transaction at the end of each test. In fact in most spec_helper.rb you'll find a line exactly like this:
# ./spec/spec_helper.rb ⋮ config.use_transactional_fixtures = true ⋮... which configures this transaction rollback behavior. Sometimes though you need to go a bit more industrial strength, due to the threading condition I opened this article with. In that case database_cleaner is your friend. Database Cleaner can be configured to clean up after every spec by truncating all of the tables in the database (except schema_migrations) which is configurable if you have special tables - like PostGIS template tables. But is it necessary to truncate clean for every single spec when some specs can use transactional fixtures and just roll back? RSpec's before and after hooks allow filtering on metadata so you can conditionally use Database Cleaner for some specs and use the default roll back behavior for others. My spec_helper.rb gets this configuration:
# ./spec/spec_helper.rb RSpec.configure do |config| ⋮ config.before(:suite) do DatabaseCleaner.strategy = :truncation DatabaseCleaner.clean_with(:truncation) end config.before(:each, :clean_up => :truncate) do DatabaseCleaner.start end config.after(:each, :clean_up => :truncate) do DatabaseCleaner.clean puts 'Cleaned with DatabaseCleaner' end ⋮ endThe :clean_up => :truncate isn't as magical as it looks at first glance. All that is going on here is a filter match so these hooks will only run for specs that meet the criteria set in the filter - that is have a :clean_up => :truncate option specified for the spec itself:
# ./spec/features/signing_up_spec.rb feature 'Signing Up' do scenario 'registering a new user (in US)', :clean_up => :truncate do visit new_user_registration_path ⋮