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.

I'm a solo developer in Vietnam. 50K Chrome extension users. $500K+ on Upwork. 5 Claude Max subscriptions running agent fleets in parallel. These are my actual CLAUDE.md templates, orchestration configs, and prompts. Not a course. Not theory. The files I copy into every project before I write a line of code. **[See what's inside →](https://zovo.one/lifetime?utm_source=ccg&utm_medium=cta-default&utm_campaign=claude-code-factory-bot-test-data-guide)** $99 once. Free forever. 47/500 founding spots left.

Related Reading

Built by theluckystrike. More at zovo.one

Find the right skill → Browse 155+ skills in our Skill Finder.