.agents/skills/factory-boy/SKILL.md
factory_boy test data generation specialist. Covers Factory, DjangoModelFactory, SQLAlchemyModelFactory, all field declarations (Faker, LazyAttribute, Sequence, SubFactory, RelatedFactory, post_generation, Trait, Maybe, Dict, List), batch creation, pytest integration, and Celery task testing patterns. USE WHEN: user mentions "factory_boy", "test factory", "DjangoModelFactory", "SQLAlchemyModelFactory", asks about "test data generation", "factory traits", "SubFactory", "factory fixtures". DO NOT USE FOR: pytest internals - use `pytest`; Django setup - use `pytest-django`; Hypothesis property testing - use `pytest` with Hypothesis
npx skillsauth add d-subrahmanyam/deno-fresh-microservices factory-boyInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Deep Knowledge: Use
mcp__documentation__fetch_docswith technology:factory-boyfor comprehensive documentation on all declarations, ORM integrations, and patterns.
pip install factory_boy faker
import factory
from myapp.models import User
class UserFactory(factory.Factory):
class Meta:
model = User
first_name = factory.Faker("first_name")
last_name = factory.Faker("last_name")
email = factory.LazyAttribute(
lambda o: f"{o.first_name}.{o.last_name}@example.com".lower()
)
username = factory.Sequence(lambda n: f"user{n}")
is_active = True
user = UserFactory() # creates (or builds, see Meta.strategy)
user = UserFactory.build() # in-memory, no DB
users = UserFactory.create_batch(5)
stub = UserFactory.stub() # StubObject, no model.__init__()
from factory.django import DjangoModelFactory
class UserFactory(DjangoModelFactory):
class Meta:
model = "auth.User" # 'app.Model' string OK
django_get_or_create = ("username",) # get-or-create on username
username = factory.Sequence(lambda n: f"user{n}")
email = factory.LazyAttribute(lambda o: f"{o.username}@example.com")
password = factory.django.Password("testpass123") # hashed via make_password
class Params:
staff = factory.Trait(is_staff=True)
admin = factory.Trait(is_staff=True, is_superuser=True)
from sqlalchemy.orm import scoped_session, sessionmaker
from factory.alchemy import SQLAlchemyModelFactory
Session = scoped_session(sessionmaker())
class UserFactory(SQLAlchemyModelFactory):
class Meta:
model = User
sqlalchemy_session = Session
sqlalchemy_session_persistence = "commit" # None | "flush" | "commit"
username = factory.Sequence(lambda n: f"user{n}")
email = factory.LazyAttribute(lambda o: f"{o.username}@example.com")
# In pytest: inject session
@pytest.fixture
def user(db_session):
UserFactory._meta.sqlalchemy_session = db_session
return UserFactory()
class ArticleFactory(factory.Factory):
class Meta:
model = Article
# Static value
status = "draft"
# Faker provider
title = factory.Faker("sentence", nb_words=6)
body = factory.Faker("paragraph")
uuid = factory.Faker("uuid4")
# Sequence (unique per factory call)
slug = factory.Sequence(lambda n: f"article-{n}")
# LazyAttribute (computed from other fields)
summary = factory.LazyAttribute(lambda o: o.body[:100])
# LazyFunction (zero-arg callable)
created_at = factory.LazyFunction(datetime.utcnow)
# SubFactory (FK)
author = factory.SubFactory(UserFactory)
# SelfAttribute (access parent or sibling fields)
author_email = factory.SelfAttribute("author.email")
# Iterator (cycles through values)
category = factory.Iterator(["tech", "culture", "science"])
# Dict field
metadata = factory.Dict({"source": "web", "version": factory.Sequence(lambda n: n)})
# Maybe (conditional)
published_at = factory.Maybe(
"is_published",
yes_declaration=factory.LazyFunction(datetime.utcnow),
no_declaration=None,
)
is_published = True
# Override sub-factory fields via __ separator
post = PostFactory(author__username="alice", author__email="[email protected]")
# Override nested sub-factory
company = CompanyFactory(owner__address__city="Rome")
class UserFactory(DjangoModelFactory):
class Meta:
model = User
profile = factory.RelatedFactory(
ProfileFactory,
factory_related_name="user", # Profile.user
bio="Default bio",
)
class ArticleFactory(DjangoModelFactory):
class Meta:
model = Article
skip_postgeneration_save = True
@factory.post_generation
def tags(self, create, extracted, **kwargs):
if not create or not extracted:
return
self.tags.set(extracted)
# Usage
article = ArticleFactory(tags=[tag1, tag2])
class OrderFactory(factory.Factory):
class Meta:
model = Order
status = "pending"
class Params:
shipped = factory.Trait(
status="shipped",
shipped_at=factory.LazyFunction(datetime.utcnow),
)
paid = factory.Trait(
status="paid",
paid_at=factory.LazyFunction(datetime.utcnow),
)
# Usage
pending = OrderFactory()
shipped = OrderFactory(shipped=True)
paid = OrderFactory(paid=True)
# conftest.py
import pytest
from myapp.tests.factories import UserFactory, ArticleFactory
@pytest.fixture
def user(db): # for Django
return UserFactory()
@pytest.fixture
def user(db_session): # for SQLAlchemy
UserFactory._meta.sqlalchemy_session = db_session
return UserFactory()
@pytest.fixture
def articles(db):
return ArticleFactory.create_batch(5)
@pytest.fixture(autouse=True)
def reset_sequences():
UserFactory.reset_sequence(0)
ArticleFactory.reset_sequence(0)
yield
| Anti-Pattern | Solution |
|---|---|
| UserFactory(email="[email protected]") in every test | Override in fixture or use Sequence |
| SubFactory without django_get_or_create | Can cause unique constraint violations |
| Not resetting sequences | Use autouse fixture to reset_sequence(0) |
| Creating M2M before object exists | Use post_generation / skip_postgeneration_save |
Official docs: https://factoryboy.readthedocs.io/
development
Guidelines for building high-performance APIs with Fastify and TypeScript, covering validation, Prisma integration, and testing best practices
development
FastAPI modern Python web framework. Covers routing, Pydantic models, dependency injection, and async support. Use when building Python APIs. USE WHEN: user mentions "fastapi", "pydantic", "async python api", "python rest api", asks about "dependency injection python", "python openapi", "python swagger", "async endpoints", "python api validation", "fastapi middleware" DO NOT USE FOR: Django apps - use `django` instead, Flask apps - use `flask` instead, synchronous Python APIs without type hints, GraphQL-only APIs
tools
FastAPI integration testing specialist. Covers synchronous TestClient, async httpx AsyncClient, dependency injection overrides, auth testing (JWT, OAuth2, API keys), WebSocket testing, file uploads, background tasks, middleware testing, and HTTP mocking with respx, responses, and pytest-httpserver. USE WHEN: user mentions "FastAPI test", "TestClient", "httpx async test", "dependency override test", "respx mock", asks about testing FastAPI endpoints, authentication in tests, or HTTP client mocking. DO NOT USE FOR: Django - use `pytest-django`; pytest internals - use `pytest`; Container infrastructure - use `testcontainers-python`
development
Expert in FastAPI Python development with best practices for APIs and async operations