Skip to main content

factory_boy integration with the pytest runner

https://img.shields.io/pypi/v/pytest-factoryboy.svg https://img.shields.io/pypi/pyversions/pytest-factoryboy.svg https://github.com/pytest-dev/pytest-factoryboy/actions/workflows/main.yml/badge.svg Documentation Status

pytest-factoryboy makes it easy to combine factory approach to the test setup with the dependency injection, heart of the pytest fixtures.

Install pytest-factoryboy

pip install pytest-factoryboy

Concept

Library exports a function to register factories as fixtures. Fixtures are contributed to the same module where register function is called.

Model Fixture

Model fixture implements an instance of a model created by the factory. Name convention is model’s lowercase-underscore class name.

import factory
from pytest_factoryboy import register

@register
class AuthorFactory(factory.Factory):
    class Meta:
        model = Author

    name = "Charles Dickens"


def test_model_fixture(author):
    assert author.name == "Charles Dickens"

Attributes are Fixtures

There are fixtures created automatically for factory attributes. Attribute names are prefixed with the model fixture name and double underscore (similar to the convention used by factory_boy).

@pytest.mark.parametrize("author__name", ["Bill Gates"])
def test_model_fixture(author):
    assert author.name == "Bill Gates"

Multiple fixtures

Model fixtures can be registered with specific names. For example, if you address instances of some collection by the name like “first”, “second” or of another parent as “other”:

register(AuthorFactory)  # author
register(AuthorFactory, "second_author")  # second_author


@register  # book
@register(_name="second_book")  # second_book
@register(_name="other_book")  # other_book, book of another author
class BookFactory(factory.Factory):
    class Meta:
        model = Book


@pytest.fixture
def other_book__author(second_author):
    """Make the relation of the `other_book.author` to `second_author`."""
    return second_author


def test_book_authors(book, second_book, other_book, author, second_author):
    assert book.author == second_book.author == author
    assert other_book.author == second_author

SubFactory

Sub-factory attribute points to the model fixture of the sub-factory. Attributes of sub-factories are injected as dependencies to the model fixture and can be overridden via the parametrization.

post-generation

Post-generation attribute fixture implements only the extracted value for the post generation function.

Factory Fixture

pytest-factoryboy also registers factory fixtures, to allow their use without importing them. The fixture name convention is to use the lowercase-underscore form of the class name.

import factory
from pytest_factoryboy import register

class AuthorFactory(factory.Factory):
    class Meta:
        model = Author


register(AuthorFactory)  # => author_factory


def test_factory_fixture(author_factory):
    author = author_factory(name="Charles Dickens")
    assert author.name == "Charles Dickens"

Integration

An example of factory_boy and pytest integration.

# tests/factories.py

import factory
from app import models
from faker import Factory as FakerFactory

faker = FakerFactory.create()


class AuthorFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = models.Author

    name = factory.LazyFunction(lambda: faker.name())


class BookFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = models.Book

    title = factory.LazyFunction(lambda: faker.sentence(nb_words=4))
    author = factory.SubFactory(AuthorFactory)
# tests/conftest.py

from pytest_factoryboy import register

from . import factories

register(factories.AuthorFactory)
register(factories.BookFactory)
# tests/test_models.py

from app.models import Book
from .factories import BookFactory


def test_book_factory(book_factory):
    """Factories become fixtures automatically."""
    assert book_factory is BookFactory


def test_book(book):
    """Instances become fixtures automatically."""
    assert isinstance(book, Book)


@pytest.mark.parametrize("book__title", ["PyTest for Dummies"])
@pytest.mark.parametrize("author__name", ["Bill Gates"])
def test_parametrized(book):
    """You can set any factory attribute as a fixture using naming convention."""
    assert book.title == "PyTest for Dummies"
    assert book.author.name == "Bill Gates"

Fixture partial specialization

There is a possibility to pass keyword parameters in order to override factory attribute values during fixture registration. This comes in handy when your test case is requesting a lot of fixture flavors. Too much for the regular pytest parametrization. In this case, you can register fixture flavors in the local test module and specify value deviations inside register function calls.

register(AuthorFactory, "male_author", gender="M", name="John Doe")
register(AuthorFactory, "female_author", gender="F")


@pytest.fixture
def female_author__name():
    """Override female author name as a separate fixture."""
    return "Jane Doe"


@pytest.mark.parametrize("male_author__age", [42])  # Override even more
def test_partial(male_author, female_author):
    """Test fixture partial specialization."""
    assert male_author.gender == "M"
    assert male_author.name == "John Doe"
    assert male_author.age == 42

    assert female_author.gender == "F"
    assert female_author.name == "Jane Doe"

Fixture attributes

Sometimes it is necessary to pass an instance of another fixture as an attribute value to the factory. It is possible to override the generated attribute fixture where desired values can be requested as fixture dependencies. There is also a lazy wrapper for the fixture that can be used in the parametrization without defining fixtures in a module.

LazyFixture constructor accepts either existing fixture name or callable with dependencies:

import pytest
from pytest_factoryboy import register, LazyFixture


@pytest.mark.parametrize("book__author", [LazyFixture("another_author")])
def test_lazy_fixture_name(book, another_author):
    """Test that book author is replaced with another author by fixture name."""
    assert book.author == another_author


