Test driven, I bet you must have heard of it in many different places. It already expanded to almost all languages and platform. This post will show you testing in Python.

What is doctest

If you have Python, you have doctest, it shipped with Python. We will start from this one.

The doctest is a piece of text that looks like interactive Python sessions. If you want , you can just copy the Python interactive interpreter output to a text file.

Lets write a simple doctest.

 
This is a simple  doctest
 
>>> def square(x):
...     return x * x
>>> square(4)
162
 

The output.

 
F:\tmp>python -m doctest test.txt
**********************************************************************
File "test.txt", line 5, in test.txt
Failed example:
    square(4)
Expected:
    162
Got:
    16
**********************************************************************
1 items had failures:
   1 of   2 in test.txt
***Test Failed*** 1 failures.
 

Unit testing in Python

When we talk about testing , we usually means unit testing, its the most common test type.

A unit is a smallest pieces of code , like a function. But in OOP, like Java or C++, usually a whole class is treated as a unit.

Go advance, the unittest

When the testing get more complex, doctest start to incompetent, we need more powerful tool, for example a testing framework like JUnit in Java. In Python , we have unittest, it has another name: PyUnit. The original name is PyUnit , but people refer it as unittest when its added to Python standard libraries.

To use unittest, import it and inherit from unittest.TestCase, define setUp and tearDown, then define your test code in method which name start with "test". If you familiar with JUnit, this should very easy to use.

 
import unittest
 
def square(x):
    return x * x
 
class MyTest(unittest.TestCase):
    def setUp(self):
        pass
    def tearDown(self):
        pass
    def test_square(self):
        self.assertTrue(square(2) == 4)        
 
if __name__ == '__main__':
    unittest.main()
 
 
 
 

Assertions in unittest

The most useful things in unittest framework it the various assertion method, you will use them a lot.

 
assertTrue,assertFalse: all purpose assertion, but not recommend to use cause it provide little infomation when test fail.
 
assertEqual, assertNotEqual: whether two parameters equal, if not, report and return the actaul value.
 
assertAlmostEqual, assertNotAlmostEqual: This is for comparing floating point, allows a tiny difference between two floating number.
 
assertRaise: Checks a whether a callable object raises a spfecified exception, when accpet a certain set of parameters.
 

Automate testing process with Nose

Nose is a tool can find your test file and execute them automatically, instead manually running these tests again and again . Because your tests needs to run repeatedly across the development process to verify the new code didn't break some of them.

Get Nose. Go to http://code.google.com/p/python-nose/downloads/list and download the packaged, decompress it to local driver and execute.

 
setup.py install
 

The Nose executable will reside in "D:\Python27\Scripts". Then you should add this path to PATH environment variable. Issues the command in cmd window.

 
D:\Python27\Scripts>nosetests
 
----------------------------------------------------------------------
Ran 0 tests in 0.006s
 
OK
 

You are ready to go.

By default, Nose will not handle doctest, except specified in command options.

 
nosetests --with-doctest --doctest-extension=txt
 

You can setup a nose.cfg file or wrap the command with a bat file.

 
F:\tmp\pythonproj\test>set HOME
HOME=D:\bin\emacs-22.3
cd D:\bin\emacs-22.3
touch nose.cfg
 
 

Put these text into nose.cfg.

 
 
[nosetests]
with-doctest=1
doctest-extension=txt
 
 

How Nose search for tests

Nose will search for the file which name contains "test" or "Test" at the beginning or following a underscore, dot or dash. Here are some examples.

 
test_1.py
test_2.txt
test3.txt
bugfix2-test.txt
bugfix1_test.txt
 

You may want to create a folder with the name like test to hold all your test files. And naming them in a consistent way, for example all start with "test_".