Merge lp:~jml/subunit/move-ls into lp:~subunit/subunit/trunk

Proposed by Jonathan Lange
Status: Merged
Approved by: Jelmer Vernooij
Approved revision: 134
Merged at revision: 132
Proposed branch: lp:~jml/subunit/move-ls
Merge into: lp:~subunit/subunit/trunk
Diff against target: 214 lines (+63/-64)
2 files modified
filters/subunit-ls (+1/-50)
python/subunit/test_results.py (+62/-14)
To merge this branch: bzr merge lp:~jml/subunit/move-ls
Reviewer Review Type Date Requested Status
Jelmer Vernooij Approve
Review via email: mp+31769@code.launchpad.net

Commit message

Move subunit-ls guts into subunit.test_results

Description of the change

This moves the code with the logic for subunit-ls out of the binary and into subunit.test_results, where it can be imported from and re-used in other Python applications.

To post a comment you must log in.
Revision history for this message
Jelmer Vernooij (jelmer) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'filters/subunit-ls'
--- filters/subunit-ls 2009-09-30 12:04:18 +0000
+++ filters/subunit-ls 2010-08-04 17:10:55 +0000
@@ -18,58 +18,9 @@
1818
19from optparse import OptionParser19from optparse import OptionParser
20import sys20import sys
21import unittest
2221
23from subunit import DiscardStream, ProtocolTestCase22from subunit import DiscardStream, ProtocolTestCase
2423from subunit.test_results import TestIdPrintingResult
25class TestIdPrintingResult(unittest.TestResult):
26
27 def __init__(self, stream, show_times=False):
28 """Create a FilterResult object outputting to stream."""
29 unittest.TestResult.__init__(self)
30 self._stream = stream
31 self.failed_tests = 0
32 self.__time = 0
33 self.show_times = show_times
34 self._test = None
35 self._test_duration = 0
36
37 def addError(self, test, err):
38 self.failed_tests += 1
39 self._test = test
40
41 def addFailure(self, test, err):
42 self.failed_tests += 1
43 self._test = test
44
45 def addSuccess(self, test):
46 self._test = test
47
48 def reportTest(self, test, duration):
49 if self.show_times:
50 seconds = duration.seconds
51 seconds += duration.days * 3600 * 24
52 seconds += duration.microseconds / 1000000.0
53 self._stream.write(test.id() + ' %0.3f\n' % seconds)
54 else:
55 self._stream.write(test.id() + '\n')
56
57 def startTest(self, test):
58 self._start_time = self._time()
59
60 def stopTest(self, test):
61 test_duration = self._time() - self._start_time
62 self.reportTest(self._test, test_duration)
63
64 def time(self, time):
65 self.__time = time
66
67 def _time(self):
68 return self.__time
69
70 def wasSuccessful(self):
71 "Tells whether or not this result was a success"
72 return self.failed_tests == 0
7324
7425
75parser = OptionParser(description=__doc__)26parser = OptionParser(description=__doc__)
7627
=== modified file 'python/subunit/test_results.py'
--- python/subunit/test_results.py 2010-03-11 21:12:10 +0000
+++ python/subunit/test_results.py 2010-08-04 17:10:55 +0000
@@ -6,7 +6,7 @@
6# license at the users choice. A copy of both licenses are available in the6# license at the users choice. A copy of both licenses are available in the
7# project source as Apache-2.0 and BSD. You may not use this file except in7# project source as Apache-2.0 and BSD. You may not use this file except in
8# compliance with one of these two licences.8# compliance with one of these two licences.
9# 9#
10# Unless required by applicable law or agreed to in writing, software10# Unless required by applicable law or agreed to in writing, software
11# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT11# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -21,16 +21,14 @@
21import iso860121import iso8601
22import testtools22import testtools
2323
24import subunit
25
2624
27# NOT a TestResult, because we are implementing the interface, not inheriting25# NOT a TestResult, because we are implementing the interface, not inheriting
28# it.26# it.
29class TestResultDecorator(object):27class TestResultDecorator(object):
30 """General pass-through decorator.28 """General pass-through decorator.
3129
32 This provides a base that other TestResults can inherit from to 30 This provides a base that other TestResults can inherit from to
33 gain basic forwarding functionality. It also takes care of 31 gain basic forwarding functionality. It also takes care of
34 handling the case where the target doesn't support newer methods32 handling the case where the target doesn't support newer methods
35 or features by degrading them.33 or features by degrading them.
36 """34 """
@@ -201,11 +199,11 @@
201 """A pyunit TestResult interface implementation which filters tests.199 """A pyunit TestResult interface implementation which filters tests.
202200
203 Tests that pass the filter are handed on to another TestResult instance201 Tests that pass the filter are handed on to another TestResult instance
204 for further processing/reporting. To obtain the filtered results, 202 for further processing/reporting. To obtain the filtered results,
205 the other instance must be interrogated.203 the other instance must be interrogated.
206204
207 :ivar result: The result that tests are passed to after filtering.205 :ivar result: The result that tests are passed to after filtering.
208 :ivar filter_predicate: The callback run to decide whether to pass 206 :ivar filter_predicate: The callback run to decide whether to pass
209 a result.207 a result.
210 """208 """
211209
@@ -213,7 +211,7 @@
213 filter_success=True, filter_skip=False,211 filter_success=True, filter_skip=False,
214 filter_predicate=None):212 filter_predicate=None):
215 """Create a FilterResult object filtering to result.213 """Create a FilterResult object filtering to result.
216 214
217 :param filter_error: Filter out errors.215 :param filter_error: Filter out errors.
218 :param filter_failure: Filter out failures.216 :param filter_failure: Filter out failures.
219 :param filter_success: Filter out successful tests.217 :param filter_success: Filter out successful tests.
@@ -238,9 +236,9 @@
238 self._current_test_filtered = None236 self._current_test_filtered = None
239 # The (new, gone) tags for the current test.237 # The (new, gone) tags for the current test.
240 self._current_test_tags = None238 self._current_test_tags = None
241 239
242 def addError(self, test, err=None, details=None):240 def addError(self, test, err=None, details=None):
243 if (not self._filter_error and 241 if (not self._filter_error and
244 self.filter_predicate(test, 'error', err, details)):242 self.filter_predicate(test, 'error', err, details)):
245 self.decorated.startTest(test)243 self.decorated.startTest(test)
246 self.decorated.addError(test, err, details=details)244 self.decorated.addError(test, err, details=details)
@@ -288,17 +286,17 @@
288286
289 def startTest(self, test):287 def startTest(self, test):
290 """Start a test.288 """Start a test.
291 289
292 Not directly passed to the client, but used for handling of tags290 Not directly passed to the client, but used for handling of tags
293 correctly.291 correctly.
294 """292 """
295 self._current_test = test293 self._current_test = test
296 self._current_test_filtered = False294 self._current_test_filtered = False
297 self._current_test_tags = set(), set()295 self._current_test_tags = set(), set()
298 296
299 def stopTest(self, test):297 def stopTest(self, test):
300 """Stop a test.298 """Stop a test.
301 299
302 Not directly passed to the client, but used for handling of tags300 Not directly passed to the client, but used for handling of tags
303 correctly.301 correctly.
304 """302 """
@@ -316,7 +314,7 @@
316314
317 Adds and removes tags as appropriate. If a test is currently running,315 Adds and removes tags as appropriate. If a test is currently running,
318 tags are not affected for subsequent tests.316 tags are not affected for subsequent tests.
319 317
320 :param new_tags: Tags to add,318 :param new_tags: Tags to add,
321 :param gone_tags: Tags to remove.319 :param gone_tags: Tags to remove.
322 """320 """
@@ -332,3 +330,53 @@
332 if id.startswith("subunit.RemotedTestCase."):330 if id.startswith("subunit.RemotedTestCase."):
333 return id[len("subunit.RemotedTestCase."):]331 return id[len("subunit.RemotedTestCase."):]
334 return id332 return id
333
334
335class TestIdPrintingResult(testtools.TestResult):
336
337 def __init__(self, stream, show_times=False):
338 """Create a FilterResult object outputting to stream."""
339 testtools.TestResult.__init__(self)
340 self._stream = stream
341 self.failed_tests = 0
342 self.__time = 0
343 self.show_times = show_times
344 self._test = None
345 self._test_duration = 0
346
347 def addError(self, test, err):
348 self.failed_tests += 1
349 self._test = test
350
351 def addFailure(self, test, err):
352 self.failed_tests += 1
353 self._test = test
354
355 def addSuccess(self, test):
356 self._test = test
357
358 def reportTest(self, test, duration):
359 if self.show_times:
360 seconds = duration.seconds
361 seconds += duration.days * 3600 * 24
362 seconds += duration.microseconds / 1000000.0
363 self._stream.write(test.id() + ' %0.3f\n' % seconds)
364 else:
365 self._stream.write(test.id() + '\n')
366
367 def startTest(self, test):
368 self._start_time = self._time()
369
370 def stopTest(self, test):
371 test_duration = self._time() - self._start_time
372 self.reportTest(self._test, test_duration)
373
374 def time(self, time):
375 self.__time = time
376
377 def _time(self):
378 return self.__time
379
380 def wasSuccessful(self):
381 "Tells whether or not this result was a success"
382 return self.failed_tests == 0

Subscribers

People subscribed via source and target branches