import factory
from factory.django import DjangoModelFactory
from factory import Faker, SubFactory, post_generation
from blog.models import Post, Comment, Tag
from django.contrib.auth import get_user_model
User = get_user_model()
class UserFactory(DjangoModelFactory):
class Meta:
model = User
email = Faker('email')
first_name = Faker('first_name')
last_name = Faker('last_name')
is_active = True
class TagFactory(DjangoModelFactory):
class Meta:
model = Tag
name = factory.Sequence(lambda n: f'tag-{n}')
class PostFactory(DjangoModelFactory):
class Meta:
model = Post
title = Faker('sentence', nb_words=6)
content = Faker('paragraph', nb_sentences=10)
author = SubFactory(UserFactory)
status = 'published'
@post_generation
def tags(self, create, extracted, **kwargs):
if not create:
return
if extracted:
for tag in extracted:
self.tags.add(tag)
class CommentFactory(DjangoModelFactory):
class Meta:
model = Comment
post = SubFactory(PostFactory)
author = SubFactory(UserFactory)
content = Faker('paragraph')
approved = True
Factory Boy eliminates boilerplate in tests by generating model instances with sensible defaults. I use Sequence for unique values, SubFactory for foreign keys, and post_generation for many-to-many relationships. The Faker integration provides realistic data. I create factories in tests/factories.py and import them across test files. For related objects, LazyAttribute computes values based on other fields. This makes tests more readable and maintainable than manual object creation. I can override any attribute when calling the factory.