← Back to team overview

testtools-dev team mailing list archive

[Merge] lp:~jml/testtools/wrap-result-in-concurrent-suite into lp:testtools

 

Jonathan Lange has proposed merging lp:~jml/testtools/wrap-result-in-concurrent-suite into lp:testtools.

Requested reviews:
  testtools committers (testtools-committers)

For more details, see:
https://code.launchpad.net/~jml/testtools/wrap-result-in-concurrent-suite/+merge/101902

>From talking with Benji, it looks like they need to be able to wrap up the per-thread results in ConcurrentTestSuite so that they can tag the tests in those results.  This branch adds a hook. 

Not 100% convinced by this change.
-- 
https://code.launchpad.net/~jml/testtools/wrap-result-in-concurrent-suite/+merge/101902
Your team testtools developers is subscribed to branch lp:testtools.
=== modified file 'testtools/tests/test_testsuite.py'
--- testtools/tests/test_testsuite.py	2011-07-29 17:34:58 +0000
+++ testtools/tests/test_testsuite.py	2012-04-13 12:22:18 +0000
@@ -4,12 +4,14 @@
 
 __metaclass__ = type
 
+import threading
 import unittest
 
 from testtools import (
     ConcurrentTestSuite,
     iterate_tests,
     TestCase,
+    ThreadsafeForwardingResult,
     )
 from testtools.helpers import try_import
 from testtools.testsuite import FixtureSuite
@@ -17,32 +19,53 @@
 
 FunctionFixture = try_import('fixtures.FunctionFixture')
 
+class Sample(TestCase):
+    def __hash__(self):
+        return id(self)
+    def test_method1(self):
+        pass
+    def test_method2(self):
+        pass
 
 class TestConcurrentTestSuiteRun(TestCase):
 
     def test_trivial(self):
         log = []
         result = LoggingResult(log)
-        class Sample(TestCase):
-            def __hash__(self):
-                return id(self)
-
-            def test_method1(self):
-                pass
-            def test_method2(self):
-                pass
         test1 = Sample('test_method1')
         test2 = Sample('test_method2')
         original_suite = unittest.TestSuite([test1, test2])
         suite = ConcurrentTestSuite(original_suite, self.split_suite)
         suite.run(result)
-        # 0 is the timestamp for the first test starting.
+        # log[0] is the timestamp for the first test starting.
         test1 = log[1][1]
         test2 = log[-1][1]
         self.assertIsInstance(test1, Sample)
         self.assertIsInstance(test2, Sample)
         self.assertNotEqual(test1.id(), test2.id())
 
+    def test_wrap_result(self):
+        # ConcurrentTestSuite has a hook for wrapping the per-thread result.
+        wrap_log = []
+        class MyConcurrentSuite(ConcurrentTestSuite):
+            def _wrap_result(self, thread_safe_result, thread_number):
+                wrap_log.append(
+                    (thread_safe_result.result.decorated, thread_number))
+                return thread_safe_result
+        result_log = []
+        result = LoggingResult(result_log)
+        test1 = Sample('test_method1')
+        test2 = Sample('test_method2')
+        original_suite = unittest.TestSuite([test1, test2])
+        suite = MyConcurrentSuite(original_suite, self.split_suite)
+        suite.run(result)
+        self.assertEqual(
+            [(result, 0),
+             (result, 1),
+             ], wrap_log)
+        # Smoke test to make sure everything ran OK.
+        self.assertNotEqual([], result_log)
+
     def split_suite(self, suite):
         tests = list(iterate_tests(suite))
         return tests[0], tests[1]

=== modified file 'testtools/testsuite.py'
--- testtools/testsuite.py	2011-07-26 22:06:46 +0000
+++ testtools/testsuite.py	2012-04-13 12:22:18 +0000
@@ -46,6 +46,10 @@
         super(ConcurrentTestSuite, self).__init__([suite])
         self.make_tests = make_tests
 
+    def _wrap_result(self, thread_safe_result, thread_number):
+        """Override this if you want to wrap the per-thread result."""
+        return thread_safe_result
+
     def run(self, result):
         """Run the tests concurrently.
 
@@ -63,10 +67,10 @@
         try:
             threads = {}
             queue = Queue()
-            result_semaphore = threading.Semaphore(1)
-            for test in tests:
-                process_result = testtools.ThreadsafeForwardingResult(result,
-                    result_semaphore)
+            semaphore = threading.Semaphore(1)
+            for i, test in enumerate(tests):
+                process_result = self._wrap_result(
+                    testtools.ThreadsafeForwardingResult(result, semaphore), i)
                 reader_thread = threading.Thread(
                     target=self._run_test, args=(test, process_result, queue))
                 threads[test] = reader_thread, process_result


Follow ups