An intro tutorial to test driven development in python/django

Welcome to the second article of our Test Driven Development Series. Similar to all our articles it kind of tries to simplify the getting started, this time with unit testing in pyton/django. It tries to save you from the pain, of going through the docs, getting lost at them, and not knowing what to do. It tells you why you should include testing in your daily schedule of writing code and helps you easily get started doing that. The article is aimed at people who know basic python/django and want to get started with testing their code. The post does not talk about integration or functional testing. In case you want, you can refer to them here.

Getting Started with Testing

Tests are a way to ensure the code which you have written, meet the specifications, with minimal developer effort. The tests help breaking the existing erroneous code, or how an existing code integrates with some new features. Having run successful tests ensure that the code works in its entirety. Getting started with testing, has an initial learning curve and kind of seems scary, but with time one starts feeling the necessity and need for it. To begin with one can start writing simple tests and can carry forward from there.

Unit Tests and Integration Tests

A unit test is repeatable (you can run the same tests again), consistent(you expect/get the same result everytime), does not have extra dependencies, verifies a unit(checks one single concern in the use case) and fast. Whereas an integration/functional/system level test, tries to test your system as a whole. The trouble with system tests are that you don't get to know, which part is exactly breaking the whole system.

Widely used unit testing libraries

There are a wide variety of tools that help you get started with unit testing, following are the most famous ones:

  1. unittest

  2. doctest

  3. nose

  4. py.test

You are free to choose any of them. In this post, i will go ahead with unittest2. You might want to read this hacker news discussion, and this SO post on unit test and unit testing library.

Writing a basic unittest

import unittest2

class TestDemo(unittest2.TestCase):
    " A demo of simple unit test"

    def setup(self):
        self.char = 'a'

    def tearDown(self):
        del self.char

    def test_first_pass(self):
        "Asserting that the charecter is not b"
        self.assertNotEqual(self.char, 'b')

    def test_second_fail(self):
        "Making a false assertion"
        assert self.char != 'c'

The above is a simple example of how a unit test is written. In the execution, the methods setup and teardown are repeated for each of the tests respectively. Docstrings are used to tell you which of the tests failed. One point that should be noticed here is that all the function names should begin with "test", another thing that should be taken care of is names should be distinct. At the very basic level unit test is assumed to test a very small piece of code. Based upon what its value should be, or what response it should return.

Progressively we are led to a query what and when to test?

There are no hard and fast rules, and no complete answer to it. Generally a rule of thumb is one should not test the standard/inbuilt libraries and should test all the custom stuff written, to adhere to the specs. Generally the models, views and templatetags.

Its always recommended to write the test up-front and then design your models and views. Initially this is going to be a bit of pain, as you might not realize how to test, this leads you to think more of the functionality and design and you end up getting a better and more structured design. Having said that, if you find it too difficult you can write the models/views first and then write the tests. Lastly if you are running short of time/resource, wait for the bug and then write test for it, make it fail, and then correct the bug. Last is the least recommended way of going about it.

A demo test

Assuming, you are familiar with django, you might want to start a new project(new_project), and an app(first_app) inside it. You can create a file inside new_project/first_app called and place the above TestDemo snippet and run python test first_app to see the above tests pass and fail.

In the next post we will be looking specifically how to test django models, views, forms, templatetags, and filters.


blog comments powered by Disqus