Large projects
In large projects, where you have many
tests, you will want to automate the assembly of testsuite as
much as possible. By creating a few Python scripts that work
with standardized testsuites (e.g., the function that returns
the testsuite is always module.suite()),
you can run all tests as often as you want to.
You can already nest testsuites out of the
box, and by creating a master test class that reads a
configuration file and constructs a master test-suite, you can
test a whole system in one run.
Take the following definition file, for
instance:
#
# unittests - unittests for the whole system.
#
# dvt1 tests the creation of a docviewdoc
#dvt1.suite
# dvt2 tests a whole lot more
dvt2.suite
If you use the following script, then all
tests that are defined in the form of module.function, where
module is on the Python path and function returns a
TestSuite object, will be combined in one
mega-TestSuite.
#
# systemtest.py - run all tests that are not commented out in unittests
#
import unittest
def suite():
testSuite=unittest.TestSuite()
f=open("unittests")
for t in f.readlines():
t=t.strip() # remove all whitespace
if t[0]!="#": # a comment
testSuite.addTest(unittest.createTestInstance(t))
return testSuite
def main():
runner = unittest.TextTestRunner()
runner.run(suite())
if __name__=="__main__":
main()
Note the use of the function
unittest.createTestInstance, which can
create a testcase or testsuite from a simple string. There's an
optional second argument, module, which points to the module
where the test can be found.
Another function,
unittest.makeSuite() can scan a class for
functions that begin with a certain prefix, and combine them
into a testsuite. For instance, we could rewrite
dvt2.py into:
#
# dvt3.py - using makeSuite
#
import sys
import unittest
from docviewdoc import DocviewDoc
def divide(a, b):
return a/b
class DocviewDocTestCase(unittest.TestCase):
"""DocviewDocTestCase test the DocviewDoc class.
"""
def checkInstantion(self):
"""Check whether the document could be instantiated"""
doc=None
doc=DocviewDoc()
assert doc!=None, 'Could not instantiate DocviewDoc'
def checkModifiable(self):
"""Check whether the document could be modified"""
doc=DocviewDoc()
doc.slotModify()
assert doc.isModified(), 'Document could not be modified'
def suite():
testSuite=unittest.makeSuite(DocviewDocTestCase, "check")
return testSuite
def main():
runner = unittest.TextTestRunner()
runner.run(suite())
if __name__=="__main__":
main()
By always prefixing your tests with
‘check', you make sure they are all included. If you had
to add every test by hand, it would be only natural to forget
one or two over time. Eventually you would notice that a test
was not being executed. By that time you might have changed the
tested code so the original test fails. The purpose of unit
testing is always to be sure that everything works as you think
it should.