Umbrella for the synthetic test data generators beyond plain Faker - FactoryBot (Ruby factories with traits, associations, and build / create / build_stubbed strategies), Mimesis (fast type-hinted Python generator with the Schema/Field bulk pattern and 46 locales), and Bogus (.NET typed `Faker<T>` builders with `.RuleFor` / `StrictMode` / `UseSeed`). Picks the right generator by language and job, shows side-by-side equivalents of the same fixture across all four ecosystems, and carries each tool's full workflow in references/ (factory-bot.md, mimesis.md, bogus.md). faker-data stays the default for plain field values in Python / JS / Ruby; use this skill when the project needs typed factory orchestration, .NET fixtures, or a documented "which tool should I use" decision.
72
91%
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
Reference detail for synthetic-data-toolkit. 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.
Per factory_bot-readme, FactoryBot supports three:
| Strategy | What it does | When to use |
|---|---|---|
build(:x) | Returns an unsaved ActiveRecord object. | Pure-logic tests; no DB persistence needed. |
create(:x) | Saves the object (and any associations) to the database. | Integration tests that exercise persistence. |
build_stubbed(:x) | Returns a stubbed object: appears persisted (new_record? returns false) but never hits the database. | Speed up unit tests that don't actually need DB IO. |
Speed hierarchy: build_stubbed >> build >> create. Use the
weakest one that still tests what you need.
build(:user) # Unsaved User instance
create(:user) # Persisted User (and any associations)
build_stubbed(:user) # Fake-persisted User; `id` is set, `new_record?` is falsePlug 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.
| Anti-pattern | Why it fails | Fix |
|---|---|---|
FactoryBot.create(:user) in every test, even for read-only assertions | Database overhead per test; suite slows linearly with test count. | Use build_stubbed for unit tests that don't exercise persistence; reserve create for integration tests. |
| One mega-factory with 30 attributes in the base | Every create(:user) writes 30 columns; tests that need 3 attributes pay the cost. | Minimal base factory + traits for the rich variants. |
| Per-test-class factory definitions | Two test files re-define :user differently; subtle bug. | One factory per class, in spec/factories/ (auto-loaded by factory_bot_rails). |
sequence for fields that should be random (e.g. names) | Sequence values are predictable; tests pass on User 1 User 2 patterns that wouldn't pass on real names. | Use Faker for value variety, sequence for uniqueness only. |
create_list(:user, 100) per test | DB write storm; even fast tests stall on bulk insert. | Use build_stubbed_list if persistence isn't required; if it is, use raw SQL bulk insert. |
| Factory associations that always create the parent | A test of Post creates a User; that creates 5 Permissions; etc. - explosion of objects. | Pass an existing parent: create(:post, user: existing_user). |
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).seed-data-curator - downstream workflow consuming FactoryBot for E2E suite seeds.