Factory Boy - An Alternative for Fixtures2022-07-19
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. 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.
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.