[Zope3-checkins] SVN: zope.testing/trunk/ Fixed bug: post-mortem debugging wasn't working for errors in layer

Jim Fulton jim at zope.com
Tue Aug 14 18:11:05 EDT 2007


Log message for revision 78821:
  Fixed bug: post-mortem debugging wasn't working for errors in layer
  setup.
  

Changed:
  U   zope.testing/trunk/README.txt
  A   zope.testing/trunk/src/zope/testing/testrunner-debugging-layer-setup.test
  U   zope.testing/trunk/src/zope/testing/testrunner.py

-=-
Modified: zope.testing/trunk/README.txt
===================================================================
--- zope.testing/trunk/README.txt	2007-08-14 19:20:39 UTC (rev 78820)
+++ zope.testing/trunk/README.txt	2007-08-14 22:11:05 UTC (rev 78821)
@@ -70,6 +70,14 @@
 
 - Added --no-progress and --auto-progress options.
 
+3.5.1 (2007/08/14)
+==================
+
+Bugs Fixed:
+-----------
+
+- Post-mortem debugging wasn't invoked for layer-setup failures.
+
 3.5.0 (2007/07/19)
 ==================
 

Added: zope.testing/trunk/src/zope/testing/testrunner-debugging-layer-setup.test
===================================================================
--- zope.testing/trunk/src/zope/testing/testrunner-debugging-layer-setup.test	                        (rev 0)
+++ zope.testing/trunk/src/zope/testing/testrunner-debugging-layer-setup.test	2007-08-14 22:11:05 UTC (rev 78821)
@@ -0,0 +1,133 @@
+Post-mortem debugging also works when there is a failure in layer
+setup.
+
+    >>> import os, shutil, sys, tempfile
+    >>> tdir = tempfile.mkdtemp()
+    >>> dir = os.path.join(tdir, 'TESTS-DIR')
+    >>> os.mkdir(dir)
+    >>> open(os.path.join(dir, 'tests.py'), 'w').write(
+    ... '''
+    ... import doctest
+    ...
+    ... class Layer:
+    ...     @classmethod
+    ...     def setUp(self):
+    ...         x = 1
+    ...         raise ValueError
+    ...     
+    ... def a_test():
+    ...     """
+    ...     >>> None
+    ...     """
+    ... def test_suite():
+    ...     suite = doctest.DocTestSuite()
+    ...     suite.layer = Layer
+    ...     return suite
+    ... 
+    ... ''')
+    
+    >>> class Input:
+    ...     def __init__(self, src):
+    ...         self.lines = src.split('\n')
+    ...     def readline(self):
+    ...         line = self.lines.pop(0)
+    ...         print line
+    ...         return line+'\n'
+
+    >>> real_stdin = sys.stdin
+    >>> if sys.version_info[:2] == (2, 3):
+    ...     sys.stdin = Input('n\np x\nc')
+    ... else:
+    ...     sys.stdin = Input('p x\nc')
+
+    >>> sys.argv = [testrunner_script]
+    >>> import zope.testing.testrunner
+    >>> try:
+    ...     zope.testing.testrunner.run(['--path', dir, '-D'])
+    ... finally: sys.stdin = real_stdin
+    ... # doctest: +ELLIPSIS
+    Running tests.Layer tests:
+      Set up tests.Layer exceptions.ValueError:
+    <BLANKLINE>
+    > ...tests.py(8)setUp()
+    -> raise ValueError
+    (Pdb) p x
+    1
+    (Pdb) c
+    True
+
+Note that post-mortem debugging doesn't work when the layer is run in
+a subprocess:
+
+    >>> if sys.version_info[:2] == (2, 3):
+    ...     sys.stdin = Input('n\np x\nc')
+    ... else:
+    ...     sys.stdin = Input('p x\nc')
+
+    >>> open(os.path.join(dir, 'tests2.py'), 'w').write(
+    ... '''
+    ... import doctest, unittest
+    ...
+    ... class Layer1:
+    ...     @classmethod
+    ...     def setUp(self):
+    ...         pass
+    ...
+    ...     @classmethod
+    ...     def tearDown(self):
+    ...         raise NotImplementedError
+    ...
+    ... class Layer2:
+    ...     @classmethod
+    ...     def setUp(self):
+    ...         x = 1
+    ...         raise ValueError
+    ...     
+    ... def a_test():
+    ...     """
+    ...     >>> None
+    ...     """
+    ... def test_suite():
+    ...     suite1 = doctest.DocTestSuite()
+    ...     suite1.layer = Layer1
+    ...     suite2 = doctest.DocTestSuite()
+    ...     suite2.layer = Layer2
+    ...     return unittest.TestSuite((suite1, suite2))
+    ... 
+    ... ''')
+
+    >>> try:
+    ...     zope.testing.testrunner.run(
+    ...       ['--path', dir, '-Dvv', '--tests-pattern', 'tests2'])
+    ... finally: sys.stdin = real_stdin
+    ... # doctest: +ELLIPSIS
+    Running tests at level 1
+    Running tests2.Layer1 tests:
+      Set up tests2.Layer1 in 0.000 seconds.
+      Running:
+     a_test (tests2)
+      Ran 1 tests with 0 failures and 0 errors in 0.001 seconds.
+    Running tests2.Layer2 tests:
+      Tear down tests2.Layer1 ... not supported
+      Running in a subprocess.
+      Set up tests2.Layer2
+    **********************************************************************
+    <BLANKLINE>
+    Can't post-mortem debug when running a layer as a subprocess!
+    Try running layer 'tests2.Layer2' by itself.
+    <BLANKLINE>
+    **********************************************************************
+    <BLANKLINE>
+    Traceback (most recent call last):
+    ...
+        raise ValueError
+    ValueError
+    <BLANKLINE>
+    <BLANKLINE>
+    Tests with errors:
+       runTest (__main__.SetUpLayerFailure)
+    Total: 1 tests, 0 failures, 1 errors in 0.210 seconds.
+    True
+
+    >>> shutil.rmtree(tdir)
+


