[Zope3-checkins]
SVN: zope.testing/branches/stub-testSetUp_in_layer/src/zope/testing/testrunner.py
Refactor bits of testrunner.py to make it more unit testable
and add some docstrings to this desert
Stuart Bishop
cvs-admin at zope.org
Fri Jun 16 02:26:51 EDT 2006
Log message for revision 68685:
Refactor bits of testrunner.py to make it more unit testable and add some docstrings to this desert
Changed:
U zope.testing/branches/stub-testSetUp_in_layer/src/zope/testing/testrunner.py
-=-
Modified: zope.testing/branches/stub-testSetUp_in_layer/src/zope/testing/testrunner.py
===================================================================
--- zope.testing/branches/stub-testSetUp_in_layer/src/zope/testing/testrunner.py 2006-06-16 06:22:34 UTC (rev 68684)
+++ zope.testing/branches/stub-testSetUp_in_layer/src/zope/testing/testrunner.py 2006-06-16 06:26:47 UTC (rev 68685)
@@ -253,7 +253,7 @@
try:
try:
- failed = run_with_options(options)
+ failed = not run_with_options(options)
except EndRun:
failed = True
finally:
@@ -288,8 +288,17 @@
return failed
-def run_with_options(options):
+def run_with_options(options, found_suites=None):
+ """Find and run tests
+
+ Passing a list of suites using the found_suites parameter will cause
+ that list of suites to be used instead of attempting to load them from
+ the filesystem. This is useful for unit testing the test runner.
+ Returns True if all tests passed, or False if there were any failures
+ of any kind.
+ """
+
if options.resume_layer:
original_stderr = sys.stderr
sys.stderr = sys.stdout
@@ -350,7 +359,7 @@
remove_stale_bytecode(options)
- tests_by_layer_name = find_tests(options)
+ tests_by_layer_name = find_tests(options, found_suites)
ran = 0
failures = []
@@ -456,7 +465,7 @@
if options.gc:
gc.set_threshold(*old_threshold)
- return bool(import_errors or failures or errors)
+ return not bool(import_errors or failures or errors)
def run_tests(options, tests, name, failures, errors):
repeat = options.repeat or 1
@@ -656,7 +665,7 @@
if layer not in setup_layers:
for base in layer.__bases__:
setup_layer(base, setup_layers)
- print " Set up %s.%s" % (layer.__module__, layer.__name__),
+ print " Set up %s" % name_from_layer(layer),
t = time.time()
layer.setUp()
print "in %.3f seconds." % (time.time() - t)
@@ -923,6 +932,15 @@
gather_layers(b, result)
def layer_from_name(layer_name):
+ """Return the layer for the corresponding layer_name by discovering
+ and importing the necessary module if necessary.
+
+ Note that a name -> layer cache is maintained by name_from_layer
+ to allow locating layers in cases where it would otherwise be
+ impossible.
+ """
+ if _layer_name_cache.has_key(layer_name):
+ return _layer_name_cache[layer_name]
layer_names = layer_name.split('.')
layer_module, module_layer_name = layer_names[:-1], layer_names[-1]
return getattr(import_name('.'.join(layer_module)), module_layer_name)
@@ -946,12 +964,34 @@
result.append(layer)
return result
+_layer_name_cache = {}
+
def name_from_layer(layer):
- return layer.__module__ + '.' + layer.__name__
+ """Determine a name for the Layer using the namespace to avoid conflicts.
-def find_tests(options):
+ We also cache a name -> layer mapping to enable layer_from_name to work
+ in cases where the layer cannot be imported (such as layers defined
+ in doctests)
+ """
+ if layer.__module__ == '__builtin__':
+ name = layer.__name__
+ else:
+ name = layer.__module__ + '.' + layer.__name__
+ _layer_name_cache[name] = layer
+ return name
+
+def find_tests(options, found_suites=None):
+ """Creates a dictionary mapping layer name to a suite of tests to be run
+ in that layer.
+
+ Passing a list of suites using the found_suites parameter will cause
+ that list of suites to be used instead of attempting to load them from
+ the filesystem. This is useful for unit testing the test runner.
+ """
suites = {}
- for suite in find_suites(options):
+ if found_suites is None:
+ found_suites = find_suites(options)
+ for suite in found_suites:
for test, layer_name in tests_from_suite(suite, options):
suite = suites.get(layer_name)
if not suite:
@@ -960,10 +1000,20 @@
return suites
def tests_from_suite(suite, options, dlevel=1, dlayer='unit'):
+ """Returns a sequence of (test, layer_name)
+
+ The tree of suites is recursively visited, with the most specific
+ layer taking precidence. So if a TestCase with a layer of 'foo' is
+ contained in a TestSuite with a layer of 'bar', the test case would be
+ returned with 'foo' as the layer.
+
+ Tests are also filtered out based on the test level and test selection
+ filters stored in the options.
+ """
level = getattr(suite, 'level', dlevel)
layer = getattr(suite, 'layer', dlayer)
if not isinstance(layer, basestring):
- layer = layer.__module__ + '.' + layer.__name__
+ layer = name_from_layer(layer)
if isinstance(suite, unittest.TestSuite):
for possible_suite in suite:
More information about the Zope3-Checkins
mailing list