DEV Community

Ranvir Singh
Ranvir Singh

Posted on • Originally published at ranvir.xyz

How to use FactoryBoy to create model instances in Django for testing

Original post: Using FactoryBoy to create model objects automatically for testing.

Testing is one of the basic and most important parts of the development process that is needed to be done every time you write or change any part of the code. It gives you the authority confidence in the code that you are writing.

I have already discussed testing in one of my earlier posts.

Writing unit tests for Django models

In this post, I will talk about the way in which we can write tests for models.

For testing models, we need to create sample objects. ๐Ÿ˜ฑ

It's pretty hard to write the same code again and again to create the same objects.

Today I am going to talk about using FactoryBoy for testing Django application.

The name FactoryBoy is inspired by the Factory Girl testing tool for Ruby on Rails. Without Factory boy, you will have to write a lot of code for the creation of test cases.

For writing tests, you have to spend a lot of time writing the setup method for the tests.

Without the use of factories, this is how your tests will look like:

from django.test import TestCase
from my_app.models import Person

class DataBaseStore(TestCase):
    def setUp(self):
        # Creating all the models   
        Person.objects.create(gender='male', age=20, name='ranvir')  

    def test_something(self):
        # test all the things that you want to.
        pass
Enter fullscreen mode Exit fullscreen mode

On the other hand, it is always nice to separate your setting up method from the testing method. For this sometimes we have to write a long code at the beginning which helps us in the future by allowing us to write smaller code.

We can write factories anywhere but it's always a good idea to write it in a separate file named factories.py inside the root directory of your app.

Write following in the factories.py file inside your root directory.

from factory.django import DjangoModelFactory  
from my_app.models import Person  

class PersonFactory(DjangoModelFactory):  
    class Meta:  
        model = Person  
    name = 'ranvir'  
    age = 20  
    gender = 'male'  
Enter fullscreen mode Exit fullscreen mode

Now we can simply call these factories during the test generation and create as many instances of models as we want to. This is a pretty simple case but we really can do a lot more. We can create instances of varies types by making use of FuzzyText and Sequence.

With the use of FuzzyText, you can generate random text making testing more awesome.

Applications of FactoryBoy

Getting random values

We can get random values for the purpose we specify to the Faker method. The values created are far more realistic than any other random methods that we use otherwise.

from factory import Faker

class PersonFactory(DjangoModelFactory):  
    class Meta:  
        model = Person
    name = Faker('name')
    age = 20
    gender = 'male'
Enter fullscreen mode Exit fullscreen mode

Here is a list of available providers by faker library which can be used.

Reproducing random values

Sometimes our tests fail for some random value and not for all of them. So, factory have introduced a concept using which we can create the same value again and again.

from factory.random import reseed_random

class PersonFactory(DjangoModelFactory):  
    class Meta:  
        model = Person
    name = reseed_random('Bill Clinton')
    age = 20
    gender = 'male'
Enter fullscreen mode Exit fullscreen mode

Using dependent values of other fields

There are some cases in which you want to use the values which are dependent on the random values of the other fields. For example, full name can be the combination of first and last name.

from factory import Faker, LazyAttribute

class PersonFactory(DjangoModelFactory):  
    class Meta:  
        model = Person
    first_name = Faker('first_name')
    second_name = Faker('last_name')
    full_name = factory.LazyAttribute(lambda a: '{0} {1}'.format(a.first_name, a.last_name))
Enter fullscreen mode Exit fullscreen mode

Using sequences for unique fields.

With random function, there is a chance that after some time the values will start repeating, and if your test suite has grown out of that threshold size you will have to use sequences in your unique fields.

from factory import Sequence

class PersonFactory(DjangoModelFactory):  
    class Meta:  
        model = Person
    email = Sequence(lambda n: 'person{0}@ranvir.xyz'.format(n))
Enter fullscreen mode Exit fullscreen mode

Foreign Keys

If your field is a foreign key, you can directly use that whole factory altogether.

from factory import Sequence

class PersonFactory(DjangoModelFactory):  
    class Meta:  
        model = Person
    email = Sequence(lambda n: 'person{0}@ranvir.xyz'.format(n))

class SocietyFactory(DjangoModelFactory):  
    class Meta:  
        model = Person
    society_number = Sequence(lambda n: 'Society {0}'.format(n))
    person = factory.SubFactory(PersonFactory)
Enter fullscreen mode Exit fullscreen mode

Testing is also considered as the sign of a good programmer. There are a ton of benefits of testing which were discussed in the post.

I hope you guys liked the idea of the post. We really can do a lot of stuff using this library. Do share your views regarding this post if you have used factories in the past or want to use it in your project. ๐Ÿ˜‡

Top comments (0)