{"id":28545565,"url":"https://github.com/pytest-dev/pytest-factoryboy","last_synced_at":"2025-07-07T05:31:40.202Z","repository":{"id":29934235,"uuid":"33480443","full_name":"pytest-dev/pytest-factoryboy","owner":"pytest-dev","description":"factory_boy integration the pytest runner","archived":false,"fork":false,"pushed_at":"2025-07-01T03:58:13.000Z","size":618,"stargazers_count":385,"open_issues_count":35,"forks_count":42,"subscribers_count":26,"default_branch":"master","last_synced_at":"2025-07-06T00:06:46.137Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"facebook/bistro","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pytest-dev.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGES.rst","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS.rst","dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-04-06T12:16:05.000Z","updated_at":"2025-07-01T03:57:27.000Z","dependencies_parsed_at":"2023-02-19T12:01:08.059Z","dependency_job_id":"9c975a60-4e75-43ac-8a88-e2abd4a9b486","html_url":"https://github.com/pytest-dev/pytest-factoryboy","commit_stats":{"total_commits":360,"total_committers":24,"mean_commits":15.0,"dds":0.3555555555555555,"last_synced_commit":"9790d91170442db10b8e9bb326668c8c56a61d69"},"previous_names":[],"tags_count":30,"template":false,"template_full_name":null,"purl":"pkg:github/pytest-dev/pytest-factoryboy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pytest-dev%2Fpytest-factoryboy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pytest-dev%2Fpytest-factoryboy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pytest-dev%2Fpytest-factoryboy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pytest-dev%2Fpytest-factoryboy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pytest-dev","download_url":"https://codeload.github.com/pytest-dev/pytest-factoryboy/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pytest-dev%2Fpytest-factoryboy/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263832541,"owners_count":23517355,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-09T23:08:06.249Z","updated_at":"2025-07-07T05:31:40.197Z","avatar_url":"https://github.com/pytest-dev.png","language":"Python","readme":"factory_boy_ integration with the pytest_ runner\n================================================\n\n.. image:: https://img.shields.io/pypi/v/pytest-factoryboy.svg\n   :target: https://pypi.python.org/pypi/pytest-factoryboy\n.. image:: https://img.shields.io/pypi/pyversions/pytest-factoryboy.svg\n  :target: https://pypi.python.org/pypi/pytest-factoryboy\n.. image:: https://github.com/pytest-dev/pytest-factoryboy/actions/workflows/main.yml/badge.svg\n    :target: https://github.com/pytest-dev/pytest-factoryboy/actions?query=workflow%3Amain\n.. image:: https://readthedocs.org/projects/pytest-factoryboy/badge/?version=latest\n    :target: https://readthedocs.org/projects/pytest-factoryboy/?badge=latest\n    :alt: Documentation Status\n\n\npytest-factoryboy makes it easy to combine ``factory`` approach to the test setup with the ``dependency`` injection,\nheart of the `pytest fixtures`_.\n\n.. _factory_boy: https://factoryboy.readthedocs.io\n.. _pytest: https://pytest.org\n.. _pytest fixtures: https://pytest.org/latest/fixture.html\n.. _overridden: https://docs.pytest.org/en/latest/how-to/fixtures.html#overriding-fixtures-on-various-levels\n\n\nInstall pytest-factoryboy\n-------------------------\n\n::\n\n    pip install pytest-factoryboy\n\n\nConcept\n-------\n\nLibrary exports a function to register factories as fixtures. Fixtures are contributed\nto the same module where register function is called.\n\n\nModel Fixture\n-------------\n\nModel fixture implements an instance of a model created by the factory. Name convention is model's lowercase-underscore\nclass name.\n\n\n.. code-block:: python\n\n    import factory\n    from pytest_factoryboy import register\n\n    @register\n    class AuthorFactory(factory.Factory):\n        class Meta:\n            model = Author\n\n        name = \"Charles Dickens\"\n\n\n    def test_model_fixture(author):\n        assert author.name == \"Charles Dickens\"\n\n\nAttributes are Fixtures\n-----------------------\n\nThere are fixtures created automatically for factory attributes. Attribute names are prefixed with the model fixture name and\ndouble underscore (similar to the convention used by factory_boy).\n\n\n.. code-block:: python\n\n    @pytest.mark.parametrize(\"author__name\", [\"Bill Gates\"])\n    def test_model_fixture(author):\n        assert author.name == \"Bill Gates\"\n\n\nMultiple fixtures\n-----------------\n\nModel fixtures can be registered with specific names. For example, if you address instances of some collection\nby the name like \"first\", \"second\" or of another parent as \"other\":\n\n\n.. code-block:: python\n\n    register(AuthorFactory)  # author\n    register(AuthorFactory, \"second_author\")  # second_author\n\n\n    @register  # book\n    @register(_name=\"second_book\")  # second_book\n    @register(_name=\"other_book\")  # other_book, book of another author\n    class BookFactory(factory.Factory):\n        class Meta:\n            model = Book\n\n\n    @pytest.fixture\n    def other_book__author(second_author):\n        \"\"\"Make the relation of the `other_book.author` to `second_author`.\"\"\"\n        return second_author\n\n\n    def test_book_authors(book, second_book, other_book, author, second_author):\n        assert book.author == second_book.author == author\n        assert other_book.author == second_author\n\n\nSubFactory\n----------\n\nSub-factory attribute points to the model fixture of the sub-factory.\nAttributes of sub-factories are injected as dependencies to the model fixture and can be overridden_ via\nthe parametrization.\n\nRelated Factory\n---------------\n\nRelated factory attribute points to the model fixture of the related factory.\nAttributes of related factories are injected as dependencies to the model fixture and can be overridden_ via\nthe parametrization.\n\n\npost-generation\n---------------\n\nPost-generation attribute fixture implements only the extracted value for the post generation function.\n\nFactory Fixture\n---------------\n\n`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.\n\n.. code-block:: python\n\n    import factory\n    from pytest_factoryboy import register\n\n    class AuthorFactory(factory.Factory):\n        class Meta:\n            model = Author\n\n\n    register(AuthorFactory)  # =\u003e author_factory\n\n\n    def test_factory_fixture(author_factory):\n        author = author_factory(name=\"Charles Dickens\")\n        assert author.name == \"Charles Dickens\"\n\n\nIntegration\n-----------\n\nAn example of factory_boy_ and pytest_ integration.\n\n.. code-block:: python\n\n    # tests/factories.py\n\n    import factory\n    from app import models\n    from faker import Factory as FakerFactory\n\n    faker = FakerFactory.create()\n\n\n    class AuthorFactory(factory.django.DjangoModelFactory):\n        class Meta:\n            model = models.Author\n\n        name = factory.LazyFunction(lambda: faker.name())\n\n\n    class BookFactory(factory.django.DjangoModelFactory):\n        class Meta:\n            model = models.Book\n\n        title = factory.LazyFunction(lambda: faker.sentence(nb_words=4))\n        author = factory.SubFactory(AuthorFactory)\n\n\n.. code-block:: python\n\n    # tests/conftest.py\n\n    from pytest_factoryboy import register\n\n    from . import factories\n\n    register(factories.AuthorFactory)\n    register(factories.BookFactory)\n\n\n.. code-block:: python\n\n    # tests/test_models.py\n\n    from app.models import Book\n    from .factories import BookFactory\n\n\n    def test_book_factory(book_factory):\n        \"\"\"Factories become fixtures automatically.\"\"\"\n        assert book_factory is BookFactory\n\n\n    def test_book(book):\n        \"\"\"Instances become fixtures automatically.\"\"\"\n        assert isinstance(book, Book)\n\n\n    @pytest.mark.parametrize(\"book__title\", [\"PyTest for Dummies\"])\n    @pytest.mark.parametrize(\"author__name\", [\"Bill Gates\"])\n    def test_parametrized(book):\n        \"\"\"You can set any factory attribute as a fixture using naming convention.\"\"\"\n        assert book.title == \"PyTest for Dummies\"\n        assert book.author.name == \"Bill Gates\"\n\n\nFixture partial specialization\n------------------------------\n\nThere is a possibility to pass keyword parameters in order to override factory attribute values during fixture\nregistration. This comes in handy when your test case is requesting a lot of fixture flavors. Too much for the\nregular pytest parametrization.\nIn this case, you can register fixture flavors in the local test module and specify value deviations inside ``register``\nfunction calls.\n\n\n.. code-block:: python\n\n    register(AuthorFactory, \"male_author\", gender=\"M\", name=\"John Doe\")\n    register(AuthorFactory, \"female_author\", gender=\"F\")\n\n\n    @pytest.fixture\n    def female_author__name():\n        \"\"\"Override female author name as a separate fixture.\"\"\"\n        return \"Jane Doe\"\n\n\n    @pytest.mark.parametrize(\"male_author__age\", [42])  # Override even more\n    def test_partial(male_author, female_author):\n        \"\"\"Test fixture partial specialization.\"\"\"\n        assert male_author.gender == \"M\"\n        assert male_author.name == \"John Doe\"\n        assert male_author.age == 42\n\n        assert female_author.gender == \"F\"\n        assert female_author.name == \"Jane Doe\"\n\n\nFixture attributes\n------------------\n\nSometimes it is necessary to pass an instance of another fixture as an attribute value to the factory.\nIt is possible to override the generated attribute fixture where desired values can be requested as\nfixture dependencies. There is also a lazy wrapper for the fixture that can be used in the parametrization\nwithout defining fixtures in a module.\n\n\nLazyFixture constructor accepts either existing fixture name or callable with dependencies:\n\n.. code-block:: python\n\n    import pytest\n    from pytest_factoryboy import register, LazyFixture\n\n\n    @pytest.mark.parametrize(\"book__author\", [LazyFixture(\"another_author\")])\n    def test_lazy_fixture_name(book, another_author):\n        \"\"\"Test that book author is replaced with another author by fixture name.\"\"\"\n        assert book.author == another_author\n\n\n    @pytest.mark.parametrize(\"book__author\", [LazyFixture(lambda another_author: another_author)])\n    def test_lazy_fixture_callable(book, another_author):\n        \"\"\"Test that book author is replaced with another author by callable.\"\"\"\n        assert book.author == another_author\n\n\n    # Can also be used in the partial specialization during the registration.\n    register(BookFactory, \"another_book\", author=LazyFixture(\"another_author\"))\n\n\nGeneric container classes as models\n-----------------------------------\nIt's often useful to create factories for ``dict`` or other common generic container classes.\nIn 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.\n\nPytest-factoryboy will otherwise raise a warning.\n\nFor example:\n\n.. code-block:: python\n\n    import factory\n    from pytest_factoryboy import named_model, register\n\n    @register\n    class JSONPayload(factory.Factory):\n        class Meta:\n            model = named_model(\"JSONPayload\", dict)\n\n        name = \"foo\"\n\n\n    def test_foo(json_payload):\n        assert json_payload.name == \"foo\"\n\nAs a bonus, factory is automatically registering the ``json_payload`` fixture (rather than ``dict``), so there is no need to override ``@register(_name=\"json_payload\"))``.\n\nPost-generation dependencies\n============================\n\nUnlike factory_boy which binds related objects using an internal container to store results of lazy evaluations,\npytest-factoryboy relies on the PyTest request.\n\nCircular dependencies between objects can be resolved using post-generation hooks/related factories in combination with\npassing the SelfAttribute, but in the case of PyTest request fixture functions have to return values in order to be cached\nin the request and to become available to other fixtures.\n\nThat's why evaluation of the post-generation declaration in pytest-factoryboy is deferred until calling\nthe test function.\nThis solves circular dependency resolution for situations like:\n\n::\n\n    o-\u003e[ A ]--\u003e[ B ]\u003c--[ C ]-o\n    |                        |\n    o----(C depends on A)----o\n\n\nOn the other hand, deferring the evaluation of post-generation declarations evaluation makes their result unavailable during the generation\nof objects that are not in the circular dependency, but they rely on the post-generation action.\n\npytest-factoryboy is trying to detect cycles and resolve post-generation dependencies automatically.\n\n\n.. code-block:: python\n\n    from pytest_factoryboy import register\n\n\n    class Foo(object):\n        def __init__(self, value):\n            self.value = value\n\n\n    class Bar(object):\n        def __init__(self, foo):\n            self.foo = foo\n\n\n    @register\n    class FooFactory(factory.Factory):\n        class Meta:\n            model = Foo\n\n        value = 0\n\n        @factory.post_generation\n        def set1(foo, create, value, **kwargs):\n            foo.value = 1\n\n    @register\n    class BarFactory(factory.Factory):\n        class Meta:\n            model = Bar\n\n        foo = factory.SubFactory(FooFactory)\n\n        @classmethod\n        def _create(cls, model_class, foo):\n            assert foo.value == 1  # Assert that set1 is evaluated before object generation\n            return super(BarFactory, cls)._create(model_class, foo=foo)\n\n\n    # Forces 'set1' to be evaluated first.\n    def test_depends_on_set1(bar):\n        \"\"\"Test that post-generation hooks are done and the value is 2.\"\"\"\n        assert bar.foo.value == 1\n\n\nHooks\n-----\n\npytest-factoryboy exposes several `pytest hooks \u003chttp://pytest.org/latest/plugins.html#well-specified-hooks\u003e`_\nwhich might be helpful for e.g. controlling database transaction, for reporting etc:\n\n* pytest_factoryboy_done(request) - Called after all factory-based fixtures and their post-generation actions have been evaluated.\n\n\nLicense\n-------\n\nThis software is licensed under the `MIT license \u003chttp://en.wikipedia.org/wiki/MIT_License\u003e`_.\n\n© 2015 Oleg Pidsadnyi, Anatoly Bubenkov and others\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpytest-dev%2Fpytest-factoryboy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpytest-dev%2Fpytest-factoryboy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpytest-dev%2Fpytest-factoryboy/lists"}