summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorRobert Collins <robertc@robertcollins.net>2009-07-28 23:32:10 +1000
committerRobert Collins <robertc@robertcollins.net>2009-07-28 23:32:10 +1000
commit7aa495ccf553cf96c04cf2c2419aec8dd7465fac (patch)
tree5b90a06fe9dadb0a5fea1cdb61caaddcb512d575 /python
parent9361b85f6b08a1b0838d157a6b2f427291a06aa7 (diff)
downloadsubunit-git-7aa495ccf553cf96c04cf2c2419aec8dd7465fac.tar.gz
Basic progress support.
Diffstat (limited to 'python')
-rw-r--r--python/subunit/__init__.py33
-rw-r--r--python/subunit/test_results.py7
-rw-r--r--python/subunit/tests/test_test_protocol.py51
-rw-r--r--python/subunit/tests/test_test_results.py7
4 files changed, 98 insertions, 0 deletions
diff --git a/python/subunit/__init__.py b/python/subunit/__init__.py
index 7859ea7..e0a4ccc 100644
--- a/python/subunit/__init__.py
+++ b/python/subunit/__init__.py
@@ -28,6 +28,10 @@ import unittest
import iso8601
+SEEK_CUR = os.SEEK_CUR
+SEEK_SET = os.SEEK_SET
+
+
def test_suite():
import subunit.tests
return subunit.tests.test_suite()
@@ -200,6 +204,18 @@ class TestProtocolServer(object):
else:
self.stdOutLineReceived(line)
+ def _handleProgress(self, offset, line):
+ """Process a progress directive."""
+ line = line[offset:].strip()
+ if line[0] in '+-':
+ whence = SEEK_CUR
+ else:
+ whence = SEEK_SET
+ delta = int(line)
+ progress_method = getattr(self.client, 'progress', None)
+ if callable(progress_method):
+ progress_method(delta, whence)
+
def _handleTags(self, offset, line):
"""Process a tags command."""
tags = line[offset:].split()
@@ -243,6 +259,8 @@ class TestProtocolServer(object):
self._addError(offset, line)
elif cmd == 'failure':
self._addFailure(offset, line)
+ elif cmd == 'progress':
+ self._handleProgress(offset, line)
elif cmd == 'skip':
self._addSkip(offset, line)
elif cmd in ('success', 'successful'):
@@ -355,6 +373,21 @@ class TestProtocolClient(unittest.TestResult):
"""Mark a test as starting its test run."""
self._stream.write("test: %s\n" % test.id())
+ def progress(self, offset, whence):
+ """Provide indication about the progress/length of the test run.
+
+ :param offset: Information about the number of tests remaining. If
+ whence is SEEK_CUR, then offset increases/decreases the remaining
+ test count. If whence is SEEK_SET, then offset specifies exactly
+ the remaining test count.
+ :param whence: One of SEEK_CUR or SEEK_SET.
+ """
+ if whence == SEEK_CUR and offset > -1:
+ prefix = "+"
+ else:
+ prefix = ""
+ self._stream.write("progress: %s%s\n" % (prefix, offset))
+
def time(self, a_datetime):
"""Inform the client of the time.
diff --git a/python/subunit/test_results.py b/python/subunit/test_results.py
index 0a87ba6..a5811aa 100644
--- a/python/subunit/test_results.py
+++ b/python/subunit/test_results.py
@@ -87,6 +87,10 @@ class HookedTestResultDecorator(object):
self._before_event()
return self._call_maybe("addUnexpectedSuccess", test)
+ def progress(self, offset, whence):
+ self._before_event()
+ return self._call_maybe("progress", offset, whence)
+
def wasSuccessful(self):
self._before_event()
return self.decorated.wasSuccessful()
@@ -124,6 +128,9 @@ class AutoTimingTestResultDecorator(HookedTestResultDecorator):
time = datetime.datetime.utcnow().replace(tzinfo=iso8601.Utc())
self._call_maybe("time", time)
+ def progress(self, offset, whence):
+ return self._call_maybe("progress", offset, whence)
+
@property
def shouldStop(self):
return self.decorated.shouldStop
diff --git a/python/subunit/tests/test_test_protocol.py b/python/subunit/tests/test_test_protocol.py
index 8124042..5eedbf9 100644
--- a/python/subunit/tests/test_test_protocol.py
+++ b/python/subunit/tests/test_test_protocol.py
@@ -37,6 +37,7 @@ class MockTestProtocolServerClient(object):
self.skip_calls = []
self.start_calls = []
self.success_calls = []
+ self.progress_calls = []
self._time = None
super(MockTestProtocolServerClient, self).__init__()
@@ -58,6 +59,9 @@ class MockTestProtocolServerClient(object):
def startTest(self, test):
self.start_calls.append(test)
+ def progress(self, offset, whence):
+ self.progress_calls.append((offset, whence))
+
def time(self, time):
self._time = time
@@ -118,6 +122,11 @@ class TestMockTestProtocolServer(unittest.TestCase):
self.assertEqual(protocol.success_calls, [])
self.assertEqual(protocol.start_calls, [])
+ def test_progress(self):
+ protocol = MockTestProtocolServerClient()
+ protocol.progress(-1, subunit.SEEK_CUR)
+ self.assertEqual(protocol.progress_calls, [(-1, subunit.SEEK_CUR)])
+
class TestTestImports(unittest.TestCase):
@@ -710,6 +719,36 @@ class TestTestProtocolServerAddSuccess(unittest.TestCase):
self.success_quoted_bracket("success:")
+class TestTestProtocolServerProgress(unittest.TestCase):
+ """Test receipt of progress: directives."""
+
+ def test_progress_accepted_stdlib(self):
+ # With a stdlib TestResult, progress events are swallowed.
+ self.result = unittest.TestResult()
+ self.stream = StringIO()
+ self.protocol = subunit.TestProtocolServer(self.result,
+ stream=self.stream)
+ self.protocol.lineReceived("progress: 23")
+ self.protocol.lineReceived("progress: -2")
+ self.protocol.lineReceived("progress: +4")
+ self.assertEqual("", self.stream.getvalue())
+
+ def test_progress_accepted_extended(self):
+ # With a progress capable TestResult, progress events are emitted.
+ self.result = MockTestProtocolServerClient()
+ self.stream = StringIO()
+ self.protocol = subunit.TestProtocolServer(self.result,
+ stream=self.stream)
+ self.protocol.lineReceived("progress: 23")
+ self.protocol.lineReceived("progress: -2")
+ self.protocol.lineReceived("progress: +4")
+ self.assertEqual("", self.stream.getvalue())
+ self.assertEqual(
+ [(23, subunit.SEEK_SET), (-2, subunit.SEEK_CUR),
+ (4, subunit.SEEK_CUR)],
+ self.result.progress_calls)
+
+
class TestTestProtocolServerStreamTags(unittest.TestCase):
"""Test managing tags on the protocol level."""
@@ -1005,6 +1044,18 @@ class TestTestProtocolClient(unittest.TestCase):
self.io.getvalue(),
'skip: %s [\nHas it really?\n]\n' % self.test.id())
+ def test_progress_set(self):
+ self.protocol.progress(23, subunit.SEEK_SET)
+ self.assertEqual(self.io.getvalue(), 'progress: 23\n')
+
+ def test_progress_neg_cur(self):
+ self.protocol.progress(-23, subunit.SEEK_CUR)
+ self.assertEqual(self.io.getvalue(), 'progress: -23\n')
+
+ def test_progress_pos_cur(self):
+ self.protocol.progress(23, subunit.SEEK_CUR)
+ self.assertEqual(self.io.getvalue(), 'progress: +23\n')
+
def test_time(self):
# Calling time() outputs a time signal immediately.
self.protocol.time(
diff --git a/python/subunit/tests/test_test_results.py b/python/subunit/tests/test_test_results.py
index 2ba9198..4537304 100644
--- a/python/subunit/tests/test_test_results.py
+++ b/python/subunit/tests/test_test_results.py
@@ -108,6 +108,9 @@ class TestHookedTestResultDecorator(unittest.TestCase):
def test_addUnexpectedSuccess(self):
self.result.addUnexpectedSuccess(self)
+ def test_progress(self):
+ self.result.progress(1, os.SEEK_SET)
+
def test_wasSuccessful(self):
self.result.wasSuccessful()
@@ -135,6 +138,10 @@ class TestAutoTimingTestResultDecorator(unittest.TestCase):
self.assertEqual(1, len(self.result.decorated._calls))
self.assertNotEqual(None, self.result.decorated._calls[0])
+ def test_no_time_from_progress(self):
+ self.result.progress(1, os.SEEK_CUR)
+ self.assertEqual(0, len(self.result.decorated._calls))
+
def test_no_time_from_shouldStop(self):
self.result.decorated.stop()
self.result.shouldStop