factory-boy

raw JSON →
3.3.3 verified Tue May 12 auth: no python install: verified

factory-boy is a versatile test fixtures replacement for Python, based on thoughtbot's factory_bot for Ruby. It helps generate fake data efficiently and declaratively for various ORMs like Django, SQLAlchemy, and MongoEngine, supporting multiple build strategies and factory inheritance.

pip install factory-boy
error ModuleNotFoundError: No module named 'factory.django'
cause This error typically occurs when attempting to import `DjangoModelFactory` from the `factory.django` module in older `factory-boy` versions (prior to 3.0) or when `factory-boy` is not installed or the virtual environment is not active. Before version 3.0, `DjangoModelFactory` was directly available under the `factory` namespace.
fix
For factory-boy versions 3.0 and above, ensure you are importing DjangoModelFactory from factory.django. If using an older version (pre-3.0), import it directly from factory. Also, confirm that factory-boy is installed (pip install factory-boy) and your virtual environment is activated.
error FactoryError: No model set on <FactoryName>Factory
cause This error occurs when a `factory.Factory` subclass, especially `DjangoModelFactory`, does not have its `Meta.model` attribute correctly defined, meaning the factory doesn't know which model it should generate instances for.
fix
Inside your factory class, define a Meta inner class and set its model attribute to the actual Python class of the model you intend to create instances of (e.g., model = myapp.models.MyModel), not a string or an instance.
error AttributeError: 'str' object has no attribute 'pk'
cause This `AttributeError` often arises in Django contexts when a `DjangoModelFactory`'s `Meta.model` is incorrectly set to a string literal (e.g., `'myapp.MyModel'`) and an older `factory-boy` version or an improper interaction attempts to access model attributes like `pk` or `objects` directly on this string. While `DjangoModelFactory` *does* support string references for `model`, this specific error points to a situation where the string is not correctly resolved to a model class during an operation that expects an actual model object, or when `factory.Factory` is used instead of `factory.django.DjangoModelFactory`.
fix
Ensure you are inheriting from factory.django.DjangoModelFactory for Django models. If the error persists, pass the actual model class to Meta.model (e.g., model = myapp.models.MyModel) instead of a string path.
error django.db.utils.IntegrityError: duplicate key value violates unique constraint
cause This database error typically occurs in Django tests when `factory-boy` creates model instances with values that violate unique constraints defined in your database schema, often due to not using `factory.Sequence` for unique fields or misconfiguring `django_get_or_create`.
fix
For any model fields that require unique values, use factory.Sequence(lambda n: f'unique_value_{n}') to generate distinct values for each instance. If you intend to retrieve existing objects instead of creating duplicates, properly configure Meta.django_get_or_create = ('unique_field_name',) with the fields that uniquely identify an object.
breaking Major breaking changes occurred in the transition from factory-boy 2.x to 3.x, including dropping support for Python 2, Python 3.4, Django 2.0, and Django 2.1.
fix Upgrade to Python 3.8+ and supported Django versions. Review the official changelog for specific removals and re-implementations.
breaking For plain `factory.Factory` subclasses, `create()` no longer calls `objects.create()` for ORM models. For Django or SQLAlchemy models, you must now use `DjangoModelFactory` or `SQLAlchemyModelFactory` respectively to ensure persistence to the database when calling `create()`.
fix Migrate your ORM-backed factories to inherit from `factory.django.DjangoModelFactory` or `factory.alchemy.SQLAlchemyModelFactory`.
deprecated Old class-level attributes like `FACTORY_FOR`, `ABSTRACT_FACTORY`, `FACTORY_STRATEGY` are deprecated. They should now be defined within a nested `Meta` class using `model`, `abstract`, and `strategy` respectively.
fix Refactor factory definitions to use the `Meta` class pattern (e.g., `class Meta: model = MyModel`).
deprecated The default behavior of `_after_postgeneration` for `DjangoModelFactory` changed. It will no longer automatically save the instance after post-generation hooks in future releases. This often results in `DeprecationWarning` if not handled.
fix If your `post_generation` hooks modify the instance, set `skip_postgeneration_save = True` in `Meta` and explicitly call `instance.save()` within your post-generation hook, typically guarding it with `if create:`.
gotcha Defining mutable fields (e.g., lists, dictionaries) directly at the factory class level can lead to all generated instances sharing the same mutable object. Changes in one instance will propagate to others.
fix Use `factory.List()`, `factory.Dict()`, or `factory.LazyAttribute` to ensure each instance receives a unique mutable object. Example: `my_list = factory.List([1, 2, 3])` or `my_dict = factory.LazyAttribute(lambda o: {})`.
gotcha Overriding attributes directly at the class level (e.g., `MyFactory.name = 'Fixed'`) is an anti-pattern and can lead to unpredictable behavior, especially in parallel test runs, as it modifies the default for all future objects.
fix Always specify attribute overrides using keyword arguments in your factory call (e.g., `MyFactory(name='Custom Name')`).
python os / libc status wheel install import disk mem side effects
3.10 alpine (musl) wheel - 0.32s 42.5M 10.2M clean
3.10 alpine (musl) - - 0.41s 42.3M 10.2M -
3.10 slim (glibc) wheel 2.7s 0.23s 43M 10.2M clean
3.10 slim (glibc) - - 0.23s 43M 10.2M -
3.11 alpine (musl) wheel - 0.39s 43.7M 10.8M clean
3.11 alpine (musl) - - 0.53s 43.6M 10.8M -
3.11 slim (glibc) wheel 2.9s 0.37s 44M 10.8M clean
3.11 slim (glibc) - - 0.35s 44M 10.8M -
3.12 alpine (musl) wheel - 0.34s 35.5M 10.4M clean
3.12 alpine (musl) - - 0.43s 35.3M 10.4M -
3.12 slim (glibc) wheel 2.8s 0.38s 36M 10.4M clean
3.12 slim (glibc) - - 0.37s 36M 10.4M -
3.13 alpine (musl) wheel - 0.32s 35.2M 10.5M clean
3.13 alpine (musl) - - 0.55s 34.9M 10.5M -
3.13 slim (glibc) wheel 2.7s 0.34s 36M 10.5M clean
3.13 slim (glibc) - - 0.35s 35M 10.5M -
3.9 alpine (musl) wheel - 0.28s 43.1M 10.0M clean
3.9 alpine (musl) - - 0.36s 43.1M 10.0M -
3.9 slim (glibc) wheel 3.5s 0.28s 44M 10.0M clean
3.9 slim (glibc) - - 0.29s 44M 10.0M -

Define a simple Python class and then create a `factory.Factory` subclass for it. Use `factory.Faker` for realistic data and `factory.LazyAttribute` for interdependent fields. Instances can be created by calling the factory, with keyword arguments overriding default attributes.

import factory

class User:
    def __init__(self, first_name, last_name, email, is_admin=False):
        self.first_name = first_name
        self.last_name = last_name
        self.email = email
        self.is_admin = is_admin

    def __str__(self):
        return f'{self.first_name} {self.last_name} ({self.email})'

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())
    is_admin = False

# Create a basic user
user = UserFactory()
print(f"Created user: {user}")

# Create an admin user
admin_user = UserFactory(is_admin=True)
print(f"Created admin user: {admin_user}")

# Create a user with specific name
specific_user = UserFactory(first_name='John', last_name='Doe')
print(f"Created specific user: {specific_user}")