[Zope3-checkins]
SVN: zope.testing/branches/test-checkers/src/zope/testing/testrunner.py
Add a --checkers option. You pass a Python module name (e.g.
Marius Gedminas
marius at pov.lt
Sat Jan 20 09:27:05 EST 2007
Log message for revision 72145:
Add a --checkers option. You pass a Python module name (e.g.
zope.testing.eventcheckers). You can pass more than one --checkers argument.
The Python module must define a function named test_checkers() that returns
a list of objects. These objects can define the following methods:
startTest(test)
stopTest(test)
startLayer(layer)
stopLayer(layer)
The checkers can inspect the application state before and after a test (or
layer) and complain if the test/layer changed something but did not clean up
after itself.
What's missing in this branch:
- tests for the feature
- documentation
- sample checkers:
- look at logging handlers
- look at zope.event.subscribers
- look at data managers registered with the transaction
- look at the list of component registrations
Changed:
U zope.testing/branches/test-checkers/src/zope/testing/testrunner.py
-=-
Modified: zope.testing/branches/test-checkers/src/zope/testing/testrunner.py
===================================================================
--- zope.testing/branches/test-checkers/src/zope/testing/testrunner.py 2007-01-20 14:22:47 UTC (rev 72144)
+++ zope.testing/branches/test-checkers/src/zope/testing/testrunner.py 2007-01-20 14:27:04 UTC (rev 72145)
@@ -377,6 +377,14 @@
remove_stale_bytecode(options)
+ checkers = []
+ if options.checkers:
+ for module_name in options.checkers:
+ module = import_name(module_name)
+ checkers.extend(module.test_checkers())
+ print "Loaded %d test checkers from %s" % (len(checkers),
+ module_name)
+
tests_by_layer_name = find_tests(options, found_suites)
ran = 0
@@ -407,7 +415,8 @@
if should_run:
print "Running unit tests:"
nlayers += 1
- ran += run_tests(options, tests, 'unit', failures, errors)
+ ran += run_tests(options, tests, 'unit', failures, errors,
+ checkers)
setup_layers = {}
@@ -430,7 +439,7 @@
nlayers += 1
try:
ran += run_layer(options, layer_name, layer, tests,
- setup_layers, failures, errors)
+ setup_layers, failures, errors, checkers)
except CanNotTearDown:
setup_layers = None
if not options.resume_layer:
@@ -441,7 +450,7 @@
if setup_layers:
if options.resume_layer == None:
print "Tearing down left over layers:"
- tear_down_unneeded((), setup_layers, True)
+ tear_down_unneeded((), setup_layers, checkers=checkers)
if options.resume_layer:
sys.stdout.close()
@@ -485,7 +494,7 @@
return not bool(import_errors or failures or errors)
-def run_tests(options, tests, name, failures, errors):
+def run_tests(options, tests, name, failures, errors, checkers=()):
repeat = options.repeat or 1
repeat_range = iter(range(repeat))
ran = 0
@@ -514,6 +523,9 @@
for test in tests:
if result.shouldStop:
break
+ for checker in checkers:
+ if hasattr(checker, 'startTest'):
+ checker.startTest(test)
result.startTest(test)
state = test.__dict__.copy()
try:
@@ -532,16 +544,25 @@
result.stopTest(test)
test.__dict__.clear()
test.__dict__.update(state)
+ for checker in checkers:
+ if hasattr(checker, 'stopTest'):
+ checker.stopTest(test)
else:
# normal
for test in tests:
if result.shouldStop:
break
+ for checker in checkers:
+ if hasattr(checker, 'startTest'):
+ checker.startTest(test)
state = test.__dict__.copy()
test(result)
test.__dict__.clear()
test.__dict__.update(state)
+ for checker in checkers:
+ if hasattr(checker, 'stopTest'):
+ checker.stopTest(test)
t = time.time() - t
if options.verbose == 1 or options.progress:
@@ -591,20 +612,20 @@
return ran
def run_layer(options, layer_name, layer, tests, setup_layers,
- failures, errors):
+ failures, errors, checkers=()):
gathered = []
gather_layers(layer, gathered)
needed = dict([(l, 1) for l in gathered])
if options.resume_number != 0:
print "Running %s tests:" % layer_name
- tear_down_unneeded(needed, setup_layers)
+ tear_down_unneeded(needed, setup_layers, False, checkers)
if options.resume_layer != None:
print " Running in a subprocess."
- setup_layer(layer, setup_layers)
- return run_tests(options, tests, layer_name, failures, errors)
+ setup_layer(layer, setup_layers, checkers)
+ return run_tests(options, tests, layer_name, failures, errors, checkers)
def resume_tests(options, layer_name, layers, failures, errors):
layers = [l for (l, _, _) in layers]
@@ -664,7 +685,7 @@
class CanNotTearDown(Exception):
"Couldn't tear down a test"
-def tear_down_unneeded(needed, setup_layers, optional=False):
+def tear_down_unneeded(needed, setup_layers, optional=False, checkers=()):
# Tear down any layers not needed for these tests. The unneeded
# layers might interfere.
unneeded = [l for l in setup_layers if l not in needed]
@@ -676,6 +697,9 @@
try:
if hasattr(l, 'tearDown'):
l.tearDown()
+ for checker in checkers:
+ if hasattr(checker, 'stopLayer'):
+ checker.stopLayer(l)
except NotImplementedError:
print "... not supported"
if not optional:
@@ -684,14 +708,17 @@
print "in %.3f seconds." % (time.time() - t)
del setup_layers[l]
-def setup_layer(layer, setup_layers):
+def setup_layer(layer, setup_layers, checkers):
assert layer is not object
if layer not in setup_layers:
for base in layer.__bases__:
if base is not object:
- setup_layer(base, setup_layers)
+ setup_layer(base, setup_layers, checkers)
print " Set up %s" % name_from_layer(layer),
t = time.time()
+ for checker in checkers:
+ if hasattr(checker, 'startLayer'):
+ checker.startLayer(layer)
if hasattr(layer, 'setUp'):
layer.setUp()
print "in %.3f seconds." % (time.time() - t)
@@ -1696,6 +1723,15 @@
Specifies the name of a directory to ignore when looking for tests.
""")
+setup.add_option(
+ '--checkers', action="append", dest='checkers',
+ help="""\
+Load test checkers from a specified Python module. The module must have
+a test_checkers() function that returns a list of test checkers. Each checker
+is an object with two methods: startTest(test) and stopTest(test). These
+methods for each checker will be called around every test that is run.
+""")
+
parser.add_option_group(setup)
######################################################################
More information about the Zope3-Checkins
mailing list