Faker and Factory Boy
Testing Django App with faker and factory_boy
Faker: Generate fake data
Factory Boy: Create factories of our models
Factory Boy is an alternative to Django testing fixtures. When testing a Django application you often need to populate the test database with some sample data. The standard Django TestCase has support for fixture loading but there are a number of problems with using fixtures. Factory boy is a fixture replacement tool, it aims to replace static, hard to maintain fixtures with easy-to-use factories for complex objects.
factory_boy provides a class DjangoModelFactory
as a base class for Django unit test factories.
pip install factory_boy
# factories.py
import factory
class CompanyFactory(factory.DjangoModelFactory):
"""
| id | name |
|:----|:----------|
| 1 | X Company |
"""
class Meta:
model = 'core.Company'
django_get_or_create = ('name',)
name = factory.Faker('name')
created = factory.Faker('date', end_datetime=datetime.date.today())
The factory’s Meta has django_get_or_create set, which means the factory will call the Django built-in `Company.objects.get_or_create` method.
# Returns a User instance that's not saved
user = UserFactory.build()
# Returns a saved User instance.
# UserFactory must subclass an ORM base class, such as DjangoModelFactory.
user = UserFactory.create()
# Same as UserFactory.create()
user = UserFactory()
We can create more objects:
Create Batch
>>> companies = Company.create_batch(3, name=factory.Sequence(lambda n: 'Name {0}'.format(n)))
>>> len(companies)
3
>>> [company.name for company in companies]
["Name 1", "Name 2", "Name 3"]
Features of Factory Boy:
Sequence
Use a `Sequence` object using a lambda function to dynamically create unique field values.
name = factory.Sequence(lambda n: ‘company_%d’ % n)`
LazyAttribute
Use a `LazyAttribute` object to return a value for a defined field.
slug = factory.LazyAttribute(lambda o: o.name)
LazyFunction
Use a `LazyFunction` to call a function to compute the value.
timestamp = factory.LazyFunction(datetime.now)
SubFactories
Use a `SubFactories` for the one-to-many model relationship.
user = factory.SubFactory(UserFactory)
# factory.SubFactory(User) == models.ForeignKey(User)
Many-to-many relationship
We use post_generation
for model M2M relationship
class CompanyFactory(factory.DjangoModelFactory):
class Meta:
model = 'core.Company'
django_get_or_create = ('name',)
name = factory.Sequence(lambda n: 'Company %d' % n)
slug = factory.LazyAttribute(lambda o: o.name)
@factory.post_generation
def phones(self, create, extracted):
if not create:
return
if extracted:
for phone in extracted:
self.phones.add(phone)
Last updated
Was this helpful?