Rev 133: (bug #623654) omit repeated time() calls. in http://bazaar.launchpad.net/~jameinel/subunit

John Arbash Meinel john at arbash-meinel.com
Wed Aug 25 01:17:20 BST 2010


At http://bazaar.launchpad.net/~jameinel/subunit

------------------------------------------------------------
revno: 133
revision-id: john at arbash-meinel.com-20100825001700-jy0r1lbbol5q5ja2
parent: jml at canonical.com-20100805122920-t6z0viif1x08yu0e
fixes bug(s): https://launchpad.net/bugs/623654
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: subunit
timestamp: Tue 2010-08-24 19:17:00 -0500
message:
  (bug #623654) omit repeated time() calls.
  If we are filtering out a bunch of tests, we should filter out their related time calls.
  We emit a time only if it comes before or after something that isn't a time call.
-------------- next part --------------
=== modified file 'NEWS'
--- a/NEWS	2010-07-02 12:51:46 +0000
+++ b/NEWS	2010-08-25 00:17:00 +0000
@@ -5,6 +5,14 @@
 NEXT (In development)
 ---------------------
 
+IMPROVEMENTS
+~~~~~~~~~~~~
+
+* 'subunit-filter' now only emits time statements if they come just before or
+  just after another action. That way, went filtering out 1k tests, we don't
+  end up with 2k time statements doing nothing.
+  (John Arbash Meinel, #623654)
+
 0.0.6
 -----
 

=== modified file 'python/subunit/test_results.py'
--- a/python/subunit/test_results.py	2010-08-04 17:05:18 +0000
+++ b/python/subunit/test_results.py	2010-08-25 00:17:00 +0000
@@ -87,6 +87,10 @@
     def time(self, a_datetime):
         return self.decorated.time(a_datetime)
 
+    def stopTestRun(self):
+        return self.decorated.stopTestRun()
+
+
 
 class HookedTestResultDecorator(TestResultDecorator):
     """A TestResult which calls a hook on every event."""
@@ -236,10 +240,13 @@
         self._current_test_filtered = None
         # The (new, gone) tags for the current test.
         self._current_test_tags = None
+        self._last_was_time = False
+        self._buffered_time = None
 
     def addError(self, test, err=None, details=None):
         if (not self._filter_error and
             self.filter_predicate(test, 'error', err, details)):
+            self._emitBufferedTime()
             self.decorated.startTest(test)
             self.decorated.addError(test, err, details=details)
         else:
@@ -248,6 +255,7 @@
     def addFailure(self, test, err=None, details=None):
         if (not self._filter_failure and
             self.filter_predicate(test, 'failure', err, details)):
+            self._emitBufferedTime()
             self.decorated.startTest(test)
             self.decorated.addFailure(test, err, details=details)
         else:
@@ -256,6 +264,7 @@
     def addSkip(self, test, reason=None, details=None):
         if (not self._filter_skip and
             self.filter_predicate(test, 'skip', reason, details)):
+            self._emitBufferedTime()
             self.decorated.startTest(test)
             self.decorated.addSkip(test, reason, details=details)
         else:
@@ -264,6 +273,7 @@
     def addSuccess(self, test, details=None):
         if (not self._filter_success and
             self.filter_predicate(test, 'success', None, details)):
+            self._emitBufferedTime()
             self.decorated.startTest(test)
             self.decorated.addSuccess(test, details=details)
         else:
@@ -271,6 +281,7 @@
 
     def addExpectedFailure(self, test, err=None, details=None):
         if self.filter_predicate(test, 'expectedfailure', err, details):
+            self._emitBufferedTime()
             self.decorated.startTest(test)
             return self.decorated.addExpectedFailure(test, err,
                 details=details)
@@ -278,6 +289,7 @@
             self._filtered()
 
     def addUnexpectedSuccess(self, test, details=None):
+        self._emitBufferedTime()
         self.decorated.startTest(test)
         return self.decorated.addUnexpectedSuccess(test, details=details)
 
@@ -330,6 +342,28 @@
         if id.startswith("subunit.RemotedTestCase."):
             return id[len("subunit.RemotedTestCase."):]
         return id
+    
+    def time(self, a_datetime):
+        if self._last_was_time:
+            self._buffered_time = a_datetime
+            return
+        self._last_was_time = True
+        super(TestResultFilter, self).time(a_datetime)
+
+    def _emitBufferedTime(self):
+        """Called before an action call.
+
+        If we have a time call that was buffered, waiting for output, we go
+        ahead and emit it now, and clear the buffers.
+        """
+        self._last_was_time = False
+        if self._buffered_time is not None:
+            super(TestResultFilter, self).time(self._buffered_time)
+            self._buffered_time = None
+
+    def stopTestRun(self):
+        self._emitBufferedTime()
+        super(TestResultFilter, self).stopTestRun()
 
 
 class TestIdPrintingResult(testtools.TestResult):

=== modified file 'python/subunit/tests/test_test_results.py'
--- a/python/subunit/tests/test_test_results.py	2009-12-13 01:59:07 +0000
+++ b/python/subunit/tests/test_test_results.py	2010-08-25 00:17:00 +0000
@@ -193,6 +193,88 @@
         self.assertNotEqual(None, self.decorated._calls[2])
 
 
+class TestTestResultFilter(unittest.TestCase):
+
+    def make_result(self, filter_success=True, filter_failure=False,
+                    filter_error=False, filter_skip=False):
+
+        terminal = TimeCapturingResult()
+        # The result object under test.
+        self.result = subunit.test_results.TestResultFilter(terminal,
+            filter_skip=filter_skip, filter_error=filter_error,
+            filter_failure=filter_failure, filter_success=filter_success)
+        self.decorated = terminal
+        self.cur_time = 0
+
+    def addTime(self):
+        dt = datetime.datetime(2009,10,11,12,13,14,self.cur_time,
+                               iso8601.Utc())
+        self.result.time(dt)
+        self.cur_time += 1
+
+    def make_simple_timing(self, center_call, *args, **kwargs):
+        self.result.startTestRun()
+        self.addTime()
+        self.addTime()
+        center_call(*args, **kwargs)
+        self.addTime()
+        self.addTime()
+        self.result.stopTestRun()
+
+    def test_timing_filtered(self):
+        self.make_result()
+        self.result.startTestRun()
+        for i in xrange(4):
+            self.addTime()
+        self.result.stopTestRun()
+        self.assertEqual(2, len(self.decorated._calls))
+
+    def test_timing_filtered_w_add_success_filtered(self):
+        self.make_result()
+        self.make_simple_timing(self.result.addSuccess, self)
+        # addSuccess defaults to being filtered, so we hide the extra time
+        # calls
+        self.assertEqual(2, len(self.decorated._calls))
+
+    def test_timing_filtered_w_add_success_not_filtered(self):
+        self.make_result(filter_success=False)
+        self.make_simple_timing(self.result.addSuccess, self)
+        # When not filtered, we include the start time, the time before and
+        # after the run, and the stop time.
+        self.assertEqual(4, len(self.decorated._calls))
+
+    def test_timing_filtered_w_add_failure(self):
+        self.make_result()
+        self.make_simple_timing(self.result.addFailure, self, details={})
+        self.assertEqual(4, len(self.decorated._calls))
+
+    def test_timing_filtered_w_add_error(self):
+        self.make_result()
+        self.make_simple_timing(self.result.addError, self, details={})
+        self.assertEqual(4, len(self.decorated._calls))
+
+    def test_timing_filtered_w_add_skip(self):
+        self.make_result(filter_skip=False)
+        self.make_simple_timing(self.result.addSkip, self, 'foo')
+        self.assertEqual(4, len(self.decorated._calls))
+
+    def test_timing_filtered_w_add_expected_failure(self):
+        self.make_result()
+        self.make_simple_timing(self.result.addExpectedFailure, self, 'xfail')
+        self.assertEqual(4, len(self.decorated._calls))
+
+    def test_timing_filtered_w_add_unexpected_success(self):
+        self.make_result()
+        self.make_simple_timing(self.result.addUnexpectedSuccess, self)
+        self.assertEqual(4, len(self.decorated._calls))
+
+    def test_timing_filtered_w_add_unexpected_success(self):
+        self.make_result()
+        self.make_simple_timing(self.result.addUnexpectedSuccess, self)
+        self.assertEqual(4, len(self.decorated._calls))
+
+
+
 def test_suite():
     loader = subunit.tests.TestUtil.TestLoader()
     result = loader.loadTestsFromName(__name__)



More information about the bazaar-commits mailing list