Chapter 7. Data-Centric Programming

Table of Contents

7.1. Diving in

In Unit Testing, we discussed the philosophy of unit testing and stepped through the implementation of it in Python. This chapter will focus more on advanced Python-specific techniques, centered around the unittest module. If you haven’t read Unit Testing, you’ll get lost about halfway through this chapter. You have been warned.

The following is a complete Python program that acts as a cheap and simple regression testing framework. It takes unit tests that you’ve written for individual modules, collects them all into one big test suite, and runs them all at once. I actually use this script as part of the build process for this book; I have unit tests for several of the example programs (not just the roman.py module featured in Unit Testing), and the first thing my automated build script does is run this program to make sure all my examples still work. If this regression test fails, the build immediately stops. I don’t want to release non-working examples any more than you want to download them and sit around scratching your head and yelling at your monitor and wondering why they don’t work.

Example 7.1. regression.py

If you have not already done so, you can download this and other examples used in this book.

"""Regression testing framework

This module will search for scripts in the same directory named
XYZtest.py.  Each such script should be a test suite that tests a
module through PyUnit.  (As of Python 2.1, PyUnit is included in
the standard library as "unittest".)  This script will aggregate all
found test suites into one big test suite and run them all at once.
"""

import sys, os, re, unittest

def regressionTest():
    path = os.path.abspath(os.path.dirname(sys.argv[0]))
    files = os.listdir(path)                    
    test = re.compile("test.py$", re.IGNORECASE)
    files = filter(test.search, files)          
    filenameToModuleName = lambda f: os.path.splitext(f)[0]
    moduleNames = map(filenameToModuleName, files)         
    modules = map(__import__, moduleNames)                 
    load = unittest.defaultTestLoader.loadTestsFromModule
    return unittest.TestSuite(map(load, modules))        

if __name__ == "__main__":
    unittest.main(defaultTest="regressionTest")

Running this script in the same directory as the rest of the example scripts that come with this book will find all the unit tests, named moduletest.py, run them as a single test, and pass or fail them all at once.

Example 7.2. Sample output of regression.py

[f8dy@oliver py]$ python regression.py -v
help should fail with no object ... ok                             1
help should return known result for apihelper ... ok
help should honor collapse argument ... ok
help should honor spacing argument ... ok
buildConnectionString should fail with list input ... ok           2
buildConnectionString should fail with string input ... ok
buildConnectionString should fail with tuple input ... ok
buildConnectionString handles empty dictionary ... ok
buildConnectionString returns known result with known input ... ok
fromRoman should only accept uppercase input ... ok                3
toRoman should always return uppercase ... ok
fromRoman should fail with blank string ... ok
fromRoman should fail with malformed antecedents ... ok
fromRoman should fail with repeated pairs of numerals ... ok
fromRoman should fail with too many repeated numerals ... ok
fromRoman should give known result with known input ... ok
toRoman should give known result with known input ... ok
fromRoman(toRoman(n))==n for all n ... ok
toRoman should fail with non-integer input ... ok
toRoman should fail with negative input ... ok
toRoman should fail with large input ... ok
toRoman should fail with 0 input ... ok
kgp a ref test ... ok
kgp b ref test ... ok
kgp c ref test ... ok
kgp d ref test ... ok
kgp e ref test ... ok
kgp f ref test ... ok
kgp g ref test ... ok

----------------------------------------------------------------------
Ran 29 tests in 2.799s

OK
1 The first 5 tests are from apihelpertest.py, which tests the example script from The Power Of Introspection.
2 The next 5 tests are from odbchelpertest.py, which tests the example script from Getting To Know Python.
3 The rest are from romantest.py, which we studied in depth in Unit Testing.