[Zope3-checkins]
SVN: zope.testing/branches/ctheune-cleanup/src/zope/testing/testrunner/
Moved the code to actually find and run tests into the runner class.
Christian Theune
ct at gocept.com
Sat May 3 12:36:54 EDT 2008
Log message for revision 86254:
Moved the code to actually find and run tests into the runner class.
Changed:
U zope.testing/branches/ctheune-cleanup/src/zope/testing/testrunner/__init__.py
U zope.testing/branches/ctheune-cleanup/src/zope/testing/testrunner/runner.py
U zope.testing/branches/ctheune-cleanup/src/zope/testing/testrunner/testrunner-layers-api.txt
-=-
Modified: zope.testing/branches/ctheune-cleanup/src/zope/testing/testrunner/__init__.py
===================================================================
--- zope.testing/branches/ctheune-cleanup/src/zope/testing/testrunner/__init__.py 2008-05-03 16:23:59 UTC (rev 86253)
+++ zope.testing/branches/ctheune-cleanup/src/zope/testing/testrunner/__init__.py 2008-05-03 16:36:53 UTC (rev 86254)
@@ -22,6 +22,7 @@
from zope.testing.testrunner.runner import Runner
+
def run(defaults=None, args=None):
# This function is here to make the whole test runner compatible before
# the large refactoring.
Modified: zope.testing/branches/ctheune-cleanup/src/zope/testing/testrunner/runner.py
===================================================================
--- zope.testing/branches/ctheune-cleanup/src/zope/testing/testrunner/runner.py 2008-05-03 16:23:59 UTC (rev 86253)
+++ zope.testing/branches/ctheune-cleanup/src/zope/testing/testrunner/runner.py 2008-05-03 16:36:53 UTC (rev 86254)
@@ -70,11 +70,18 @@
"""
- def __init__(self, defaults=None, args=None):
+ def __init__(self, defaults=None, args=None, found_suites=None,
+ options=None):
self.defaults = defaults
self.args = args
+ self.found_suites = found_suites
+ self.options = options
def run(self):
+ self.configure()
+ self.setup_features()
+ self.shutdown_features()
+
args = self.args
defaults = self.defaults
@@ -150,7 +157,9 @@
try:
try:
- failed = not run_with_options(options)
+ self.options = options
+ self.find_tests()
+ failed = self.run_tests()
except EndRun:
failed = True
finally:
@@ -181,7 +190,197 @@
return failed
+ def configure(self):
+ pass
+ def setup_features(self):
+ pass
+
+ def find_tests(self):
+ pass
+
+ def run_tests(self):
+ """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 there where failures or False if all tests passed.
+
+ """
+ options = self.options
+ found_suites = self.found_suites
+
+ global _layer_name_cache
+ _layer_name_cache.clear() # Reset to enforce test isolation
+
+ output = options.output
+
+ if options.resume_layer:
+ original_stderr = sys.stderr
+ sys.stderr = sys.stdout
+ elif options.verbose:
+ if options.all:
+ msg = "Running tests at all levels"
+ else:
+ msg = "Running tests at level %d" % options.at_level
+ output.info(msg)
+
+ old_threshold = gc.get_threshold()
+ if options.gc:
+ if len(options.gc) > 3:
+ output.error("Too many --gc options")
+ sys.exit(1)
+ if options.gc[0]:
+ output.info("Cyclic garbage collection threshold set to: %s" %
+ repr(tuple(options.gc)))
+ else:
+ output.info("Cyclic garbage collection is disabled.")
+
+ gc.set_threshold(*options.gc)
+
+ old_flags = gc.get_debug()
+ if options.gc_option:
+ new_flags = 0
+ for op in options.gc_option:
+ new_flags |= getattr(gc, op)
+ gc.set_debug(new_flags)
+
+ old_reporting_flags = doctest.set_unittest_reportflags(0)
+ reporting_flags = 0
+ if options.ndiff:
+ reporting_flags = doctest.REPORT_NDIFF
+ if options.udiff:
+ if reporting_flags:
+ output.error("Can only give one of --ndiff, --udiff, or --cdiff")
+ sys.exit(1)
+ reporting_flags = doctest.REPORT_UDIFF
+ if options.cdiff:
+ if reporting_flags:
+ output.error("Can only give one of --ndiff, --udiff, or --cdiff")
+ sys.exit(1)
+ reporting_flags = doctest.REPORT_CDIFF
+ if options.report_only_first_failure:
+ reporting_flags |= doctest.REPORT_ONLY_FIRST_FAILURE
+
+ if reporting_flags:
+ doctest.set_unittest_reportflags(reporting_flags)
+ else:
+ doctest.set_unittest_reportflags(old_reporting_flags)
+
+
+ # Add directories to the path
+ for path in options.path:
+ if path not in sys.path:
+ sys.path.append(path)
+
+ tests_by_layer_name = find_tests(options, found_suites)
+
+ ran = 0
+ failures = []
+ errors = []
+ nlayers = 0
+ import_errors = tests_by_layer_name.pop(None, None)
+
+ output.import_errors(import_errors)
+
+ if 'unit' in tests_by_layer_name:
+ tests = tests_by_layer_name.pop('unit')
+ if (not options.non_unit) and not options.resume_layer:
+ if options.layer:
+ should_run = False
+ for pat in options.layer:
+ if pat('unit'):
+ should_run = True
+ break
+ else:
+ should_run = True
+
+ if should_run:
+ if options.list_tests:
+ output.list_of_tests(tests, 'unit')
+ else:
+ output.info("Running unit tests:")
+ nlayers += 1
+ ran += run_tests(options, tests, 'unit', failures, errors)
+
+ setup_layers = {}
+
+ layers_to_run = list(ordered_layers(tests_by_layer_name))
+ if options.resume_layer is not None:
+ layers_to_run = [
+ (layer_name, layer, tests)
+ for (layer_name, layer, tests) in layers_to_run
+ if layer_name == options.resume_layer
+ ]
+ elif options.layer:
+ layers_to_run = [
+ (layer_name, layer, tests)
+ for (layer_name, layer, tests) in layers_to_run
+ if filter(None, [pat(layer_name) for pat in options.layer])
+ ]
+
+
+ if options.list_tests:
+ for layer_name, layer, tests in layers_to_run:
+ output.list_of_tests(tests, layer_name)
+ return False
+
+ start_time = time.time()
+
+ for layer_name, layer, tests in layers_to_run:
+ nlayers += 1
+ try:
+ ran += run_layer(options, layer_name, layer, tests,
+ setup_layers, failures, errors)
+ except CanNotTearDown:
+ setup_layers = None
+ if not options.resume_layer:
+ ran += resume_tests(options, layer_name, layers_to_run,
+ failures, errors)
+ break
+
+ if setup_layers:
+ if options.resume_layer == None:
+ output.info("Tearing down left over layers:")
+ tear_down_unneeded(options, (), setup_layers, True)
+
+ total_time = time.time() - start_time
+
+ if options.resume_layer:
+ sys.stdout.close()
+ # Communicate with the parent. The protocol is obvious:
+ print >> original_stderr, ran, len(failures), len(errors)
+ for test, exc_info in failures:
+ print >> original_stderr, ' '.join(str(test).strip().split('\n'))
+ for test, exc_info in errors:
+ print >> original_stderr, ' '.join(str(test).strip().split('\n'))
+
+ else:
+ if options.verbose:
+ output.tests_with_errors(errors)
+ output.tests_with_failures(failures)
+
+ if nlayers != 1:
+ output.totals(ran, len(failures), len(errors), total_time)
+
+ output.modules_with_import_problems(import_errors)
+
+ doctest.set_unittest_reportflags(old_reporting_flags)
+
+ if options.gc_option:
+ gc.set_debug(old_flags)
+
+ if options.gc:
+ gc.set_threshold(*old_threshold)
+
+ return bool(import_errors or failures or errors)
+
+ def shutdown_features(self):
+ pass
+
+
def run_tests(options, tests, name, failures, errors):
repeat = options.repeat or 1
repeat_range = iter(range(repeat))
@@ -372,184 +571,8 @@
return rantotal
-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.
- """
-
- global _layer_name_cache
- _layer_name_cache.clear() # Reset to enforce test isolation
-
- output = options.output
-
- if options.resume_layer:
- original_stderr = sys.stderr
- sys.stderr = sys.stdout
- elif options.verbose:
- if options.all:
- msg = "Running tests at all levels"
- else:
- msg = "Running tests at level %d" % options.at_level
- output.info(msg)
-
-
- old_threshold = gc.get_threshold()
- if options.gc:
- if len(options.gc) > 3:
- output.error("Too many --gc options")
- sys.exit(1)
- if options.gc[0]:
- output.info("Cyclic garbage collection threshold set to: %s" %
- repr(tuple(options.gc)))
- else:
- output.info("Cyclic garbage collection is disabled.")
-
- gc.set_threshold(*options.gc)
-
- old_flags = gc.get_debug()
- if options.gc_option:
- new_flags = 0
- for op in options.gc_option:
- new_flags |= getattr(gc, op)
- gc.set_debug(new_flags)
-
- old_reporting_flags = doctest.set_unittest_reportflags(0)
- reporting_flags = 0
- if options.ndiff:
- reporting_flags = doctest.REPORT_NDIFF
- if options.udiff:
- if reporting_flags:
- output.error("Can only give one of --ndiff, --udiff, or --cdiff")
- sys.exit(1)
- reporting_flags = doctest.REPORT_UDIFF
- if options.cdiff:
- if reporting_flags:
- output.error("Can only give one of --ndiff, --udiff, or --cdiff")
- sys.exit(1)
- reporting_flags = doctest.REPORT_CDIFF
- if options.report_only_first_failure:
- reporting_flags |= doctest.REPORT_ONLY_FIRST_FAILURE
-
- if reporting_flags:
- doctest.set_unittest_reportflags(reporting_flags)
- else:
- doctest.set_unittest_reportflags(old_reporting_flags)
-
-
- # Add directories to the path
- for path in options.path:
- if path not in sys.path:
- sys.path.append(path)
-
- tests_by_layer_name = find_tests(options, found_suites)
-
- ran = 0
- failures = []
- errors = []
- nlayers = 0
- import_errors = tests_by_layer_name.pop(None, None)
-
- output.import_errors(import_errors)
-
- if 'unit' in tests_by_layer_name:
- tests = tests_by_layer_name.pop('unit')
- if (not options.non_unit) and not options.resume_layer:
- if options.layer:
- should_run = False
- for pat in options.layer:
- if pat('unit'):
- should_run = True
- break
- else:
- should_run = True
-
- if should_run:
- if options.list_tests:
- output.list_of_tests(tests, 'unit')
- else:
- output.info("Running unit tests:")
- nlayers += 1
- ran += run_tests(options, tests, 'unit', failures, errors)
-
- setup_layers = {}
-
- layers_to_run = list(ordered_layers(tests_by_layer_name))
- if options.resume_layer is not None:
- layers_to_run = [
- (layer_name, layer, tests)
- for (layer_name, layer, tests) in layers_to_run
- if layer_name == options.resume_layer
- ]
- elif options.layer:
- layers_to_run = [
- (layer_name, layer, tests)
- for (layer_name, layer, tests) in layers_to_run
- if filter(None, [pat(layer_name) for pat in options.layer])
- ]
-
-
- if options.list_tests:
- for layer_name, layer, tests in layers_to_run:
- output.list_of_tests(tests, layer_name)
- return True
-
- start_time = time.time()
-
- for layer_name, layer, tests in layers_to_run:
- nlayers += 1
- try:
- ran += run_layer(options, layer_name, layer, tests,
- setup_layers, failures, errors)
- except CanNotTearDown:
- setup_layers = None
- if not options.resume_layer:
- ran += resume_tests(options, layer_name, layers_to_run,
- failures, errors)
- break
-
- if setup_layers:
- if options.resume_layer == None:
- output.info("Tearing down left over layers:")
- tear_down_unneeded(options, (), setup_layers, True)
-
- total_time = time.time() - start_time
-
- if options.resume_layer:
- sys.stdout.close()
- # Communicate with the parent. The protocol is obvious:
- print >> original_stderr, ran, len(failures), len(errors)
- for test, exc_info in failures:
- print >> original_stderr, ' '.join(str(test).strip().split('\n'))
- for test, exc_info in errors:
- print >> original_stderr, ' '.join(str(test).strip().split('\n'))
-
- else:
- if options.verbose:
- output.tests_with_errors(errors)
- output.tests_with_failures(failures)
-
- if nlayers != 1:
- output.totals(ran, len(failures), len(errors), total_time)
-
- output.modules_with_import_problems(import_errors)
-
- doctest.set_unittest_reportflags(old_reporting_flags)
-
- if options.gc_option:
- gc.set_debug(old_flags)
-
- if options.gc:
- gc.set_threshold(*old_threshold)
-
- return not bool(import_errors or failures or errors)
-
-
def tear_down_unneeded(options, needed, setup_layers, optional=False):
# Tear down any layers not needed for these tests. The unneeded
# layers might interfere.
Modified: zope.testing/branches/ctheune-cleanup/src/zope/testing/testrunner/testrunner-layers-api.txt
===================================================================
--- zope.testing/branches/ctheune-cleanup/src/zope/testing/testrunner/testrunner-layers-api.txt 2008-05-03 16:23:59 UTC (rev 86253)
+++ zope.testing/branches/ctheune-cleanup/src/zope/testing/testrunner/testrunner-layers-api.txt 2008-05-03 16:36:53 UTC (rev 86254)
@@ -95,7 +95,7 @@
Before we can run the tests, we need to setup some helpers.
->>> from zope.testing.testrunner import runner, options
+>>> from zope.testing.testrunner import options
>>> from zope.testing.loggingsupport import InstalledHandler
>>> import logging
>>> log_handler = InstalledHandler('zope.testing.tests')
@@ -111,7 +111,9 @@
the TestSpecifyingNoLayer was run and setup/torn down around the
TestSpecifyingBaseLayer tests.
->>> succeeded = runner.run_with_options(fresh_options(), [umbrella_suite])
+>>> from zope.testing.testrunner import Runner
+>>> runner = Runner(options=fresh_options(), found_suites=[umbrella_suite])
+>>> succeeded = runner.run_tests()
Running unit tests:
Ran 2 tests with 0 failures and 0 errors in N.NNN seconds.
Set up BaseLayer in N.NNN seconds.
@@ -125,7 +127,8 @@
a layer. This is generally how you specify what layer doctests need.
>>> no_layer_suite.layer = BaseLayer
->>> succeeded = runner.run_with_options(fresh_options(), [umbrella_suite])
+>>> runner = Runner(options=fresh_options(), found_suites=[umbrella_suite])
+>>> succeeded = runner.run_tests()
Set up BaseLayer in N.NNN seconds.
Ran 4 tests with 0 failures and 0 errors in N.NNN seconds.
Tearing down left over layers:
@@ -142,7 +145,8 @@
TestSpecifyingNoLayer tests are run.
>>> TestSpecifyingNoLayer.layer = TopLayer
->>> succeeded = runner.run_with_options(fresh_options(), [umbrella_suite])
+>>> runner = Runner(options=fresh_options(), found_suites=[umbrella_suite])
+>>> succeeded = runner.run_tests()
Set up BaseLayer in N.NNN seconds.
Ran 2 tests with 0 failures and 0 errors in N.NNN seconds.
Set up TopLayer in N.NNN seconds.
@@ -223,7 +227,8 @@
... pass
>>> suite = unittest.makeSuite(DeepTest)
>>> log_handler.clear()
->>> succeeded = runner.run_with_options(fresh_options(), [suite])
+>>> runner = Runner(options=fresh_options(), found_suites=[suite])
+>>> succeeded = runner.run_tests()
Set up A in 0.000 seconds.
Set up B in 0.000 seconds.
Set up C in 0.000 seconds.
More information about the Zope3-Checkins
mailing list