Django Unit Testing - Sloathking/Foolish-Wizardz GitHub Wiki

Unit Testing in Django

Author: Brett W.


Overview

Automating the tests that will be used to test the functionality of our code, not only speeds up testing but also allows for early warnings if new additions will mess up something.

Django makes use of the Python standard library module unittest and follows a naming pattern of test_*.

Steps

  1. Setup folder and file structure
  2. Write Tests

Setup folder and file structure

  • Create a /tests/ folder in the base directory.

image

  • Create an __init__.py file, and leave this file empty.

image

  • Then create test_*.py files for the parts you want to test.

DO NOT CREATE A __pycache__ FOLDER. It will be created automatically when you run tests

Write Tests

  1. Models

When unit testing the Models in the database, we want to test that our Model is saved to the database correctly and any methods we have defined function as they should.

Import Modules

from django.test import TestCase
from django.contrib.auth.models import User
from proj_app.models import Session

Create test Class

class SessionModelTest(TestCase):

Creating test data There are 2 ways to make sure there is something for the tests to test.

  1. Using setUpTestData(): This method is only called ONCE when the test environment is setup.
  2. Using setUp(): This method is called before every test that is run.
def setUp(self):
   self.user = User.objects.create_user(username='testuser', password='password123')
   self.session = Session.objects.create(
       owner=self.user,
       title='Test Session',
       game_name='Test Game',
       thumbnail='https://test.com',
       date='2024-04-24',
       time='12:00:00',
       description='Test Description'
   )

Model Tests

Test methods must be of the format test_*(self): for them to be found when you run the tests.

def test_title(self):
       session = Session.objects.get(id=1)
       expected_object_name = f'{session.title}'
       self.assertEqual(expected_object_name, 'Test Session')

The testing for forms and views will be similiar.

  1. Forms

If you are using the built-in Django forms then we want to test that all the correct fields are generated when it renders the form. If you are using a custom form, then you will want to test that things are labeled correctly and generated correctly.

Import Modules

from django.test import TestCase
from django.contrib.auth.models import User
from proj_app.models import Session
from proj_app.forms import *

Create test Class(es)

class SessionFormTest(TestCase):
class GameSelectFormTest(TestCase):

Instead of creating test data, we can create the form and verify

def test_form_fields(self):
   form = SessionForm()
   self.assertTrue(form.fields['title'])
   self.assertTrue(form.fields['game_name'])
   self.assertTrue(form.fields['thumbnail'])
   self.assertTrue(form.fields['date'])
   self.assertTrue(form.fields['time'])
   self.assertTrue(form.fields['description'])
  1. Views

Import Modules

from django.test import TestCase, Client
from django.urls import reverse
from django.contrib.auth.models import User
from proj_app.models import Session

Create test Class

class ViewTest(TestCase):

Create test data This has the same 2 methods as the Models section

def setUp(self):
        self.client = Client()
        self.user = User.objects.create_user('testuser', 'password123')
        self.session = Session.objects.create(
            owner=self.user,
            title='test session',
            game_name='test game',
            thumbnail='test thumbnail',
            date='2024-04-24',
            time='12:00',
            description='test description'
        )

View tests

def test_index_view(self):
        response = self.client.get(reverse('index'))
        self.assertEqual(response.status_code, 200)
        self.assertTemplateUsed(response, 'proj_app/index.html')