Lets Unit Test Django Forms

In the last few months I have been building a web application using Django. In a brief, It’s a app that does CRUD operations to a PostgreSQL DB. The project can be said to be moderate in size, it has dozens of models, dozens of views and a few dozen forms.
There was a moment when I was thinking that the project will grow more. If I make a change in a model, I will have to change its instances in different parts of the code like in views, Admins and forms.
Any tiny change could trigger a bug in the whole project. So I started researching about what good practices, libraries or approaches that I could implement to improve the development of my Django Application. I came up with Unit Testing and Test-Driven Development.
Test-Driven Development is a software development approach where you first write tests before making the logic of your application source code. This tests are write in form unit tests (testing every aspect of the code).
Unit Testing Django Forms
Forms are components that accepts data from the user. Django validates those forms based in the structure of the model that they are based on or the validations that you implement.
So, Let’s create our first unit testing for a form based in a a model. First lets create a project:
django-admin startproject unit-test-project
python manage.py startapp product
python manage.py runserver
python manage.py migrate
Making tests
In order to implement unit tests in your Django project, we can inherent our tests from TestCase. This is a subclass of unitest.TestCase, which is a class used in python for unit tests. There are other classes like TransactionTestCase or SimpleTestCase.
For make tests, we implement asserts. Assert are declarations that validates if a piece of code works correctly. There are multiple types of asserts like:
self.assertTrue // checks if a value is true
self.assertFalse //check if a value if false
self.assertEqual //check if two values are equal
If you want to learn more about them here is a link for a list of available asserts in python
Inside tests.py, write
from django.test import TestCase
from .models import Product
from .forms import ProductFormclass ProductFormTest(TestCase):def test_is_invalid(self):
form = ProductForm(data={"name": "Computer", "price": 400.1234})
self.assertFalse(form.is_valid())def test_form_is_valid(self):
form = ProductForm(data={"name": "Computer", "price": 400})
self.assertTrue(form.is_valid())
We are going to validate if the data passed to the form is valid.
For run our tests, we have to run:
python manage.py test
This will search tests in any file named “test*.py” under the current working directory. This will cause an error because we don’t have our Product Model or Product Form.
Implementing model and form
In product’s model.py, write the next model:
class Product(models.Model):
name = models.CharField(max_length=25)
price = models.IntegerField()def __str__(self):
return self.name
then hit
python manage.py makemigrations
python manage.py migrate
This will create the entity in the DB.
Now, write the next form in forms.py
from django import forms
from .models import Productclass ProductForm(forms.ModelForm):
class Meta:
model = Product
fields = ("name", "price", )
Having the model and the form, we can make the tests.
python manage.py test
This will show if the tests passed.
Conclusion
Make unit tests to every aspect of your code allows you to check if it works like you are expecting. You can use your tests as a documentation for your code. If you migrate the version of your library or programming language, it allows you to verify if everything is working correctly.
if you want to learn more about testing in Django: here and here are good links from Django documentation