@pytest.mark.parametrize("book__author", [LazyFixture(lambda another_author: another_author)])
def test_lazy_fixture_callable(book, another_author):
    """Test that book author is replaced with another author by callable."""
    assert book.author == another_author


# Can also be used in the partial specialization during the registration.
register(BookFactory, "another_book", author=LazyFixture("another_author"))

Generic container classes as models

It’s often useful to create factories for dict or other common generic container classes. In that case, you should wrap the container class around named_model(...), so that pytest-factoryboy can correctly determine the model name when using it in a SubFactory or RelatedFactory.

Pytest-factoryboy will otherwise raise a warning.

For example:

import factory
from pytest_factoryboy import named_model, register

@register
class JSONPayload(factory.Factory):
    class Meta:
        model = named_model("JSONPayload", dict)

    name = "foo"


def test_foo(json_payload):
    assert json_payload.name == "foo"

As a bonus, factory is automatically registering the json_payload fixture (rather than dict), so there is no need to override @register(_name="json_payload")).

Post-generation dependencies

Unlike factory_boy which binds related objects using an internal container to store results of lazy evaluations, pytest-factoryboy relies on the PyTest request.

Circular dependencies between objects can be resolved using post-generation hooks/related factories in combination with passing the SelfAttribute, but in the case of PyTest request fixture functions have to return values in order to be cached in the request and to become available to other fixtures.

That’s why evaluation of the post-generation declaration in pytest-factoryboy is deferred until calling the test function. This solves circular dependency resolution for situations like:

o->[ A ]-->[ B ]<--[ C ]-o
|                        |
o----(C depends on A)----o

On the other hand, deferring the evaluation of post-generation declarations evaluation makes their result unavailable during the generation of objects that are not in the circular dependency, but they rely on the post-generation action.

pytest-factoryboy is trying to detect cycles and resolve post-generation dependencies automatically.

from pytest_factoryboy import register


class Foo(object):
    def __init__(self, value):
        self.value = value


class Bar(object):
    def __init__(self, foo):
        self.foo = foo


@register
class FooFactory(factory.Factory):
    class Meta:
        model = Foo

    value = 0

    @factory.post_generation
    def set1(foo, create, value, **kwargs):
        foo.value = 1

@register
class BarFactory(factory.Factory):
    class Meta:
        model = Bar

    foo = factory.SubFactory(FooFactory)

    @classmethod
    def _create(cls, model_class, foo):
        assert foo.value == 1  # Assert that set1 is evaluated before object generation
        return super(BarFactory, cls)._create(model_class, foo=foo)


# Forces 'set1' to be evaluated first.
def test_depends_on_set1(bar):
    """Test that post-generation hooks are done and the value is 2."""
    assert bar.foo.value == 1

Hooks

pytest-factoryboy exposes several pytest hooks which might be helpful for e.g. controlling database transaction, for reporting etc:

  • pytest_factoryboy_done(request) - Called after all factory-based fixtures and their post-generation actions have been evaluated.

License

This software is licensed under the MIT license.

© 2015 Oleg Pidsadnyi, Anatoly Bubenkov and others

Release files for pytest-factoryboy 2.8.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pytest-factoryboy 2.8.1
File Size Uploaded
pytest_factoryboy-2.8.1.tar.gz 16.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pytest-factoryboy 2.8.1
File Interpreter ABI Platform
pytest_factoryboy-2.8.1-py3-none-any.whl Python 3 none any Details

Total release size: 33.3 kB

Release files / pytest_factoryboy-2.8.1.tar.gz

Download URL pytest_factoryboy-2.8.1.tar.gz
Size 16.9 kB
Tags Source
SHA-256 checksum
How to use checksums
2221d48b31b8b8ccaa739c6a162fb50a43a4de6dff6043f249d2807a3462548d
BLAKE2b-256 checksum
How to use checksums
918aa0f9c58bf176b0d39b630a6e29cccebec9a429dfeb62204bbb9b632fb798
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.12.9

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 1, 2025.

Transparency log

Release files / pytest_factoryboy-2.8.1-py3-none-any.whl

Download URL pytest_factoryboy-2.8.1-py3-none-any.whl
Size 16.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
91c762cb236bf34b11efdf2e54bafae33114488235621e8b2c4bd9fd77838784
BLAKE2b-256 checksum
How to use checksums
062f4f73a79196b4acb0f902520a805caa22f8ba0adbecdfb028a371404c2537
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.12.9

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 1, 2025.

Transparency log

Release history Release notifications | RSS feed

This release

2.8.1 This release

2 release files

2.8.0

2 release files

2.7.0

2 release files

2.6.1

2 release files

2.6.0

2 release files

2.5.1

2 release files

2.5.0

2 release files

2.4.0

2 release files

2.3.1

2 release files

2.3.0

2 release files

2.2.1

2 release files

2.2.0

2 release files

2.1.0

2 release files

2.0.3

1 release file

2.0.2

1 release file

2.0.1

1 release file

1.3.2

1 release file

1.3.1

1 release file

1.3.0

1 release file

1.2.2

1 release file

1.2.1

1 release file

1.1.6

1 release file

1.1.5

1 release file

1.1.4

1 release file

1.1.3

1 release file

1.1.2

1 release file

1.1.1

1 release file

1.1.0

1 release file

1.0.3

1 release file

1.0.2

1 release file

1.0.1

1 release file

1.0.0

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page