factory-boy
Test fixture replacement — generates test objects with realistic fake data for Python tests. factory_boy features: Factory class with field declarations, Faker integration for realistic data, SubFactory for related objects, LazyAttribute for computed fields, Sequence for unique incrementing values, RelatedFactory for post-create relations, DjangoModelFactory for Django, SQLAlchemyModelFactory for SQLAlchemy, create()/build()/stub() strategies, create_batch() for multiple objects, Trait for conditional field sets, and reset_sequence() for test isolation.
Score Breakdown
⚙ Agent Friendliness
🔒 Security
Test-only library. Faker generates realistic but fake PII — do not use factory_boy in production data generation. Ensure test DB is isolated from production. factory.Faker('ssn') or similar sensitive data fields should only exist in test factories, never in production code.
⚡ Reliability
Best When
Django and SQLAlchemy test data generation — factory_boy eliminates fixture files and manual test object creation with declarative, composable factories.
Avoid When
Non-Django/SQLAlchemy projects (use pure dataclasses), production data (use migrations), HTTP mocking (use responses), or simple unit tests that don't need DB records.
Use Cases
- • Agent Django factory — import factory; from factory.django import DjangoModelFactory; from myapp.models import User; class UserFactory(DjangoModelFactory): class Meta: model = User; username = factory.Sequence(lambda n: f'user{n}'); email = factory.LazyAttribute(lambda obj: f'{obj.username}@example.com'); first_name = factory.Faker('first_name') — Django; agent creates test users with realistic data; UserFactory.create() saves to DB
- • Agent related objects — class ArticleFactory(DjangoModelFactory): class Meta: model = Article; author = factory.SubFactory(UserFactory); title = factory.Faker('sentence', nb_words=6); content = factory.Faker('text') — related; agent creates article with automatically created author; SubFactory creates related object first; avoids manual FK setup
- • Agent build vs create — user = UserFactory.build() — no DB; user = UserFactory.create() — saves to DB; user = UserFactory.stub() — dict-like, no model; batch = UserFactory.create_batch(5) — creates 5 users — strategies; agent uses build() for tests not requiring DB; create() for integration tests
- • Agent override fields — user = UserFactory(username='admin', is_staff=True) — override; admin = UserFactory.create(username='admin'); batch = UserFactory.create_batch(3, is_active=False) — batch override; agent creates objects with specific field values; override at call time not in factory definition
- • Agent traits — class UserFactory(factory.Factory): class Meta: model = User; is_active = True; is_staff = False; class Params: admin = factory.Trait(is_staff=True, is_superuser=True) — traits; admin_user = UserFactory(admin=True) — activates trait; agent uses traits for conditional field presets; cleaner than multiple factories
Not For
- • Production data generation — factory_boy is for testing only; for production seed data use management commands or migrations
- • Performance benchmarking — DB factories are slow; for bulk test data consider raw SQL or csv loading
- • API response mocking — factory_boy creates Python objects/DB records not HTTP mocks; use responses library for HTTP
Interface
Authentication
No auth — test fixture library.
Pricing
factory_boy is MIT licensed. Free for all use.
Agent Metadata
Known Gotchas
- ⚠ Sequence increments globally — factory.Sequence(lambda n: f'user{n}') increments across all test calls; tests depending on specific sequence values fail non-deterministically; agent code: use reset_sequence() in setUp() or use factory.Sequence for uniqueness only (not specific values); or use factory.Faker for non-sequential unique values
- ⚠ SubFactory creates DB record — SubFactory(UserFactory) calls UserFactory.create() (DB save); if only UserFactory.build() is used, SubFactory still creates; agent code using build(): SubFactory(UserFactory, **{'_create': False}) or override with build strategy in Meta: strategy = factory.BUILD_STRATEGY
- ⚠ LazyAttribute receives declaration object — LazyAttribute(lambda obj: f'{obj.username}@example.com') receives partially-built factory object; fields declared before LazyAttribute are available; fields declared after are NOT yet set; agent code: declare LazyAttribute after all fields it depends on
- ⚠ DjangoModelFactory requires @pytest.mark.django_db — factory.create() touches database; tests must be marked with @pytest.mark.django_db (pytest-django); without mark: django.db.utils.ProgrammingError or AppRegistryNotReady; agent code: mark all tests using DjangoModelFactory.create()
- ⚠ Faker locale must be set explicitly — factory.Faker('name') generates English names; for other locales: factory.Faker('name', locale='fr_FR'); or set globally: factory.Faker._DEFAULT_LOCALE = 'de_DE'; agent code: set locale per-field or globally for consistent locale in test data
- ⚠ create_batch does not use bulk_create — UserFactory.create_batch(100) calls create() 100 times — 100 SQL INSERT statements; slow for large batches; agent code needing many test records: use Django's bulk_create: User.objects.bulk_create([UserFactory.build() for _ in range(100)]); much faster but bypasses post_save signals
Full Evaluation Report
Detailed scoring breakdown, competitive positioning, security analysis, and improvement recommendations for factory-boy.
Scores are editorial opinions as of 2026-03-06.