Merge lp:~lifeless/subunit/progress-gtk into lp:~subunit/subunit/trunk

Proposed by Robert Collins
Status: Superseded
Proposed branch: lp:~lifeless/subunit/progress-gtk
Merge into: lp:~subunit/subunit/trunk
Diff against target: None lines
To merge this branch: bzr merge lp:~lifeless/subunit/progress-gtk
Reviewer Review Type Date Requested Status
Subunit Developers Pending
Review via email: mp+9418@code.launchpad.net

This proposal has been superseded by a proposal from 2009-07-30.

To post a comment you must log in.
Revision history for this message
Robert Collins (lifeless) wrote :

This builds on progress-core to do a GTK progress bar. Woo. Shiny.

lp:~lifeless/subunit/progress-gtk updated
76. By Robert Collins

Handle python 2.5 a bit better in subunit2gtk.

77. By Robert Collins

Fix gtk support more.

78. By Robert Collins

Fix returning None from gobject IO callbacks.

Unmerged revisions

78. By Robert Collins

Fix returning None from gobject IO callbacks.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'NEWS'
--- NEWS 2009-07-22 09:39:00 +0000
+++ NEWS 2009-07-29 09:59:36 +0000
@@ -10,10 +10,26 @@
1010
11 IMPROVEMENTS:11 IMPROVEMENTS:
1212
13 * Subunit streams can now include optional, incremental lookahead
14 information about progress. This allows reporters to make estimates
15 about completion, when such information is available. See the README
16 under ``progress`` for more details.
17
18 * ``subunit2gtk`` has been added, a filter that shows a GTK summary of a
19 test stream.
20
21 * ``subunit2pyunit`` has a --progress flag which will cause the bzrlib
22 test reporter to be used, which has a textual progress bar. This requires
23 a recent bzrlib as a minor bugfix was required in bzrlib to support this.
24
13 BUG FIXES:25 BUG FIXES:
1426
15 API CHANGES:27 API CHANGES:
1628
29 * When a progress: directive is encountered in a subunit stream, the
30 python bindings now call the ``progress(offset, whence)`` methd on
31 ``TestResult``.
32
17 * When a time: directive is encountered in a subunit stream, the python33 * When a time: directive is encountered in a subunit stream, the python
18 bindings now call the ``time(seconds)`` method on ``TestResult``.34 bindings now call the ``time(seconds)`` method on ``TestResult``.
1935
2036
=== modified file 'README'
--- README 2009-07-22 09:39:00 +0000
+++ README 2009-07-29 09:59:36 +0000
@@ -47,6 +47,7 @@
47Subunit supplies the following filters:47Subunit supplies the following filters:
48 * tap2subunit - convert perl's TestAnythingProtocol to subunit.48 * tap2subunit - convert perl's TestAnythingProtocol to subunit.
49 * subunit2pyunit - convert a subunit stream to pyunit test results.49 * subunit2pyunit - convert a subunit stream to pyunit test results.
50 * subunit2gtk - show a subunit stream in GTK.
50 * subunit-filter - filter out tests from a subunit stream.51 * subunit-filter - filter out tests from a subunit stream.
51 * subunit-ls - list info about tests present in a subunit stream.52 * subunit-ls - list info about tests present in a subunit stream.
52 * subunit-stats - generate a summary of a subunit stream.53 * subunit-stats - generate a summary of a subunit stream.
@@ -130,12 +131,17 @@
130 # needed and report to your result object.131 # needed and report to your result object.
131 suite.run(result)132 suite.run(result)
132133
133subunit includes extensions to the python ``TestResult`` protocol. The134subunit includes extensions to the python ``TestResult`` protocol.
134``time(a_datetime)`` method is called (if present) when a ``time:``135
136The ``time(a_datetime)`` method is called (if present) when a ``time:``
135directive is encountered in a subunit stream. This is used to tell a TestResult137directive is encountered in a subunit stream. This is used to tell a TestResult
136about the time that events in the stream occured at, to allow reconstructing138about the time that events in the stream occured at, to allow reconstructing
137test timing from a stream.139test timing from a stream.
138140
141The ``progress(offset, whence)`` method controls progress data for a stream.
142The offset parameter is an int, and whence is one of subunit.SEEK_CUR,
143subunit.SEEK_SET.
144
139Finally, subunit.run is a convenience wrapper to run a python test suite via145Finally, subunit.run is a convenience wrapper to run a python test suite via
140the command line, reporting via subunit::146the command line, reporting via subunit::
141147
@@ -216,10 +222,12 @@
216xfail[:] test label222xfail[:] test label
217xfail[:] test label [223xfail[:] test label [
218]224]
225progress: [+|-]X
219tags: [-]TAG ...226tags: [-]TAG ...
220time: YYYY-MM-DD HH:MM:SSZ227time: YYYY-MM-DD HH:MM:SSZ
221unexpected output on stdout -> stdout.228unexpected output on stdout -> stdout.
222exit w/0 or last test -> error229exit w/0 or last test completing -> error
230
223Tags given outside a test are applied to all following tests231Tags given outside a test are applied to all following tests
224Tags given after a test: line and before the result line for the same test232Tags given after a test: line and before the result line for the same test
225apply only to that test, and inheric the current global tags.233apply only to that test, and inheric the current global tags.
@@ -228,7 +236,19 @@
228In Python, tags are assigned to the .tags attribute on the RemoteTest objects236In Python, tags are assigned to the .tags attribute on the RemoteTest objects
229created by the TestProtocolServer.237created by the TestProtocolServer.
230238
231The time element acts as a clock event - it sets the time for all future239The progress directive is used to provide progress information about a stream
240so that stream consumer can provide completion estimates, progress bars and so
241on. Stream generators that know how many tests will be present in the stream
242should output "progress: COUNT". Stream filters that add tests should output
243"progress: +COUNT", and those that remove tests should output
244"progress: -COUNT". An absolute count should reset the progress indicators in
245use - it indicates that two separate streams from different generators have
246been trivially concatenated together, and there is no knowledge of how many
247more complete streams are incoming. Smart concatenation could scan each stream
248for their count and sum them, or alternatively translate absolute counts into
249relative counts inline.
250
251The time directive acts as a clock event - it sets the time for all future
232events. The value should be a valid ISO8601 time.252events. The value should be a valid ISO8601 time.
233253
234The skip result is used to indicate a test that was found by the runner but not254The skip result is used to indicate a test that was found by the runner but not
235255
=== added file 'filters/subunit2gtk'
--- filters/subunit2gtk 1970-01-01 00:00:00 +0000
+++ filters/subunit2gtk 2009-07-29 09:59:36 +0000
@@ -0,0 +1,229 @@
1#!/usr/bin/env python
2# subunit: extensions to python unittest to get test results from subprocesses.
3# Copyright (C) 2009 Robert Collins <robertc@robertcollins.net>
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write to the Free Software
17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18#
19
20### The GTK progress bar __init__ function is derived from the pygtk tutorial:
21# The PyGTK Tutorial is Copyright (C) 2001-2005 John Finlay.
22#
23# The GTK Tutorial is Copyright (C) 1997 Ian Main.
24#
25# Copyright (C) 1998-1999 Tony Gale.
26#
27# Permission is granted to make and distribute verbatim copies of this manual
28# provided the copyright notice and this permission notice are preserved on all
29# copies.
30#
31# Permission is granted to copy and distribute modified versions of this
32# document under the conditions for verbatim copying, provided that this
33# copyright notice is included exactly as in the original, and that the entire
34# resulting derived work is distributed under the terms of a permission notice
35# identical to this one.
36#
37# Permission is granted to copy and distribute translations of this document
38# into another language, under the above conditions for modified versions.
39#
40# If you are intending to incorporate this document into a published work,
41# please contact the maintainer, and we will make an effort to ensure that you
42# have the most up to date information available.
43#
44# There is no guarantee that this document lives up to its intended purpose.
45# This is simply provided as a free resource. As such, the authors and
46# maintainers of the information provided within can not make any guarantee
47# that the information is even accurate.
48
49"""Display a subunit stream in a gtk progress window."""
50
51import os
52import sys
53import unittest
54
55import pygtk
56pygtk.require('2.0')
57import gtk, gtk.gdk, gobject
58
59from subunit import ProtocolTestCase, TestProtocolServer
60
61class GTKTestResult(unittest.TestResult):
62
63 def __init__(self):
64 super(GTKTestResult, self).__init__()
65 # Instance variables (in addition to TestResult)
66 self.window = None
67 self.run_label = None
68 self.ok_label = None
69 self.not_ok_label = None
70 self.total_tests = None
71
72 self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
73 self.window.set_resizable(True)
74
75 self.window.connect("destroy", gtk.main_quit)
76 self.window.set_title("Tests...")
77 self.window.set_border_width(0)
78
79 vbox = gtk.VBox(False, 5)
80 vbox.set_border_width(10)
81 self.window.add(vbox)
82 vbox.show()
83
84 # Create a centering alignment object
85 align = gtk.Alignment(0.5, 0.5, 0, 0)
86 vbox.pack_start(align, False, False, 5)
87 align.show()
88
89 # Create the ProgressBar
90 self.pbar = gtk.ProgressBar()
91 align.add(self.pbar)
92 self.pbar.set_text("Running")
93 self.pbar.show()
94
95 separator = gtk.HSeparator()
96 vbox.pack_start(separator, False, False, 0)
97 separator.show()
98
99 # rows, columns, homogeneous
100 table = gtk.Table(2, 3, False)
101 vbox.pack_start(table, False, True, 0)
102 table.show()
103 # Show summary details about the run. Could use an expander.
104 label = gtk.Label("Run:")
105 table.attach(label, 0, 1, 1, 2, gtk.EXPAND | gtk.FILL,
106 gtk.EXPAND | gtk.FILL, 5, 5)
107 label.show()
108 self.run_label = gtk.Label("N/A")
109 table.attach(self.run_label, 1, 2, 1, 2, gtk.EXPAND | gtk.FILL,
110 gtk.EXPAND | gtk.FILL, 5, 5)
111 self.run_label.show()
112
113 label = gtk.Label("OK:")
114 table.attach(label, 0, 1, 2, 3, gtk.EXPAND | gtk.FILL,
115 gtk.EXPAND | gtk.FILL, 5, 5)
116 label.show()
117 self.ok_label = gtk.Label("N/A")
118 table.attach(self.ok_label, 1, 2, 2, 3, gtk.EXPAND | gtk.FILL,
119 gtk.EXPAND | gtk.FILL, 5, 5)
120 self.ok_label.show()
121
122 label = gtk.Label("Not OK:")
123 table.attach(label, 0, 1, 3, 4, gtk.EXPAND | gtk.FILL,
124 gtk.EXPAND | gtk.FILL, 5, 5)
125 label.show()
126 self.not_ok_label = gtk.Label("N/A")
127 table.attach(self.not_ok_label, 1, 2, 3, 4, gtk.EXPAND | gtk.FILL,
128 gtk.EXPAND | gtk.FILL, 5, 5)
129 self.not_ok_label.show()
130
131 self.window.show()
132 # For the demo.
133 self.window.set_keep_above(True)
134 self.window.present()
135
136 def stopTest(self, test):
137 super(GTKTestResult, self).stopTest(test)
138 if not self.total_tests:
139 self.pbar.pulse()
140 else:
141 self.pbar.set_fraction(self.testsRun/float(self.total_tests))
142
143 def stopTestRun(self):
144 try:
145 super(GTKTestResult, self).stopTestRun()
146 except AttributeError:
147 pass
148 self.pbar.set_text('Finished')
149
150 def addError(self, test, err):
151 super(GTKTestResult, self).addError(test, err)
152 self.update_counts()
153
154 def addFailure(self, test, err):
155 super(GTKTestResult, self).addFailure(test, err)
156 self.update_counts()
157
158 def addSuccess(self, test):
159 super(GTKTestResult, self).addSuccess(test)
160 self.update_counts()
161
162 def addSkip(self, test, reason):
163 super(GTKTestResult, self).addSkipSuccess(test, reason)
164 self.update_counts()
165
166 def addExpectedFailure(self, test, err):
167 super(GTKTestResult, self).addExpectedFailure(test, err)
168 self.update_counts()
169
170 def addUnexpectedSuccess(self, test):
171 super(GTKTestResult, self).addUnexpectedSuccess(test)
172 self.update_counts()
173
174 def progress(self, offset, whence):
175 if whence == os.SEEK_SET:
176 self.total_tests = offset
177 else:
178 self.total_tests += offset
179
180 def time(self, a_datetime):
181 # We don't try to estimate completion yet.
182 pass
183
184 def update_counts(self):
185 self.run_label.set_text(str(self.testsRun))
186 bad = len(self.failures + self.errors)
187 self.ok_label.set_text(str(self.testsRun - bad))
188 self.not_ok_label.set_text(str(bad))
189
190
191class GIOProtocolTestCase(object):
192
193 def __init__(self, stream, result, on_finish):
194 self.stream = stream
195 self.schedule_read()
196 self.hup_id = gobject.io_add_watch(stream, gobject.IO_HUP, self.hup)
197 self.protocol = TestProtocolServer(result)
198 self.on_finish = on_finish
199
200 def read(self, source, condition):
201 #NB: \o/ actually blocks
202 line = source.readline()
203 if not line:
204 self.protocol.lostConnection()
205 self.on_finish()
206 return False
207 self.protocol.lineReceived(line)
208 # schedule more IO shortly - if we say we're willing to do it
209 # immediately we starve things.
210 source_id = gobject.timeout_add(1, self.schedule_read)
211 return False
212
213 def schedule_read(self):
214 self.read_id = gobject.io_add_watch(self.stream, gobject.IO_IN, self.read)
215
216 def hup(self, source, condition):
217 self.protocol.lostConnection()
218 gobject.remove(self.read_id)
219 self.on_finish()
220
221
222result = GTKTestResult()
223test = GIOProtocolTestCase(sys.stdin, result, result.stopTestRun)
224gtk.main()
225if result.wasSuccessful():
226 exit_code = 0
227else:
228 exit_code = 1
229sys.exit(exit_code)
0230
=== modified file 'filters/subunit2pyunit'
--- filters/subunit2pyunit 2009-02-15 11:55:00 +0000
+++ filters/subunit2pyunit 2009-07-28 21:44:28 +0000
@@ -17,15 +17,27 @@
17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18#18#
1919
20"""Filter a subunit stream through python's default unittest test runner."""20"""Display a subunit stream through python's unittest test runner."""
2121
22from optparse import OptionParser
22import sys23import sys
23import unittest24import unittest
2425
25from subunit import ProtocolTestCase, TestProtocolServer26from subunit import ProtocolTestCase, TestProtocolServer
2627
27runner = unittest.TextTestRunner(verbosity=2)28parser = OptionParser(description=__doc__)
29parser.add_option("--progress", action="store_true",
30 help="Use bzrlib's test reporter (requires bzrlib)",
31 default=False)
32(options, args) = parser.parse_args()
28test = ProtocolTestCase(sys.stdin)33test = ProtocolTestCase(sys.stdin)
34if options.progress:
35 from bzrlib.tests import TextTestRunner
36 from bzrlib import ui
37 ui.ui_factory = ui.make_ui_for_terminal(None, sys.stdout, sys.stderr)
38 runner = TextTestRunner()
39else:
40 runner = unittest.TextTestRunner(verbosity=2)
29if runner.run(test).wasSuccessful():41if runner.run(test).wasSuccessful():
30 exit_code = 042 exit_code = 0
31else:43else:
3244
=== modified file 'python/subunit/__init__.py'
--- python/subunit/__init__.py 2009-07-22 08:46:04 +0000
+++ python/subunit/__init__.py 2009-07-28 13:32:10 +0000
@@ -28,6 +28,10 @@
28import iso860128import iso8601
2929
3030
31SEEK_CUR = os.SEEK_CUR
32SEEK_SET = os.SEEK_SET
33
34
31def test_suite():35def test_suite():
32 import subunit.tests36 import subunit.tests
33 return subunit.tests.test_suite()37 return subunit.tests.test_suite()
@@ -200,6 +204,18 @@
200 else:204 else:
201 self.stdOutLineReceived(line)205 self.stdOutLineReceived(line)
202206
207 def _handleProgress(self, offset, line):
208 """Process a progress directive."""
209 line = line[offset:].strip()
210 if line[0] in '+-':
211 whence = SEEK_CUR
212 else:
213 whence = SEEK_SET
214 delta = int(line)
215 progress_method = getattr(self.client, 'progress', None)
216 if callable(progress_method):
217 progress_method(delta, whence)
218
203 def _handleTags(self, offset, line):219 def _handleTags(self, offset, line):
204 """Process a tags command."""220 """Process a tags command."""
205 tags = line[offset:].split()221 tags = line[offset:].split()
@@ -243,6 +259,8 @@
243 self._addError(offset, line)259 self._addError(offset, line)
244 elif cmd == 'failure':260 elif cmd == 'failure':
245 self._addFailure(offset, line)261 self._addFailure(offset, line)
262 elif cmd == 'progress':
263 self._handleProgress(offset, line)
246 elif cmd == 'skip':264 elif cmd == 'skip':
247 self._addSkip(offset, line)265 self._addSkip(offset, line)
248 elif cmd in ('success', 'successful'):266 elif cmd in ('success', 'successful'):
@@ -355,6 +373,21 @@
355 """Mark a test as starting its test run."""373 """Mark a test as starting its test run."""
356 self._stream.write("test: %s\n" % test.id())374 self._stream.write("test: %s\n" % test.id())
357375
376 def progress(self, offset, whence):
377 """Provide indication about the progress/length of the test run.
378
379 :param offset: Information about the number of tests remaining. If
380 whence is SEEK_CUR, then offset increases/decreases the remaining
381 test count. If whence is SEEK_SET, then offset specifies exactly
382 the remaining test count.
383 :param whence: One of SEEK_CUR or SEEK_SET.
384 """
385 if whence == SEEK_CUR and offset > -1:
386 prefix = "+"
387 else:
388 prefix = ""
389 self._stream.write("progress: %s%s\n" % (prefix, offset))
390
358 def time(self, a_datetime):391 def time(self, a_datetime):
359 """Inform the client of the time.392 """Inform the client of the time.
360393
361394
=== modified file 'python/subunit/test_results.py'
--- python/subunit/test_results.py 2009-07-22 23:17:18 +0000
+++ python/subunit/test_results.py 2009-07-28 13:32:10 +0000
@@ -87,6 +87,10 @@
87 self._before_event()87 self._before_event()
88 return self._call_maybe("addUnexpectedSuccess", test)88 return self._call_maybe("addUnexpectedSuccess", test)
8989
90 def progress(self, offset, whence):
91 self._before_event()
92 return self._call_maybe("progress", offset, whence)
93
90 def wasSuccessful(self):94 def wasSuccessful(self):
91 self._before_event()95 self._before_event()
92 return self.decorated.wasSuccessful()96 return self.decorated.wasSuccessful()
@@ -124,6 +128,9 @@
124 time = datetime.datetime.utcnow().replace(tzinfo=iso8601.Utc())128 time = datetime.datetime.utcnow().replace(tzinfo=iso8601.Utc())
125 self._call_maybe("time", time)129 self._call_maybe("time", time)
126130
131 def progress(self, offset, whence):
132 return self._call_maybe("progress", offset, whence)
133
127 @property134 @property
128 def shouldStop(self):135 def shouldStop(self):
129 return self.decorated.shouldStop136 return self.decorated.shouldStop
130137
=== modified file 'python/subunit/tests/test_test_protocol.py'
--- python/subunit/tests/test_test_protocol.py 2009-07-22 08:46:04 +0000
+++ python/subunit/tests/test_test_protocol.py 2009-07-28 13:32:10 +0000
@@ -37,6 +37,7 @@
37 self.skip_calls = []37 self.skip_calls = []
38 self.start_calls = []38 self.start_calls = []
39 self.success_calls = []39 self.success_calls = []
40 self.progress_calls = []
40 self._time = None41 self._time = None
41 super(MockTestProtocolServerClient, self).__init__()42 super(MockTestProtocolServerClient, self).__init__()
4243
@@ -58,6 +59,9 @@
58 def startTest(self, test):59 def startTest(self, test):
59 self.start_calls.append(test)60 self.start_calls.append(test)
6061
62 def progress(self, offset, whence):
63 self.progress_calls.append((offset, whence))
64
61 def time(self, time):65 def time(self, time):
62 self._time = time66 self._time = time
6367
@@ -118,6 +122,11 @@
118 self.assertEqual(protocol.success_calls, [])122 self.assertEqual(protocol.success_calls, [])
119 self.assertEqual(protocol.start_calls, [])123 self.assertEqual(protocol.start_calls, [])
120124
125 def test_progress(self):
126 protocol = MockTestProtocolServerClient()
127 protocol.progress(-1, subunit.SEEK_CUR)
128 self.assertEqual(protocol.progress_calls, [(-1, subunit.SEEK_CUR)])
129
121130
122class TestTestImports(unittest.TestCase):131class TestTestImports(unittest.TestCase):
123132
@@ -710,6 +719,36 @@
710 self.success_quoted_bracket("success:")719 self.success_quoted_bracket("success:")
711720
712721
722class TestTestProtocolServerProgress(unittest.TestCase):
723 """Test receipt of progress: directives."""
724
725 def test_progress_accepted_stdlib(self):
726 # With a stdlib TestResult, progress events are swallowed.
727 self.result = unittest.TestResult()
728 self.stream = StringIO()
729 self.protocol = subunit.TestProtocolServer(self.result,
730 stream=self.stream)
731 self.protocol.lineReceived("progress: 23")
732 self.protocol.lineReceived("progress: -2")
733 self.protocol.lineReceived("progress: +4")
734 self.assertEqual("", self.stream.getvalue())
735
736 def test_progress_accepted_extended(self):
737 # With a progress capable TestResult, progress events are emitted.
738 self.result = MockTestProtocolServerClient()
739 self.stream = StringIO()
740 self.protocol = subunit.TestProtocolServer(self.result,
741 stream=self.stream)
742 self.protocol.lineReceived("progress: 23")
743 self.protocol.lineReceived("progress: -2")
744 self.protocol.lineReceived("progress: +4")
745 self.assertEqual("", self.stream.getvalue())
746 self.assertEqual(
747 [(23, subunit.SEEK_SET), (-2, subunit.SEEK_CUR),
748 (4, subunit.SEEK_CUR)],
749 self.result.progress_calls)
750
751
713class TestTestProtocolServerStreamTags(unittest.TestCase):752class TestTestProtocolServerStreamTags(unittest.TestCase):
714 """Test managing tags on the protocol level."""753 """Test managing tags on the protocol level."""
715754
@@ -1005,6 +1044,18 @@
1005 self.io.getvalue(),1044 self.io.getvalue(),
1006 'skip: %s [\nHas it really?\n]\n' % self.test.id())1045 'skip: %s [\nHas it really?\n]\n' % self.test.id())
10071046
1047 def test_progress_set(self):
1048 self.protocol.progress(23, subunit.SEEK_SET)
1049 self.assertEqual(self.io.getvalue(), 'progress: 23\n')
1050
1051 def test_progress_neg_cur(self):
1052 self.protocol.progress(-23, subunit.SEEK_CUR)
1053 self.assertEqual(self.io.getvalue(), 'progress: -23\n')
1054
1055 def test_progress_pos_cur(self):
1056 self.protocol.progress(23, subunit.SEEK_CUR)
1057 self.assertEqual(self.io.getvalue(), 'progress: +23\n')
1058
1008 def test_time(self):1059 def test_time(self):
1009 # Calling time() outputs a time signal immediately.1060 # Calling time() outputs a time signal immediately.
1010 self.protocol.time(1061 self.protocol.time(
10111062
=== modified file 'python/subunit/tests/test_test_results.py'
--- python/subunit/tests/test_test_results.py 2009-07-22 23:17:18 +0000
+++ python/subunit/tests/test_test_results.py 2009-07-28 13:32:10 +0000
@@ -108,6 +108,9 @@
108 def test_addUnexpectedSuccess(self):108 def test_addUnexpectedSuccess(self):
109 self.result.addUnexpectedSuccess(self)109 self.result.addUnexpectedSuccess(self)
110110
111 def test_progress(self):
112 self.result.progress(1, os.SEEK_SET)
113
111 def test_wasSuccessful(self):114 def test_wasSuccessful(self):
112 self.result.wasSuccessful()115 self.result.wasSuccessful()
113116
@@ -135,6 +138,10 @@
135 self.assertEqual(1, len(self.result.decorated._calls))138 self.assertEqual(1, len(self.result.decorated._calls))
136 self.assertNotEqual(None, self.result.decorated._calls[0])139 self.assertNotEqual(None, self.result.decorated._calls[0])
137140
141 def test_no_time_from_progress(self):
142 self.result.progress(1, os.SEEK_CUR)
143 self.assertEqual(0, len(self.result.decorated._calls))
144
138 def test_no_time_from_shouldStop(self):145 def test_no_time_from_shouldStop(self):
139 self.result.decorated.stop()146 self.result.decorated.stop()
140 self.result.shouldStop147 self.result.shouldStop

Subscribers

People subscribed via source and target branches