How can I isolate the usage of fixtures to specific tests?
In my setup some of my tests rely on fixture data and some don't, so the default of loading all my fixtures in test_helper.rb with fixtures :all
breaks my tests.
Example integration test that requires empty behaviorists table:
require 'test_helper'
class WelcomeFlowTest < ActionDispatch::IntegrationTest
test "when no user is found start welcome flow" do
get "/"
follow_redirect!
assert_response :success
post "/setup", {
behaviorist: { name: "Andy", email: "[email protected]" },
habit: { name: "Interval running", on_monday: false, on_tuesday: true, \
on_wednesday: false, on_thursday: true, on_friday: false, \
on_saturday: true, on_sunday: false }
}
assert_response :success
assert_equal 1, Behaviorist.count
assert_equal 1, Habit.count
end
end
My unit test that requires behaviorist fixtures:
require 'test_helper'
class BehavioristTest < ActiveSupport::TestCase
test "validates uniqueness of :name" do
andy = Behaviorist.new(name: "Andy", remote_ip: "127.0.0.1")
assert_not run.valid?
assert_match /has already been taken/, andy.errors[:name].join
end
end
With a little digging on how Rails implements fixtures I see that fixtures, once loaded, are isolated from changes within each TestCase via a transaction. My working solution is to remove loading the fixtures :all
inside the test_helper.rb. Then for each test that requires fixtures I override the default of using transactional fixtures, load specific fixtures, and then remove them on teardown.
Example of isolated fixtures for single TestCase:
require 'test_helper'
class BehavioristTest < ActiveSupport::TestCase
self.use_transactional_fixtures = false
fixtures :behaviorists
teardown :delete_behaviorists
test "validates uniqueness of :name" do
andy = Behaviorist.new(name: "Andy", remote_ip: "127.0.0.1")
assert_not run.valid?
assert_match /has already been taken/, run.errors[:name].join
end
private
def delete_behaviorists
Behaviorist.delete_all
end
end