Writing automated tests for your Django app | An introduction to continuous integration (CI)

Writing automated tests for your Django app | An introduction to continuous integration (CI)

Have you ever bought a pen and tried to write something on a random piece of paper to see if it works? why do you test it even when we all know it is a pen and pens are supposed to write stuff? You do that to ensure you do not pay for a faulty pen because errors can happen from the factory. This is why it is important to test things. So, what does it mean to test your app? This is something I was always curious about, being a junior developer striving to learn things on my own. It has been a cool journey so far. In this article, I will try to explain what testing is all about and how you can run simple tests for your Django app :)

Why is it important to run tests as a programmer?

  • To validate your code works as expected.
  • When you’re refactoring or modifying old code, you can use tests to ensure your changes haven’t affected your application’s behavior unexpectedly.

In the world of programming, testing is done to prevent your program from having unforeseen bugs and providing evidence that your code works the way you said it should. For example, if you enter number 12, and you want your function to return the number 6 every time, the only way to confirm that it works is by writing tests. Python programming language comes with several testing libraries like unittest, nose or nose2, and pytest. But the most popular library is unittest.

Running tests in python

The assert keyword is used to run tests in python programming language. It can be used to test if a simulation is equal to a result with assertEqual, or if it would return True or False (assertTrue and assertFalse respectively).

Assuming we want to test a simple function that returns true if a number is even and false if it is odd. A python test will look like this:

Lets call this file helper_functions.py;

# Function to check if number is odd or even

def is_even(num):
      if (num % 2) == 0:
           return True
      else:
           return False

In the test file, let's call it test.py;

import unittest

from helper_functions import is_even

# This class will house all your tests. And don't forget to begin the name of every test with 'test'
class Tests (unittest.TestCase):

         def test_1(self):
               """ test if number 6 is an even number """
               self.assertTrue(is_even(6))

         def test_2(self):
               """ test if number 7 is an even number """
               self.assertFalse(is_even(7))


# when the program is run, unittest will run all the tests
if __name__ == "__main__":
       unittest.main()

When you run this test, it will bring up something like this:

System check identified 3 issues (0 silenced).
...
----------------------------------------------------------------------
Ran 3 tests in 0.077s

OK

Running tests in Django

Testing a Web application is a complex task because a Web application is made of several layers of logic – from HTTP-level request handling, to form validation and processing, to template rendering. With Django’s test-execution framework and loaded utilities, you can simulate requests, insert test data, inspect your application’s output and generally verify your code is doing what it should be doing. Django also uses unittest as the standard library. Django makes use of subclasses from django.test.TestCase, which is a subclass of unittest.TestCase runs each test to provide isolation. In the example below, let us assume we have a database model in our Django app called Cars, which stores cars and their model:

from django.test import Client, TestCase
from .models import Cars

# TestCase to house all tests
class CarsTestCase(TestCase):
        # setUp is used to set up dummy data to test with
         def setUp(self):
              # create dummy cars in the database
              car1 = Cars.objects.create(company="toyota", model="corolla")
              car2 = Cars.objects.create(company="nissan", model="bluebird")
              car3 = Cars.objects.create(company="toyota", model="camry")

            # test the number of toyota cars
         def test_toyota_count(self):
               a = Cars.objects.filter(company="toyota")
               self.assertEqual(a.count(), 2)

          # test for the total number of cars in the model
         def test_car_count(self):
               a = Cars.objects.all()
               self.assertEqual(a.count(), 3)


         # test for index page
        def test_index(self):
                # simulate user
               c = Client()
               response = c.get("/home/")
               self.assertEqual(response.status_code, 200)


          # test valid car page
        def test_valid_page(self):
               a = Cars.objects.get(company="toyota")
                # simulate user
               c = Client()
               response = c.get(f"/cars/{a.id}")
               fake_response = c.get("/cars/a4")
               self.assertEqual(response.status_code, 200)
               self.assertFalse(fake_response.status_code, 404)

To run a test in Django, run the test.py file that is automatically generated when you install a Django app by the command:

python manage.py test

This command will run all the tests on your web app and tell you if parts of your application are not behaving as expected. Django tests are usually carried out to cover every important part of the web page. It is important to write as many tests as possible and also write new tests whenever you add features to your web application.

Can you test javascript web pages? Yes! some libraries let you simulate a user interacting with your page like when a user clicks a button. Libraries like selenium, TestingWhiz e.t.c.

Continuous Integration (CI)

So, after writing all the tests, what next? The idea of writing test is to automate debugging so when working with a team or adding new features, you don't have to manually go through all the codes to confirm everything works fine -- that would be a lot of work :o, or wait until deployment only to realize someone's code broke the entire app. What is the solution to this? One very good and popular tool is Github Actions. With Github actions, anytime you push to the production repo, Github virtual machine runs your tests to find bugs, if all the tests are not passed it would fail to deploy until the problem is fixed. That way, you don't have to worry about your app having issues. Click on %[github.com/features/actions] to learn more about Github actions.

Thanks for reading. I hope you enjoyed my article. Watch out for more ;)