Testing Your Factories First

Reade Harris

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.


  1. Looking for FactoryGirl? The library was renamed in 2017.