A first testcase

A testcase is a single class that contains one or more methods that perform a single check each. It is possible to check two different behaviors in one test method, but that's a particularly bad idea— if the test fails, you won't know exactly what went wrong, and where.

The example class we want to test, DocviewDoc, is to show a very simple behavior: it must be creatable, and it must know whether it is modified. That makes for two tests.

To create a test, we have to subclass the unittest.TestCase class. This class provides some methods for the setting up and destroying of a test environment and a default method, runTest, that can contain the testing code. A very simple test is defined as follows:

class SimpleTest(unittest.TestCase):

    def runTest(self):
        assert 1=2, 'One is not two'
    

We want to check whether the DocviewDoc class can be instantiated. This is not as trivial and silly as it may sound: a Python class constructor can have a great and variable number of arguments, and keeping classes instantiatable is quite important. First, let's define a testcase:

#
# dvt1.py - a simple test of instantiating a document
#
import unittest
from docviewdoc import DocviewDoc

class DocviewDocTestCase(unittest.TestCase):
    """DocviewDocTestCase test the DocviewDoc class.
    """

    def setUp(self):
        print "setUp called"

    def tearDown(self):
        print "tearDown called"

    def runTest(self):
        """Check whether the document could be instantiated"""
        doc=None
        doc=DocviewDoc()
        assert doc!=null, 'Could not instantiate DocviewDoc'
    

Adding a docstring, always a good idea, is particularly useful for TestCase classes, since this text will be available through the shortDescription() function. It will be displayed when the test is run - either on the command line or in the gui.

The setUp method of the TestCase class is executed before runTest, and can be used to prepare the environment. The tearDown method is called after the test has run, whether successfully or not. You can use it to clear away garbage that is left by the test. On the other hand, if setUp fails, the entire test will not run. I have included the functions here; you don't have to write them if you don't need them.

The test itself is very simple. First, we give the variable doc a known value, namely None. After that, a DocviewDoc is instantiated. Using Python's standard assert statement, a check is made to see whether the variable doc still points to None—if so, instantiation failed.

Note that use of assert means that running unit tests with optimized bytecode (.pyo files) is useless. Compiling Python to optimized bytecode removes all traces of asserts (and the line-numbers that can be used for stack traces). While the unittest framework includes a special, home-brew, assert function that isn't affected by optimized compilation, it is still better to test plain Python. The stacktraces are far more useful, and additionally, the unittest assert is less convenient.

Python's assert statement is very handy, and quite simple. It takes the form of:

      assert expression, message
    

Where the message will be printed and an AssertionError raised when the expression turns out to be false. assert is a statement, not a function. This means that you shouldn't encase the expression and the message in brackets. If the statement is too long for the line, you can use a backslash as a line-continuation.