Rails Using FactoryBot

Use syntax helpers

Always include the syntax helpers in your tests. This makes build and create available in your test cases.

# rails_helper.rb
config.include FactoryBot::Syntax::Methods

Build, don't create

Prefer build over create, if you can get away with it. This can lead to faster tests. Avoid build_stubbed.

Use sequences

Never hard-code emails and similar fields that must be unique. Use sequence when possible.

factory :user do
  sequence(:email) { |i| "user-#{i}@email.com" }
  ...
end

Write reusable sequences when possible

Place reusable sequences in a separate file.

# spec/factories/factory_sequences.rb
FactoryBot.define do
  sequence(:uid) { |i| SecureRandom.uuid }
  sequence(:email) { |i| "user-#{i}@email.com" }
end

factory :admin do
  uid
  email
end

factory :client do
  uid
  email
end

Traits

Traits can be used to remove duplication, but use them sparingly.

Always update

Make sure that factories are always up to date.

Simple defaults

Always provide the simplest defaults for your factories. Prefer to only add fields that are validated such that records built through the factory will pass validation. Other fields would only serve to make for confusing future tests and make it difficult to test default behavior.

class Profile < ActiveRecord::Base
  validates :name, presence: true
  validates :gender, inclusion: %w(male female)
end

factory :profile do
  name "Jack Sparrow"
  gender "male"
  occupation "Pirate" # <- Don't
  bio "Jack is a pirate lord of the seven seas." # <- Don't
end

Test your factories

Test your factories. This will make it easy to spot any factories that may be out of date.

EXCLUDED = [:factories, :to, :exclude, :if, :any]

FactoryBot.factories.map(&:name).each do |factory_name|
  next if EXCLUDED.include?(factory_name)

  it "the #{factory_name} factory is valid" do
    expect(build factory_name).to be_valid
  end
end