Factory Boy — An alternative for Fixtures

Factory Boy is a fixtures replacement tool. It allows you to use objects customized for the current test, while only declaring the test-specific fields.

Setting up your factories:

For testing the Django app, create a root directory named tests. Then create __init__.py, tests.py (to write your tests), factories.py (to write your model factories) in that directory.

So, your app layout looks like:

myapp
|- __init__.py
|- admin.py
|- forms.py
|- models.py
|- tests
|- __init__.py
|- factories.py
|- tests.py
|- urls.py
|- views.py

Features of Factory Boy:

It allows you to automate much of the testing scenarios. Some examples are:

1. Use a ‘Sequence’ object using a lambda function to dynamically create unique field values:
EX: username = factory.Sequence(lambda n: ‘user_%d’ % n)

2. Use a LazyAttribute object to pick from a range of choices for a defined field
EX: choice = factory.LazyAttribute(lambda s: random.choice(dict(MyModel.CHOICES).keys()))

A basic factory: Factories declare a set of attributes used to instantiate an object. Here’s a basic factory that generates auth.User instances:

# factories.py
from factory import DjangoModelFactory, lazy_attribute
from django.contrib.auth.models import User
class UserFactory(DjangoModelFactory):
first_name = 'Shirisha'
last_name = 'Gaddi'
username = factory.Sequence(lambda n: 'user_%d' % n)
email = lazy_attribute(lambda obj: obj.username + "@example.com")
class Meta:
model = 'User'
django_get_or_create = ('username',)

Calling this as factories.UserFactory() will perform same task as User.objects.create call. Howerver, it is possible to override the defined attributes by passing keyword arguments:

# Create a user instance by overriding first_name
user = factories.UserFactory(first_name="Karuna")

The factory’s Meta has django_get_or_create set, which means the factory will call the Django built-in User.objects.get_or_create method.

The article was originally published at MicroPyramid blog