Django Unit Testing Testing Django Models Effectively


Assuming a class

from django.db import models

class Author(models.Model):
   name = models.CharField(max_length=50)
    def __str__(self):
    def get_absolute_url(self):
        return reverse('view_author', args=[str(])

class Book(models.Model):
    author = models.ForeignKey(Manufacturer, on_delete=models.CASCADE)
    private = models.BooleanField(default=false)
    publish_date = models.DateField()

    def get_absolute_url(self):
        return reverse('view_book', args=[str(])
    def __str__(self):

Testing examples

from django.test import TestCase
from .models import Book, Author

class BaseModelTestCase(TestCase):

    def setUpClass(cls):
        super(BaseModelTestCase, cls).setUpClass() = Author(name='hawking')
        cls.first_book = Book(, name="short_history_of_time")
        cls.second_book = Book(, name="long_history_of_time")

class AuthorModelTestCase(BaseModelTestCase):
    def test_created_properly(self):
         self.assertEqual(, 'hawking')
         self.assertEqual(True, self.first_book in
    def test_absolute_url(self):
        self.assertEqual(, reverse('view_author', args=[str(]))

class BookModelTestCase(BaseModelTestCase):
    def test_created_properly(self:
        self.assertEqual(1, len(Book.objects.filter(name__startswith='long'))
    def test_absolute_url(self):

Some points

  • created_properly tests are used to verify the state properties of django models. They help catch sitautions where we've changed default values, file_upload_paths etc.
  • absolute_url might seem trivial but I've found that it's helped me prevent some bugs when changing url paths
  • I similarly write test cases for all the methods implemented inside a model (using mock objects etc)
  • By defining a common BaseModelTestCase we can setup the necessary relationships between models to ensure proper testing.

Finally, when in doubt, write a test. Trivial behavior changes are caught by paying attention to detail and long forgotten pieces of code don't end up causing unnecessary trouble.