Authors Ruby FactoryBot factories with traits, associations, sequences, and the three build strategies (build / create / build_stubbed); integrates with RSpec / Minitest test suites; pairs with Faker for randomized field values. Use when the project is Ruby / Rails and needs structured fixture creation with referential integrity.
75
94%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
FactoryBot (formerly factory_girl) is the canonical Ruby fixture-
factory library - it builds object graphs with referential integrity
that raw faker-data cannot
(factory_bot-readme).
The split:
Faker::Name.name).create(:user, :admin, posts_count: 3)) - including sequence-based unique IDs,
associations between models, and trait composition.User with three Posts and a
Profile, all linked correctly.create(:admin))
rather than per-field overrides.factory_bot_rails (Rails) or factory_bot to the test group and require it.spec/factories/, one attribute block each.trait blocks for variants (:admin, :with_posts) instead of separate variant factories.Faker into attribute blocks for randomized values; use .unique where uniqueness matters.build_stubbed for unit, build for no-DB, create for persistence.FactoryBot::Syntax::Methods in the RSpec / Minitest config to call create(:user) directly.gem install factory_botFor Rails projects, prefer the Rails-specific gem with auto-loading:
# Gemfile
group :test do
gem 'factory_bot_rails' # adds Rails-specific helpers and auto-loads spec/factories/
end(Per factory_bot-readme.)
# spec/factories/users.rb
FactoryBot.define do
factory :user do
name { "John Doe" }
email { "john@example.com" }
end
end(Per factory_bot-readme.)
Each attribute is a block - the block is evaluated lazily at object
creation, so Faker::Name.name re-runs per create call.
For unique values across factory invocations:
sequence :email do |n|
"user#{n}@example.com"
end
factory :user do
email # uses the sequence
end(Per factory_bot-readme.)
factory :post do
title { "Hello" }
body { "World" }
user # implicit reference to a user factory
end
# OR explicit association
factory :post do
user # short form
# association :user, factory: :admin # explicit form
end
# Has-many: build N posts from a user factory
factory :user do
name { "John" }
after(:create) do |user|
create_list(:post, 3, user: user)
end
endTraits compose mix-ins onto a base factory:
factory :user do
name { "John Doe" }
email { "john@example.com" }
trait :admin do
role { "admin" }
end
trait :with_posts do
after(:create) do |user|
create_list(:post, 3, user: user)
end
end
end
# Apply one or more traits at create time
FactoryBot.create(:user, :admin, :with_posts)(Per factory_bot-readme.)
Traits are the canonical way to keep factory bodies DRY - instead of
ten variant factories (:admin_user, :premium_user,
:admin_premium_user, …), one base factory plus N traits composes
to all variants.
FactoryBot supports three: build (unsaved), create (persisted with
associations), and build_stubbed (fake-persisted, never hits the DB).
Speed hierarchy: build_stubbed >> build >> create - use the
weakest one that still tests what you need. Full table and examples:
references/strategies-and-anti-patterns.md.
Plug Faker into the factory body for randomized values:
require 'faker'
FactoryBot.define do
factory :user do
name { Faker::Name.name }
email { Faker::Internet.unique.email } # `.unique` enforces uniqueness across factory invocations
age { Faker::Number.between(from: 18, to: 80) }
end
endFaker::Internet.unique (and other unique helpers) tracks
generated values per session and raises if exhausted. Use this
instead of a sequence when you want both randomness and
uniqueness.
# spec/spec_helper.rb (or rails_helper.rb for Rails)
RSpec.configure do |config|
config.include FactoryBot::Syntax::Methods # enables `create(:user)` instead of `FactoryBot.create(:user)`
end
# spec/users_spec.rb
RSpec.describe User do
it 'has a name' do
user = create(:user)
expect(user.name).to be_present
end
end# test/test_helper.rb
class ActiveSupport::TestCase
include FactoryBot::Syntax::Methods
endPer factory_bot-readme; both syntaxes mirror the same DSL - only the test-framework hookup differs.
A test needs an admin user that owns three posts. Define the factory with two traits and Faker-backed values:
# spec/factories/users.rb
FactoryBot.define do
factory :user do
name { Faker::Name.name }
email { Faker::Internet.unique.email }
trait :admin do
role { "admin" }
end
trait :with_posts do
after(:create) { |user| create_list(:post, 3, user: user) }
end
end
endCompose both traits in one intent-revealing call:
RSpec.describe User do
it 'admin owns three posts' do
user = create(:user, :admin, :with_posts)
expect(user.role).to eq('admin')
expect(user.posts.count).to eq(3)
end
endcreate persists the user and, via the :with_posts after(:create)
hook, its three posts - one line instead of six lines of manual setup.
Common FactoryBot pitfalls - create for read-only tests, mega base
factories, per-test-class definitions, sequence where values should
be random, bulk create_list, and always-create associations - and
their fixes are catalogued in
references/strategies-and-anti-patterns.md.
factory_bot_rails. Pure Ruby projects
must require factory files manually.has_many through:. You can express it
with after(:create) blocks, but the syntax is hand-rolled.user1@example.com ... user5000@example.com. If
asserting on the n-th sequence value, your test breaks when run
in isolation.faker-data - Ruby Faker (the value
engine for FactoryBot fields).synthetic-data-tool-selector -
dispatcher selecting the right factory library per language.seed-data-curator - downstream
workflow consuming FactoryBot for E2E suite seeds.