Testing all Factories (with RSpec)

Leif Ringstad edited this page Nov 1, 2017 · 26 revisions

FactoryBot.lint now exists

IMPORTANT: This functionality is no longer necessary for newer versions of FactoryBot that now support FactoryBot.lint

To make sure that your factories are valid you can automatically test all of them with:

# /spec/support/factories_spec.rb

# If using RSpec 2.x (or if not using Rails), require `spec_helper` instead
require 'rails_helper' 

# If using RSpec 2.x, remove `RSpec.`
RSpec.describe "Factory Bot" do
  FactoryBot.factories.map(&:name).each do |factory_name|
    describe "#{factory_name} factory" do

      # Test each factory
      it "is valid" do
        factory = FactoryBot.build(factory_name)
        if factory.respond_to?(:valid?)
          # the lambda syntax only works with rspec 2.14 or newer;  for earlier versions, you have to call #valid? before calling the matcher, otherwise the errors will be empty
          expect(factory).to be_valid, lambda { factory.errors.full_messages.join("\n") }
        end
      end

      # Test each trait
      FactoryBot.factories[factory_name].definition.defined_traits.map(&:name).each do |trait_name|
        context "with trait #{trait_name}" do
          it "is valid" do
            factory = FactoryBot.build(factory_name, trait_name)
            if factory.respond_to?(:valid?)
              expect(factory).to be_valid, lambda { factory.errors.full_messages.join("\n") }
            end
          end
        end
      end

    end
  end
end

Guard (optional)

If you'd like to use Guard RSpec to automatically rerun your factory tests whenever you save a factory:

# /Guardfile
guard :rspec, cmd: 'bundle exec rspec' do

  # Watch factories
  watch(%r{^spec/factories/(.+)\.rb$}) { "spec/support/factories_spec.rb" }

  # ...

end