Claude Code Factory Bot Test Data (2026)
Claude Code Factory Bot Test Data Guide
Factory Bot is a Ruby library for building test data fixtures in a flexible and maintainable way. When combined with Claude Code, you can automate factory creation, generate complex test scenarios, and build solid test suites faster than ever.
Understanding Factory Bot Basics
Factory Bot replaces traditional Rails fixtures with a more expressive, configurable approach to test data. Instead of static YAML files, you define factories as Ruby classes that can generate objects with default values, associations, and dynamic attributes.
Setting Up Factory Bot in Your Project
First, add Factory Bot to your Gemfile:
group :test do
gem 'factory_bot_rails'
end
Then run bundle install and configure Factory Bot in your test setup:
spec/rails_helper.rb
RSpec.configure do |config|
config.include FactoryBot::Syntax::Methods
end
Defining Your First Factory
Create factories in spec/factories/ with a clear, consistent naming convention:
spec/factories/users.rb
FactoryBot.define do
factory :user do
sequence(:email) { |n| "user#{n}@example.com" }
first_name { "John" }
last_name { "Doe" }
password { "securePassword123" }
admin { false }
factory :admin_user do
admin { true }
role { "admin" }
end
end
end
Using Factory Bot with Claude Code
When working with Claude Code, you can use its understanding of Factory Bot to generate factories for your existing models and create sophisticated test data scenarios.
Generating Factories from Models
Ask Claude Code to analyze your models and create appropriate factories:
Create Factory Bot factories for my User, Post, and Comment models.
Include associations, valid sequences, and trait variations for common states.
Claude Code will generate factories similar to:
spec/factories/posts.rb
FactoryBot.define do
factory :post do
title { "Sample Post Title" }
body { "This is the post content body." }
published { false }
association :author, factory: :user
trait :published do
published { true }
published_at { Time.current }
end
trait :draft do
published { false }
end
factory :published_post, traits: [:published]
factory :draft_post, traits: [:draft]
end
end
spec/factories/comments.rb
FactoryBot.define do
factory :comment do
body { "Great article!" }
association :post
association :author, factory: :user
end
end
Building Complex Test Scenarios
Factory Bot shines when you need to create related records for testing complex associations:
Creating a post with multiple comments
let(:post_with_comments) do
create(:post, :published).tap do |post|
create_list(:comment, 3, post: post)
end
end
Creating a user with posts
let(:prolific_author) do
create(:user, first_name: "Prolific").tap do |user|
create_list(:post, 10, :published, author: user)
end
end
Advanced Factory Bot Patterns
Using Transient Attributes
Transient attributes don’t map directly to model fields but customize factory behavior:
FactoryBot.define do
factory :order do
transient do
item_count { 3 }
include_discount { false }
end
after(:build) do |order, evaluator|
if evaluator.include_discount
order.discount_percentage = 15
end
end
after(:create) do |order, evaluator|
create_list(:line_item, evaluator.item_count, order: order)
end
end
end
Factory Sequences for Unique Data
Ensure unique values across test runs with sequences:
FactoryBot.define do
factory :account do
sequence(:subdomain) { |n| "company#{n}" }
sequence(:email) { |n| "admin#{n}@company.com" }
name { "Company Name" }
end
end
Inheritance and Aliases
Create base factories and extend them:
FactoryBot.define do
factory :post do
title { "Default Title" }
body { "Default body content" }
author
factory :article do
type { "Article" }
category { "tech" }
end
factory :announcement do
type { "Announcement" }
priority { "high" }
end
end
factory :guest_post, parent: :post do
author { create(:user, :guest) }
end
end
Integration with RSpec
Factory Bot Methods in Tests
After configuring the syntax methods, use factories directly in your tests:
RSpec.describe Post do
describe "#publish!" do
it "changes published status to true" do
post = create(:post, :draft)
post.publish!
expect(post.published?).to be true
end
it "sets published_at timestamp" do
post = create(:post, :draft)
expect { post.publish! }.to change(post, :published_at).from(nil)
end
it "notifies followers" do
post = create(:post)
follower = create(:user, :following, post: post)
expect { post.publish! }.to change { follower.notifications.count }.by(1)
end
end
end
Using Factory Traits for Test Variations
Organize test data variations with traits:
RSpec.describe User do
describe "#can_post?" do
context "with active subscription" do
let(:user) { create(:user, :active, subscription: "pro") }
it { expect(user.can_post?).to be true }
end
context "with basic subscription" do
let(:user) { create(:user, :active, subscription: "basic") }
it { expect(user.can_post?).to be false }
end
context "with inactive account" do
let(:user) { create(:user, :inactive) }
it { expect(user.can_post?).to be false }
end
end
end
Factory with traits
FactoryBot.define do
factory :user do
name { "Test User" }
subscription { "free" }
trait :active do
active { true }
end
trait :inactive do
active { false }
end
end
end
Best Practices for Factory Bot
Keep Factories Fast
Avoid slow operations in factories:
Bad - file processing in factory
factory :document do
file { File.open(Rails.root.join("spec/fixtures/large.pdf")) }
end
Good - minimal, fast factory
factory :document do
filename { "document.pdf" }
content_type { "application/pdf" }
end
Use build_stubbed for Unit Tests
For tests that don’t hit the database, use stubbed objects:
Much faster - no database write
user = build_stubbed(:user)
expect(user.name).to eq("John Doe")
Clean Up Between Tests
Factory Bot handles cleanup automatically, but for performance-critical tests:
RSpec.configure do |config|
config.before(:suite) do
DatabaseCleaner.strategy = :transaction
FactoryBot.lint
end
end
Working with Associations
Handling Dependent Records
FactoryBot.define do
factory :project do
name { "My Project" }
owner
# Automatically create owner if not provided
association :owner, factory: :user
# With nested attributes
factory :project_with_tasks do
after(:create) do |project|
create_list(:task, 5, project: project)
end
end
end
end
Self-Referential Associations
FactoryBot.define do
factory :user do
sequence(:username) { |n| "user#{n}" }
factory :user_with_friends do
after(:create) do |user|
friend1 = create(:user)
friend2 = create(:user)
user.friendships.create!(friend: friend1)
user.friendships.create!(friend: friend2)
end
end
end
end
Conclusion
Factory Bot combined with Claude Code creates a powerful testing workflow. Use Claude Code to generate factories from your models, create test data scenarios, and maintain clean, reusable factory definitions. This approach ensures your test suite remains fast, maintainable, and expressive.
Troubleshooting Factory Bot Performance
Diagnosing Slow Test Suites
Factory Bot is often blamed for slow test suites, but the real culprit is usually unnecessary database writes. Profile your factories to find the hot spots:
spec/support/factory_bot_profiler.rb
module FactoryBotProfiler
SLOW_THRESHOLD_MS = 100
def self.enable!
ActiveSupport::Notifications.subscribe('factory_bot.run_factory') do |name, start, finish, id, payload|
duration_ms = ((finish - start) * 1000).round(1)
factory_name = payload[:name]
strategy = payload[:strategy]
if duration_ms > SLOW_THRESHOLD_MS
Rails.logger.warn "[FactoryBot] Slow factory: #{factory_name} took #{duration_ms}ms"
end
end
end
end
Run with PROFILE_FACTORIES=1 bundle exec rspec to identify which factories consistently exceed the threshold.
Replacing create with build_stubbed at Scale
The single most impactful optimization for pure unit tests is replacing create with build_stubbed. The stubbed strategy skips the database entirely:
RSpec.describe User do
describe "#display_name" do
it "combines first and last name" do
# Bad: writes to database, unnecessary for this test
user = create(:user, first_name: "Jane", last_name: "Smith")
# Good: no database write, 10-100x faster
user = build_stubbed(:user, first_name: "Jane", last_name: "Smith")
expect(user.display_name).to eq("Jane Smith")
end
end
end
Apply this pattern to any test that exercises business logic without querying the database. A test suite that replaces 40% of create calls with build_stubbed often sees 30-50% overall speed improvement.
Generating Realistic Test Data
Using Faker for Realistic Attributes
Static factory values like "John Doe" can mask bugs that only appear with real-world input variation. Use Faker to generate realistic data:
spec/factories/users.rb
require 'faker'
FactoryBot.define do
factory :user do
first_name { Faker::Name.first_name }
last_name { Faker::Name.last_name }
sequence(:email) { |n| "user-#{n}@#{Faker::Internet.domain_name}" }
phone { Faker::PhoneNumber.cell_phone_in_e164 }
born_on { Faker::Date.birthday(min_age: 18, max_age: 75) }
trait :international do
country_code { Faker::Address.country_code }
end
end
end
Faker generates unique values on each test run, catching encoding issues, boundary conditions, and display formatting bugs that static fixtures never surface.
Building State-Machine Factories
Applications with AASM or StateMachines need factories that respect state transitions. Use callbacks to advance through states correctly:
FactoryBot.define do
factory :order do
user
sequence(:reference) { |n| "ORD-#{n.to_s.rjust(6, '0')}" }
state { 'pending' }
trait :confirmed do
after(:create, &:confirm!)
end
trait :shipped do
after(:create) do |order|
order.confirm!
order.ship!(tracking_number: "TRACK#{rand(1_000_000)}")
end
end
trait :cancelled do
after(:create, &:cancel!)
end
end
end
This ensures your test objects always arrive in a valid state, preventing the flakiness that comes from manually setting state columns without triggering callbacks.
Using Claude Code to Generate Factories
When using Claude Code to generate new factories for your Rails app, include your existing factory conventions in the prompt:
Using Factory Bot, create a factory for the Payment model with these requirements:
- Required associations: user, order
- Amount should use Faker::Commerce.price
- Include traits for: authorized, captured, refunded, failed
- The captured and refunded traits should advance through state machine transitions
- Include a transient attribute for amount_in_cents that calculates from amount
Reference our existing patterns in spec/factories/orders.rb for consistency.
Claude Code reads your existing factories and generates new ones that follow the same patterns: correct trait structure, proper callback placement, and consistent Faker usage across your test suite.
Linting Your Factory Definitions
Use Factory Bot’s built-in linter to catch misconfigured factories before they cause mysterious test failures:
spec/support/factory_linter.rb
RSpec.describe "Factory Bot Linting" do
it "has valid factories" do
expect { FactoryBot.lint }.not_to raise_error
end
end
The linter instantiates each factory and checks that the resulting object is valid according to your model validations. Run this in your CI pipeline on every push. A factory that fails validation silently in tests can cause hours of debugging.
Try it: Paste your error into our Error Diagnostic for an instant fix.
Related Reading
- Claude Code Skills for Ruby on Rails Projects
- Claude Code ActiveRecord Query Optimization Workflow Guide
- Chrome Extension Microphone Test Tool: Developer Guide
Built by theluckystrike. More at zovo.one
Find the right skill → Browse 155+ skills in our Skill Finder.