Property changes on: zope.testing/trunk/src/zope/testing/testrunner-debugging-layer-setup.test
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: zope.testing/trunk/src/zope/testing/testrunner.py
===================================================================
--- zope.testing/trunk/src/zope/testing/testrunner.py	2007-08-14 19:20:39 UTC (rev 78820)
+++ zope.testing/trunk/src/zope/testing/testrunner.py	2007-08-14 22:11:05 UTC (rev 78821)
@@ -19,6 +19,7 @@
 # Too bad: For now, we depend on zope.testing.  This is because
 # we want to use the latest, greatest doctest, which zope.testing
 # provides.  Then again, zope.testing is generally useful.
+
 import gc
 import glob
 import logging
@@ -27,6 +28,7 @@
 import errno
 import pdb
 import re
+import cStringIO
 import sys
 import tempfile
 import threading
@@ -1246,9 +1248,23 @@
     if options.resume_layer != None:
         output.info_suboptimal( "  Running in a subprocess.")
 
-    setup_layer(options, layer, setup_layers)
-    return run_tests(options, tests, layer_name, failures, errors)
+    try:
+        setup_layer(options, layer, setup_layers)
+    except EndRun:
+        raise
+    except Exception:
+        f = cStringIO.StringIO()
+        traceback.print_exc(file=f)
+        output.error(f.getvalue())
+        errors.append((SetUpLayerFailure(), sys.exc_info()))
+        return 0
+    else:
+        return run_tests(options, tests, layer_name, failures, errors)
 
+class SetUpLayerFailure(unittest.TestCase):
+    def runTest(self):
+        "Layer set up failure."
+
 def resume_tests(options, layer_name, layers, failures, errors):
     output = options.output
     layers = [l for (l, _, _) in layers]
@@ -1341,6 +1357,12 @@
             output.stop_tear_down(time.time() - t)
         del setup_layers[l]
 
+
+cant_pm_in_subprocess_message = """
+Can't post-mortem debug when running a layer as a subprocess!
+Try running layer %r by itself.
+"""
+
 def setup_layer(options, layer, setup_layers):
     assert layer is not object
     output = options.output
@@ -1351,7 +1373,20 @@
         output.start_set_up(name_from_layer(layer))
         t = time.time()
         if hasattr(layer, 'setUp'):
-            layer.setUp()
+            try:
+                layer.setUp()
+            except Exception:
+                if options.post_mortem:
+                    if options.resume_layer:
+                        options.output.error_with_banner(
+                            cant_pm_in_subprocess_message
+                            % options.resume_layer)
+                        raise
+                    else:
+                        post_mortem(sys.exc_info())
+                else:
+                    raise
+                    
         output.stop_set_up(time.time() - t)
         setup_layers[layer] = 1
 
@@ -2639,6 +2674,7 @@
         doctest.DocFileSuite(
         'testrunner-arguments.txt',
         'testrunner-coverage.txt',
+        'testrunner-debugging-layer-setup.test',
         'testrunner-debugging.txt',
         'testrunner-edge-cases.txt',
         'testrunner-errors.txt',



More information about the Zope3-Checkins mailing list