[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