[TIP] unittest 0.2.0: class and module level fixtures

Michael Foord fuzzyman at voidspace.org.uk
Fri Mar 5 16:55:20 PST 2010


Hello all,

unittest2 0.2.0 is out. unittest2 now has class and module level 
fixtures: setUpClass, setUpModule, tearDownClass, tearDownModule.

http://pypi.python.org/pypi/unittest2/

Install with: "pip install -U unittest2"

These features are tested but I'm sure there are some lurking bugs or 
oddities, so please try it out.

* Implementation: http://hg.python.org/unittest2/file/tip/unittest2/suite.py
* Tests: 
http://hg.python.org/unittest2/file/tip/unittest2/test/test_shared_fixtures.py

Below are some notes on how they work.

Class and module level fixtures are implemented in unittest2.TestSuite. 
When the test suite encounters a test from a new class then 
tearDownClass from the previous class (if there is one) is called, 
followed by setUpClass from the new class.

Similarly if a test is from a different module from the previous test 
then tearDownModule from the previous module is run, followed by 
setUpModule from the new module.

After all the tests in the suite have run the final tearDownClass and 
tearDownModule are run.

The default ordering of tests created by the unittest test loaders is to 
group all tests from the same modules and classes together. This will 
lead to setUpClass / setUpModule (etc) being called exactly once per 
class and module. If you randomize the order so that tests from 
different modules and classes are adjacent to each other then these 
shared fixture functions may be called multiple times.

If there are any exceptions raised during one of these functions / 
methods then the test is reported as an error. Because there is no 
corresponding test instance an _ErrorHolder object (that has the same 
interface as a TestCase) is created to represent the error. If you are 
just using the standard unittest2 test runner then this detail doesn't 
matter, but if you are a framework author it may be relevant.

If there is demand for it, it would be possible to add a 'randomize' 
option to the test loaders that will randomize the order of test modules 
in a suite, the order of test classes within modules and the order of 
tests within a class. This will allow for tests to be run in a somewhat 
random order whilst maintaining an order properly compatible with shared 
fixtures.

Note that shared fixtures do not play well with features like test 
parallelization and they also break test isolation. They should be used 
with care.


setUpClass and tearDownClass
--------------------------------------

These must be implemented as class methods.

import unittest2

class Test(unittest2.TestCase):
@classmethod
def setUpClass(cls):
cls._connection = createExpensiveConnectionObject()

@classmethod
def tearDownClass(cls):
cls._connection.destroy()

If you want the setUpClass and tearDownClass on base classes called then 
you must call up to them yourself. The implementations in 
unittest2.TestCase are empty.

If an exception is raised during a setUpClass then the tests in the 
class are not run and the tearDownClass is not run. Skipped classes will 
not have setUpClass or tearDownClass run.

A setUpClass that raises a unittest2.SkipTest exception will currently 
be reported as an error rather than a skip (although the effect is the 
same). This will be fixed at some point in the future.


setUpModule and tearDownModule
--------------------------------------------

These should be implemented as functions.

def setUpModule():
createConnection()

def tearDownModule():
closeConnection()

If an exception is raised in a setUpModule then none of the tests in the 
module will be run and the tearDownModule will not be run.

A setUpModule that raises a unittest2.SkipTest exception will currently 
be reported as an error rather than a skip (although the effect is the 
same). This will be fixed at some point in the future.

-- 
http://www.ironpythoninaction.com/
http://www.voidspace.org.uk/blog

READ CAREFULLY. By accepting and reading this email you agree, on behalf 
of your employer, to release me from all obligations and waivers arising 
from any and all NON-NEGOTIATED agreements, licenses, terms-of-service, 
shrinkwrap, clickwrap, browsewrap, confidentiality, non-disclosure, 
non-compete and acceptable use policies (”BOGUS AGREEMENTS”) that I have 
entered into with your employer, its partners, licensors, agents and 
assigns, in perpetuity, without prejudice to my ongoing rights and 
privileges. You further represent that you have the authority to release 
me from any BOGUS AGREEMENTS on behalf of your employer.




More information about the testing-in-python mailing list