How to use FactoryBoy to create model instances in Django for testing
January 18, 2018 ·
6 mins read
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 the Django models and why is it important?
#GSoC-2017
#testing
#django
#python
July 5, 2017
4 mins read
1. Creating model objects without FactoryBoy
2. Creating model objects with FactoryBoy
3. Applications of FactoryBoy
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.
2. Creating model objects with FactoryBoy
3. Applications of FactoryBoy
Creating model objects without FactoryBoy
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
method
from the testing method. For this sometimes we have to write long code in 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.
Creating model objects with FactoryBoy
from factory.django import DjangoModelFactory
from my_app.models import Person
class PersonFactory(DjangoModelFactory):
class Meta:
model = Person
name = 'ranvir'
age = 20
gender = 'male'
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 theFaker
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'
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'
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))
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))
Foreign Keys
If your field is a foreign key, you can directly use that whole factory all together.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)
Please share your Feedback:
Did you enjoy reading or think it can be improved? Don’t forget to leave your thoughts in the comments section below! If you liked this article, please share it with your friends, and read a few more!