← Back to team overview

testtools-dev team mailing list archive

[Merge] lp:~lifeless/testtools/cleanups into lp:testtools

 

Robert Collins has proposed merging lp:~lifeless/testtools/cleanups into lp:testtools.

Requested reviews:
  testtools developers (testtools-dev)


This will make fixtures better. Yay.
-- 
https://code.launchpad.net/~lifeless/testtools/cleanups/+merge/35907
Your team testtools developers is requested to review the proposed merge of lp:~lifeless/testtools/cleanups into lp:testtools.
=== modified file 'MANUAL'
--- MANUAL	2010-08-03 18:05:03 +0000
+++ MANUAL	2010-09-18 02:14:39 +0000
@@ -42,6 +42,11 @@
         self.addCleanup(foo.unlock)
         ...
 
+Cleanups can also report multiple errors, if appropriate by wrapping them in
+a testtools.MultipleExceptions object::
+
+    raise MultipleExceptions(exc_info1, exc_info2)
+
 
 TestCase.addOnException
 ~~~~~~~~~~~~~~~~~~~~~~~

=== modified file 'NEWS'
--- NEWS	2010-09-17 17:04:02 +0000
+++ NEWS	2010-09-18 02:14:39 +0000
@@ -7,6 +7,10 @@
 Improvements
 ------------
 
+* Cleanups can raise ``testtools.MultipleExceptions`` if they have multiple
+  exceptions to report. For instance, a cleanup which is itself responsible for
+  running several different internal cleanup routines might use this.
+
 * Code duplication between assertEqual and the matcher Equals has been removed.
 
 * In normal circumstances, a TestCase will no longer share details with clones

=== modified file 'testtools/__init__.py'
--- testtools/__init__.py	2010-08-24 16:47:35 +0000
+++ testtools/__init__.py	2010-09-18 02:14:39 +0000
@@ -8,6 +8,7 @@
     'ErrorHolder',
     'ExtendedToOriginalDecorator',
     'iterate_tests',
+    'MultipleExceptions',
     'MultiTestResult',
     'PlaceHolder',
     'TestCase',
@@ -28,6 +29,7 @@
     )
 from testtools.testcase import (
     ErrorHolder,
+    MultipleExceptions,
     PlaceHolder,
     TestCase,
     clone_test_with_new_id,

=== modified file 'testtools/testcase.py'
--- testtools/testcase.py	2010-09-17 06:22:49 +0000
+++ testtools/testcase.py	2010-09-18 02:14:39 +0000
@@ -5,6 +5,7 @@
 __metaclass__ = type
 __all__ = [
     'clone_test_with_new_id',
+    'MultipleExceptions',
     'TestCase',
     'skip',
     'skipIf',
@@ -60,6 +61,13 @@
         """
 
 
+class MultipleExceptions(Exception):
+    """Represents many exceptions raised from some operation.
+
+    :ivar args: The sys.exc_info() tuples for each exception.
+    """
+
+
 class TestCase(unittest.TestCase):
     """Extensions to the basic TestCase.
 
@@ -188,9 +196,14 @@
             except KeyboardInterrupt:
                 raise
             except:
-                exc_info = sys.exc_info()
-                self._report_traceback(exc_info)
-                last_exception = exc_info[1]
+                exceptions = [sys.exc_info()]
+                while exceptions:
+                    exc_info = exceptions.pop()
+                    if exc_info[0] is MultipleExceptions:
+                        exceptions.extend(exc_info[1].args)
+                        continue
+                    self._report_traceback(exc_info)
+                    last_exception = exc_info[1]
         return last_exception
 
     def addCleanup(self, function, *arguments, **keywordArguments):

=== modified file 'testtools/tests/test_testtools.py'
--- testtools/tests/test_testtools.py	2010-09-17 06:22:49 +0000
+++ testtools/tests/test_testtools.py	2010-09-18 02:14:39 +0000
@@ -8,6 +8,7 @@
 
 from testtools import (
     ErrorHolder,
+    MultipleExceptions,
     PlaceHolder,
     TestCase,
     clone_test_with_new_id,
@@ -608,6 +609,27 @@
         self.assertRaises(
             KeyboardInterrupt, self.test.run, self.logging_result)
 
+    def test_all_errors_from_MultipleExceptions_reported(self):
+        # When a MultipleExceptions exception is caught, all the errors are
+        # reported.
+        def raiseMany():
+            try:
+                1/0
+            except Exception:
+                exc_info1 = sys.exc_info()
+            try:
+                1/0
+            except Exception:
+                exc_info2 = sys.exc_info()
+            raise MultipleExceptions(exc_info1, exc_info2)
+        self.test.addCleanup(raiseMany)
+        self.logging_result = ExtendedTestResult()
+        self.test.run(self.logging_result)
+        self.assertEqual(['startTest', 'addError', 'stopTest'],
+            [event[0] for event in self.logging_result._events])
+        self.assertEqual(set(['traceback', 'traceback-1']),
+            set(self.logging_result._events[1][2].keys()))
+
     def test_multipleCleanupErrorsReported(self):
         # Errors from all failing cleanups are reported as separate backtraces.
         self.test.addCleanup(lambda: 1/0)


Follow ups