JSON Web Tokens in django application - part I

Posted by Kyle Ding on August 20, 2017

During my work with the team, i learned a lot from them. Especially with CTO and my friends there. They taught me by giving a test code that is so beautiful. With Django Factory Boy I can create a shadow object during the testing phase without needing to create objects from the queryset that make it so simple.


This note gives me feedback in the future. I keep using this note for my reference in the code testing phase in Django Framework.

For installation, it’s pretty easy. I only need a package named factory_boywhich includes the Faker package.

(myenv) $ pip install factory_boy

If you want to see full reference from factory_boy, you can visit this link.

How to use ?

How to use it is quite easy. In this case I have a simple model class, called Product model.

class Product(models.Model):
    sku = models.CharField(max_length=30, unique=True, 
                           primary_key=True)
    name = models.CharField(max_length=30)
    base_price = models.PositiveIntegerField()
    price = models.PositiveIntegerField()
    stock = models.PositiveIntegerField()
    stock_min = models.PositiveIntegerField()

    def __str__(self):
        return self.sku

    class Meta:
        db_table = 'product'

Then, iwill create a tests directory. However, I need to delete the tests.pyfile inside my app before making it.

Then I will create a structure like this inside my app:

myapp/
    tests/
        factories.py
        test_products_v1.py

The factories.py file contains the factory product that will create the product object as long as I call it in the testing phase. It will create as many objects as I want in testing. While the test_products_v1.py file contains the test code for the product.

The contents of the factories.py file are as follows:

import factory
import random
from factory.django import DjangoModelFactory

class ProductFactory(DjangoModelFactory):
    @factory.sequence
    def sku(n):
        return 'SKU-%d' % n

    @factory.sequence
    def name(n):
        return 'PRODUCT-%d' % n

    base_price = factory.lazy_attribute(
                 lambda o: random.randint(100, 2000))
    price = factory.lazy_attribute(
            lambda o: random.randint(1000, 20000))
    stock = factory.lazy_attribute(lambda o: random.randint(1, 100))
    stock_min = factory.lazy_attribute(
                lambda o: random.randint(1, 5))

    class Meta:
        model = myapp.Product'

Look at the fields. It’s like a field on a model that’s in the Product model. In the Meta class, there is one attribute named model. This attribute contains a value referencing my Product model that has the format <appname>. <ModelName>.

Ok, if we make the test in the file test_products_v1.py, more or less we will use the Factory class we have created earlier:

import json
from django.test import TestCase
from rest_framework.test import APITestCase
from rest_framework import status
from salesapi.tests.factories import ProductFactory
from sales.models import Product

class TestProductsV1(APITestCase):

    def test_product_list(self):
        for _ in range(3):
            ProductFactory()
        response = self.client.get(
            '/api-sales/products/'
        )
        expected = 3
        self.assertEqual(
            response.status_code, status.HTTP_200_OK)
        self.assertEqual(
            len(json.loads(response.content.decode('utf-8'))), 
            expected)

Simple and so elegant. I love it. Django & Python is fucking awesome.