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 fixturefactory_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
| Concept | Usage | Notes |
|---|---|---|
| Factory Class | class MyFactory(factory.Factory): | Defines how to create test data |
| Fixture | @pytest.fixture def my_factory(): return MyFactory | Provides factory to tests |
| Create Data | instance = my_factory() | Call factory to get new data |
| Sequence | factory.Sequence(lambda n: n) | Generates unique incremental values |
| Faker | factory.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.