There are comments in the rails codebase that indicate that the test database should be reset between runs
rake -T
rake test:all # Run tests quickly by merging all types and not resetting db
rake test:all:db # Run tests quickly, but also reset db
config/database.yml
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
This doesn''t seem to be the case for me.
I'm using factory girl generate test models, here is an example factory
FactoryGirl.define do
factory :podcast do
sequence(:title) { |n| "Podcast #{n}" }
sequence(:feed_url) { |n| "http://podcast.com/#{n}" }
end
end
The podcast should have a unique feed_url so I validate it's uniqueness in the model.
class Podcast < ActiveRecord::Base
validates :feed_url, uniqueness: true, presence: true
end
In test_helper.rb
I lint all factories
ENV["RAILS_ENV"] ||= "test"
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require 'minitest/autorun'
FactoryGirl.lint
My test creates a podcast, builds another with the same name, then asserts that the second is invalid.
require 'test_helper'
describe Podcast do
describe '#feed_url' do
it 'must be unique' do
podcast = create(:podcast)
new_podcast = build(:podcast, feed_url: podcast.name)
assert_invalid podcast, :feed_url, 'has already been taken'
end
end
end
The first time I run the tests it executes without errors and the tests all pass. The second time I run the tests the Factory Girl lint fails because podcast feed_url has already been taken.
Why isn't the test database being rebuilt between runs?
We have a more involved FactoryGirl set up that prepares our database with some canonical items, but I think you could probably put this code directly in your test_helper.rb
to assure the database is emptied:
# Destroy all models because they do not get destroyed automatically
(ActiveRecord::Base.connection.tables - %w{schema_migrations}).each do |table_name|
ActiveRecord::Base.connection.execute "TRUNCATE TABLE #{table_name};"
end
Alternatively, run rake db:test:prepare
before every run.
There is a gem too that you can use, but I don't have any experience with it: http://rubygems.org/gems/database_cleaner.