docs
  • Overview
  • 🐍 PYTHON
    • Type Hints
    • PEP8 Style Guide for Python Code
    • 🏡Pipenv
    • Pathlib
  • 🕸Django
    • 🗄models
      • 🎯Best Practices
      • 🚦Django Signals
    • ⚙️ settings
    • DRF
      • Serializer
      • Authentication
      • Permissions
      • Viewsets
    • Testing
      • Faker and Factory Boy
    • 🧪Test Coverage
    • 💦Python-Decouple
    • Django Tips:
    • 💾Django ORM Queryset
    • Custom Exceptions
    • Celery
    • Resources
  • Deploy
    • 🚀Django Deployment
    • 🔒Setup SSL Certificate
  • 💾Database
    • MongoDB
  • 🛠️DevOps
    • 🖥Scripting
      • A First Script
      • Loops
      • Test
      • Variables
      • External programs
      • Functions
    • Command Line Shortcuts
    • Basic Linux Commands
    • 🎛Microservices
    • 🐳Docker
      • Docker Commands
      • Docker Compose
      • Django project
    • Kubernates
  • 📝Software IDE
    • EditorConfig
    • Linters
    • VsCode
Powered by GitBook
On this page
  • Faker: Generate fake data
  • Factory Boy: Create factories of our models
  • Create Batch

Was this helpful?

  1. 🕸Django
  2. Testing

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)
PreviousTestingNextTest Coverage

Last updated 3 years ago

Was this helpful?