Recipe 8.8. Running Unit Tests Most Simply
Credit: Justin Shaw
Problem
You
find the test runners in standard library module
unittest to be less than optimally simple, and you
want to ensure that running unit tests is so simple and painless as
to leave simply no excuse for not testing
regularly and copiously.
Solution
Save the following code in module microtest.py
somewhere along your Python sys.path:
import types, sys, traceback
class TestException(Exception): pass
def test(modulename, verbose=None, log=sys.stdout):
''' Execute all functions in the named module which have _ _test_ _
in their name and take no arguments.
modulename: name of the module to be tested.
verbose: If true, print test names as they are executed
Returns None on success, raises exception on failure.
'''
module = _ _import_ _(modulename)
total_tested = 0
total_failed = 0
for name in dir(module):
if '_ _test_ _' in name:
obj = getattr(module, name)
if (isinstance(obj, types.FunctionType) and
not obj.func_code.co_argcount):
if verbose:
print>>log, 'Testing %s' % name
try:
total_tested += 1
obj( )
except Exception, e:
total_failed += 1
print>>sys.stderr, '%s.%s FAILED' % (modulename, name)
traceback.print_exc( )
message = 'Module %s failed %s out of %s unittests.' % (
modulename, total_failed, total_tested)
if total_failed:
raise TestException(message)
if verbose:
print>>log, message
def _ _test_ _( ):
print 'in _ _test_ _'
import pretest
pretest.pretest('microtest', verbose=True)
Discussion
Module unittest in the Python Standard Library is
far more sophisticated than this simple microtest
module, of course, and I earnestly urge you to study it. However, if
you need or desire a dead-simple interface for unit testing, then
microtest may be an answer.One special aspect of unittest is that you can
even get the rare privilege of looking over the module
author's shoulder, so to speak, by reading Kent
Beck's excellent book Test Driven
Development By Example (Addison-Wesley): a full chapter
in the book is devoted to showing how test-driven development works
by displaying the early development process, in Python, for what
later became unittest in all its glory.
Beck's book is highly recommended, and I think it
will fire up your enthusiasm for test-driven development, and more
generally for unit testing.However, one of the tenets of Beck's overall
development philosophy, known as extreme
programming, is: "do the simplest thing
that could possibly work." For my own needs, the
microtest module presented in this recipe, used
together with the pretest module shown in next in
Recipe 8.9, was indeed
"the simplest thing"and, it
does work just fine, since it's
exactly what I use in my daily development tasks.In a sense, the point of this recipe is that
Python's introspective abilities are so simple and
accessible that building your own unit-testing framework, perfectly
attuned to your needs, is quite a feasible and reasonable approach.
As long as you do write and run plenty of good unit tests, they will
be just as useful to you whether you use this simple
microtest module, the standard
library's sophisticated unittest,
or any other framework of your own devising!
See Also
Documentation on the unittest standard library
module in the Library Reference and
Python in a Nutshell; Kent Beck,
Test Driven Development By Example
(Addison-Wesley).