Have you ever added a seemingly innocent validation to a model, like so:
class User < ActiveRecord::Base
validates_presence_of :first_name
end
And then had this happen?:
rake spec
If you’re using FactoryBot1, this can often happen because you haven’t updated your factory to respect the new validation.
Of course, the fix is simple:
# spec/factories.rb
FactoryBot.define do
factory :user do
first_name { 'Jonah' }
end
end
But how do you save yourself the time (and potential heart attack) of watching all those dreaded Fs go by?
Watching Over Your Factories
My old solution used to be adding a boilerplate test in each model’s unit spec, like so:
# spec/models/user_spec.rb
describe User do
it 'has a valid Factory' do
build(:user).should be_valid
end
end
This is better than nothing, but it has two major problems.
- It’s not DRY. This code needs to be added to every unit spec.
- It’s slow. The whole model spec (and potentially many other specs) will have to run before we can address the failure.
Enter our savior, the factories_spec.rb
:>
# spec/factories_spec.rb
FactoryBot.factories.map(&:name).each do |factory_name|
describe "The #{factory_name} factory" do
it 'is valid' do
build(factory_name).should be_valid
end
end
end
Fancytime! Now all our factory specs are in one place, DRY as a desert.
Fast-Failing Factories
On to the second problem: we don’t want to wait for all our specs to run to deal with this error.
If you use rake
to run your tests, one way to take care of this is by adding a
pre-requisite to your rake spec
task:
# Rakefile
if defined?(RSpec)
desc 'Run factory specs.'
RSpec::Core::RakeTask.new(:factory_specs) do |t|
t.pattern = './spec/factories_spec.rb'
end
end
task spec: :factory_specs
Now the :factory_specs
task will need to run and succeed before the whole
suite is run. If you have a bad factory, you’ll know right away with a nice
failure message:
rake spec
No more panic attacks necessary.
Just one of the many new things I’ve learned in my first day as a thoughtbot apprentice!
Project name history can be found here.
-
Looking for FactoryGirl? The library was renamed in 2017. ↩