0
0
PytestHow-ToBeginner ยท 4 min read

How to Use Factory Boy with pytest for Easy Test Data Creation

Use factory_boy to define factories for your models and integrate them with pytest by creating fixtures that return factory classes. This allows you to generate test data easily inside your pytest tests with simple calls to the factory.
๐Ÿ“

Syntax

Define a factory class inheriting from factory.Factory or factory.django.DjangoModelFactory for Django models. Use pytest.fixture to create a fixture that returns factory classes. In tests, call the factory to create test data.

  • class MyFactory(factory.Factory): - defines a factory
  • @pytest.fixture - marks a pytest fixture
  • factory_instance = MyFactory() - creates test data
python
import factory
import pytest

class UserFactory(factory.Factory):
    class Meta:
        model = dict  # simple example using dict instead of a model

    id = factory.Sequence(lambda n: n)
    name = factory.Faker('name')

@pytest.fixture
def user_factory():
    return UserFactory

# In your test, you can use:
# def test_example(user_factory):
#     user = user_factory()
#     assert 'name' in user
๐Ÿ’ป

Example

This example shows how to define a simple factory for a user dictionary, create a pytest fixture for it, and use it in a test to generate user data dynamically.

python
import factory
import pytest

class UserFactory(factory.Factory):
    class Meta:
        model = dict

    id = factory.Sequence(lambda n: n + 1)
    name = factory.Faker('name')

@pytest.fixture
def user_factory():
    return UserFactory

def test_user_creation(user_factory):
    user1 = user_factory()
    user2 = user_factory()

    assert user1['id'] == 1
    assert user2['id'] == 2
    assert isinstance(user1['name'], str)
    assert isinstance(user2['name'], str)
Output
============================= test session starts ============================== collected 1 item test_factoryboy_pytest.py . [100%] ============================== 1 passed in 0.03s ===============================
โš ๏ธ

Common Pitfalls

Common mistakes include:

  • Not returning the factory class from the fixture, which prevents creating new instances in tests.
  • Using the factory class directly instead of calling it to create data.
  • Not resetting sequences or states when needed, causing unexpected data values.

Always call the factory to get fresh data and use fixtures to provide the factory cleanly.

python
import factory
import pytest

class UserFactory(factory.Factory):
    class Meta:
        model = dict

    id = factory.Sequence(lambda n: n + 1)
    name = factory.Faker('name')

@pytest.fixture
def user_factory():
    return UserFactory

# Wrong: Using factory class directly without calling
# def test_wrong(user_factory):
#     user = user_factory  # missing ()
#     assert 'name' in user  # fails because user is a class, not data

# Right:
# def test_right(user_factory):
#     user = user_factory()
#     assert 'name' in user
๐Ÿ“Š

Quick Reference

ConceptUsageNotes
Factory Classclass MyFactory(factory.Factory):Defines how to create test data
Fixture@pytest.fixture def my_factory(): return MyFactoryProvides factory to tests
Create Datainstance = my_factory()Call factory to get new data
Sequencefactory.Sequence(lambda n: n)Generates unique incremental values
Fakerfactory.Faker('name')Generates realistic fake data
โœ…

Key Takeaways

Define factories with Factory Boy to create reusable test data blueprints.
Use pytest fixtures to provide factory classes cleanly to your tests.
Always call the factory (e.g., factory()) to generate fresh test data instances.
Use sequences and Faker fields in factories for unique and realistic data.
Avoid returning factory instances directly without calling them in tests.