Merge lp:~lifeless/subunit/addSkip into lp:~subunit/subunit/trunk

Proposed by Robert Collins
Status: Merged
Approved by: Jonathan Lange
Approved revision: 58
Merged at revision: not available
Proposed branch: lp:~lifeless/subunit/addSkip
Merge into: lp:~subunit/subunit/trunk
Diff against target: None lines
To merge this branch: bzr merge lp:~lifeless/subunit/addSkip
Reviewer Review Type Date Requested Status
Jonathan Lange Approve
Review via email: mp+4033@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Robert Collins (lifeless) wrote :

This includes filters; best to review after that is reviewed. Also when is that getting reviewed ? :)

lp:~lifeless/subunit/addSkip updated
58. By Robert Collins

subunit-filter can now filter skips too.

Revision history for this message
Jonathan Lange (jml) wrote :

Fine to land, along with the tweaks suggested for lp:~lifeless/subunit/filter.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'README'
--- README 2009-02-15 11:55:00 +0000
+++ README 2009-02-28 09:27:25 +0000
@@ -40,6 +40,8 @@
40stream on-the-fly. Currently subunit provides:40stream on-the-fly. Currently subunit provides:
41 * tap2subunit - convert perl's TestAnythingProtocol to subunit.41 * tap2subunit - convert perl's TestAnythingProtocol to subunit.
42 * subunit2pyunit - convert a subunit stream to pyunit test results.42 * subunit2pyunit - convert a subunit stream to pyunit test results.
43 * subunit-filter - filter out tests from a subunit stream.
44 * subunit-ls - list the tests present in a subunit stream.
43 * subunit-stats - generate a summary of a subunit stream.45 * subunit-stats - generate a summary of a subunit stream.
44 * subunit-tags - add or remove tags from a stream.46 * subunit-tags - add or remove tags from a stream.
4547
@@ -200,8 +202,10 @@
200Currently this is not exposed at the python API layer.202Currently this is not exposed at the python API layer.
201203
202The skip result is used to indicate a test that was found by the runner but not204The skip result is used to indicate a test that was found by the runner but not
203fully executed due to some policy or dependency issue. Currently this is205fully executed due to some policy or dependency issue. This is represented in
204represented in Python as a successful test.206python using the addSkip interface that testtools
207(https://edge.launchpad.net/testtools) defines. When communicating with a non
208skip aware test result, the test is reported as an error.
205The xfail result is used to indicate a test that was expected to fail failing209The xfail result is used to indicate a test that was expected to fail failing
206in the expected manner. As this is a normal condition for such tests it is210in the expected manner. As this is a normal condition for such tests it is
207represented as a successful test in Python.211represented as a successful test in Python.
208212
=== added file 'filters/subunit-filter'
--- filters/subunit-filter 1970-01-01 00:00:00 +0000
+++ filters/subunit-filter 2009-02-22 07:51:04 +0000
@@ -0,0 +1,50 @@
1#!/usr/bin/env python
2# subunit: extensions to python unittest to get test results from subprocesses.
3# Copyright (C) 2008 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"""Filter a subunit stream to include/exclude tests.
21
22The default is to strip successful tests.
23"""
24
25from optparse import OptionParser
26import sys
27import unittest
28
29from subunit import ProtocolTestCase, TestResultFilter, TestProtocolClient
30
31parser = OptionParser(description=__doc__)
32parser.add_option("--error", action="store_false",
33 help="include errors", default=False, dest="error")
34parser.add_option("-e", "--no-error", action="store_true",
35 help="exclude errors", dest="error")
36parser.add_option("--failure", action="store_false",
37 help="include failures", default=False, dest="failure")
38parser.add_option("-f", "--no-failure", action="store_true",
39 help="include failures", dest="failure")
40parser.add_option("-s", "--success", action="store_false",
41 help="include successes", dest="success")
42parser.add_option("--no-success", action="store_true",
43 help="exclude successes", default=True, dest="success")
44(options, args) = parser.parse_args()
45result = TestProtocolClient(sys.stdout)
46result = TestResultFilter(result, filter_error=options.error, filter_failure=options.failure,
47 filter_success=options.success)
48test = ProtocolTestCase(sys.stdin)
49test.run(result)
50sys.exit(0)
051
=== added file 'filters/subunit-ls'
--- filters/subunit-ls 1970-01-01 00:00:00 +0000
+++ filters/subunit-ls 2009-02-23 10:54:28 +0000
@@ -0,0 +1,62 @@
1#!/usr/bin/env python
2# subunit: extensions to python unittest to get test results from subprocesses.
3# Copyright (C) 2008 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"""List tests in a subunit stream."""
21
22import sys
23import unittest
24
25from subunit import ProtocolTestCase
26
27class FilterResult(unittest.TestResult):
28 """Filter test objects for display."""
29
30 def __init__(self, stream):
31 """Create a FilterResult object outputting to stream."""
32 unittest.TestResult.__init__(self)
33 self._stream = stream
34 self.failed_tests = 0
35
36 def addError(self, test, err):
37 self.failed_tests += 1
38 self.reportTest(test)
39
40 def addFailure(self, test, err):
41 self.failed_tests += 1
42 self.reportTest(test)
43
44 def addSuccess(self, test):
45 self.reportTest(test)
46
47 def reportTest(self, test):
48 self._stream.write(test.id() + '\n')
49
50 def wasSuccessful(self):
51 "Tells whether or not this result was a success"
52 return self.failed_tests == 0
53
54
55result = FilterResult(sys.stdout)
56test = ProtocolTestCase(sys.stdin)
57test.run(result)
58if result.wasSuccessful():
59 exit_code = 0
60else:
61 exit_code = 1
62sys.exit(exit_code)
063
=== modified file 'python/subunit/__init__.py'
--- python/subunit/__init__.py 2009-02-15 11:55:00 +0000
+++ python/subunit/__init__.py 2009-02-28 09:27:25 +0000
@@ -133,7 +133,7 @@
133 self.current_test_description == line[offset:-1]):133 self.current_test_description == line[offset:-1]):
134 self.state = TestProtocolServer.OUTSIDE_TEST134 self.state = TestProtocolServer.OUTSIDE_TEST
135 self.current_test_description = None135 self.current_test_description = None
136 self.client.addSuccess(self._current_test)136 self._skip_or_error()
137 self.client.stopTest(self._current_test)137 self.client.stopTest(self._current_test)
138 elif (self.state == TestProtocolServer.TEST_STARTED and138 elif (self.state == TestProtocolServer.TEST_STARTED and
139 self.current_test_description + " [" == line[offset:-1]):139 self.current_test_description + " [" == line[offset:-1]):
@@ -142,6 +142,16 @@
142 else:142 else:
143 self.stdOutLineReceived(line)143 self.stdOutLineReceived(line)
144144
145 def _skip_or_error(self, message=None):
146 """Report the current test as a skip if possible, or else an error."""
147 addSkip = getattr(self.client, 'addSkip', None)
148 if not callable(addSkip):
149 self.client.addError(self._current_test, RemoteError(message))
150 else:
151 if not message:
152 message = "No reason given"
153 addSkip(self._current_test, message)
154
145 def _addSuccess(self, offset, line):155 def _addSuccess(self, offset, line):
146 if (self.state == TestProtocolServer.TEST_STARTED and156 if (self.state == TestProtocolServer.TEST_STARTED and
147 self.current_test_description == line[offset:-1]):157 self.current_test_description == line[offset:-1]):
@@ -173,8 +183,12 @@
173 self.client.addError(self._current_test,183 self.client.addError(self._current_test,
174 RemoteError(self._message))184 RemoteError(self._message))
175 self.client.stopTest(self._current_test)185 self.client.stopTest(self._current_test)
186 elif self.state == TestProtocolServer.READING_SKIP:
187 self.state = TestProtocolServer.OUTSIDE_TEST
188 self.current_test_description = None
189 self._skip_or_error(self._message)
190 self.client.stopTest(self._current_test)
176 elif self.state in (191 elif self.state in (
177 TestProtocolServer.READING_SKIP,
178 TestProtocolServer.READING_SUCCESS,192 TestProtocolServer.READING_SUCCESS,
179 TestProtocolServer.READING_XFAIL,193 TestProtocolServer.READING_XFAIL,
180 ):194 ):
@@ -314,6 +328,12 @@
314 self._stream.write("%s\n" % line)328 self._stream.write("%s\n" % line)
315 self._stream.write("]\n")329 self._stream.write("]\n")
316330
331 def addSkip(self, test, reason):
332 """Report a skipped test."""
333 self._stream.write("skip: %s [\n" % test.id())
334 self._stream.write("%s\n" % reason)
335 self._stream.write("]\n")
336
317 def addSuccess(self, test):337 def addSuccess(self, test):
318 """Report a success in a test."""338 """Report a success in a test."""
319 self._stream.write("successful: %s\n" % test.id())339 self._stream.write("successful: %s\n" % test.id())
@@ -363,7 +383,7 @@
363 return self.__description383 return self.__description
364384
365 def id(self):385 def id(self):
366 return "%s.%s" % (self._strclass(), self.__description)386 return "%s" % (self.__description,)
367387
368 def __str__(self):388 def __str__(self):
369 return "%s (%s)" % (self.__description, self._strclass())389 return "%s (%s)" % (self.__description, self._strclass())
@@ -651,6 +671,7 @@
651 unittest.TestResult.__init__(self)671 unittest.TestResult.__init__(self)
652 self._stream = stream672 self._stream = stream
653 self.failed_tests = 0673 self.failed_tests = 0
674 self.skipped_tests = 0
654 self.tags = set()675 self.tags = set()
655676
656 @property677 @property
@@ -663,16 +684,20 @@
663 def addFailure(self, test, err):684 def addFailure(self, test, err):
664 self.failed_tests += 1685 self.failed_tests += 1
665686
687 def addSkip(self, test, reason):
688 self.skipped_tests += 1
689
666 def formatStats(self):690 def formatStats(self):
667 self._stream.write("Total tests: %5d\n" % self.total_tests)691 self._stream.write("Total tests: %5d\n" % self.total_tests)
668 self._stream.write("Passed tests: %5d\n" % self.passed_tests)692 self._stream.write("Passed tests: %5d\n" % self.passed_tests)
669 self._stream.write("Failed tests: %5d\n" % self.failed_tests)693 self._stream.write("Failed tests: %5d\n" % self.failed_tests)
694 self._stream.write("Skipped tests: %5d\n" % self.skipped_tests)
670 tags = sorted(self.tags)695 tags = sorted(self.tags)
671 self._stream.write("Tags: %s\n" % (", ".join(tags)))696 self._stream.write("Tags: %s\n" % (", ".join(tags)))
672697
673 @property698 @property
674 def passed_tests(self):699 def passed_tests(self):
675 return self.total_tests - self.failed_tests700 return self.total_tests - self.failed_tests - self.skipped_tests
676701
677 def stopTest(self, test):702 def stopTest(self, test):
678 unittest.TestResult.stopTest(self, test)703 unittest.TestResult.stopTest(self, test)
@@ -681,3 +706,66 @@
681 def wasSuccessful(self):706 def wasSuccessful(self):
682 """Tells whether or not this result was a success"""707 """Tells whether or not this result was a success"""
683 return self.failed_tests == 0708 return self.failed_tests == 0
709
710
711class TestResultFilter(unittest.TestResult):
712 """A pyunit TestResult interface implementation which filters tests.
713
714 Tests that pass the filter are handed on to another TestResult instance
715 for further processing/reporting. To obtain the filtered results,
716 the other instance must be interrogated.
717
718 :ivar result: The result that tests are passed to after filtering.
719 """
720
721 def __init__(self, result, filter_error=False, filter_failure=False,
722 filter_success=True, filter_skip=False):
723 """Create a FilterResult object filtering to result.
724
725 :param filter_error: Filter out errors.
726 :param filter_failure: Filter out failures.
727 :param filter_success: Filter out successful tests.
728 :param filter_skip: Filter out skipped tests.
729 """
730 unittest.TestResult.__init__(self)
731 self.result = result
732 self._filter_error = filter_error
733 self._filter_failure = filter_failure
734 self._filter_success = filter_success
735 self._filter_skip = filter_skip
736
737 def addError(self, test, err):
738 if not self._filter_error:
739 self.result.startTest(test)
740 self.result.addError(test, err)
741 self.result.stopTest(test)
742
743 def addFailure(self, test, err):
744 if not self._filter_failure:
745 self.result.startTest(test)
746 self.result.addFailure(test, err)
747 self.result.stopTest(test)
748
749 def addSkip(self, test, reason):
750 if not self._filter_skip:
751 self.result.startTest(test)
752 # This is duplicated, it would be nice to have on a 'calls
753 # TestResults' mixin perhaps.
754 addSkip = getattr(self.result, 'addSkip', None)
755 if not callable(addSkip):
756 self.result.addError(test, RemoteError(reason))
757 else:
758 self.result.addSkip(test, reason)
759 self.result.stopTest(test)
760
761 def addSuccess(self, test):
762 if not self._filter_success:
763 self.result.startTest(test)
764 self.result.addSuccess(test)
765 self.result.stopTest(test)
766
767 def id_to_orig_id(self, id):
768 if id.startswith("subunit.RemotedTestCase."):
769 return id[len("subunit.RemotedTestCase."):]
770 return id
771
684772
=== modified file 'python/subunit/tests/__init__.py'
--- python/subunit/tests/__init__.py 2008-12-09 01:00:03 +0000
+++ python/subunit/tests/__init__.py 2009-02-22 06:28:08 +0000
@@ -19,6 +19,7 @@
1919
20from subunit.tests import (20from subunit.tests import (
21 TestUtil,21 TestUtil,
22 test_subunit_filter,
22 test_subunit_stats,23 test_subunit_stats,
23 test_subunit_tags,24 test_subunit_tags,
24 test_tap2subunit,25 test_tap2subunit,
@@ -29,6 +30,7 @@
29 result = TestUtil.TestSuite()30 result = TestUtil.TestSuite()
30 result.addTest(test_test_protocol.test_suite())31 result.addTest(test_test_protocol.test_suite())
31 result.addTest(test_tap2subunit.test_suite())32 result.addTest(test_tap2subunit.test_suite())
33 result.addTest(test_subunit_filter.test_suite())
32 result.addTest(test_subunit_tags.test_suite())34 result.addTest(test_subunit_tags.test_suite())
33 result.addTest(test_subunit_stats.test_suite())35 result.addTest(test_subunit_stats.test_suite())
34 return result36 return result
3537
=== added file 'python/subunit/tests/test_subunit_filter.py'
--- python/subunit/tests/test_subunit_filter.py 1970-01-01 00:00:00 +0000
+++ python/subunit/tests/test_subunit_filter.py 2009-02-28 09:27:25 +0000
@@ -0,0 +1,125 @@
1#
2# subunit: extensions to python unittest to get test results from subprocesses.
3# Copyright (C) 2005 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"""Tests for subunit.TestResultFilter."""
21
22import unittest
23from StringIO import StringIO
24
25import subunit
26
27
28class TestTestResultFilter(unittest.TestCase):
29 """Test for TestResultFilter, a TestResult object which filters tests."""
30
31 def _setUp(self):
32 self.output = StringIO()
33
34 def test_default(self):
35 """The default is to exclude success and include everything else."""
36 self.filtered_result = unittest.TestResult()
37 self.filter = subunit.TestResultFilter(self.filtered_result)
38 self.run_tests()
39 # skips are seen as errors by default python TestResult.
40 self.assertEqual(['error', 'skipped'],
41 [error[0].id() for error in self.filtered_result.errors])
42 self.assertEqual(['failed'],
43 [failure[0].id() for failure in
44 self.filtered_result.failures])
45 self.assertEqual(3, self.filtered_result.testsRun)
46
47 def test_exclude_errors(self):
48 self.filtered_result = unittest.TestResult()
49 self.filter = subunit.TestResultFilter(self.filtered_result,
50 filter_error=True)
51 self.run_tests()
52 # skips are seen as errors by default python TestResult.
53 self.assertEqual(['skipped'],
54 [error[0].id() for error in self.filtered_result.errors])
55 self.assertEqual(['failed'],
56 [failure[0].id() for failure in
57 self.filtered_result.failures])
58 self.assertEqual(2, self.filtered_result.testsRun)
59
60 def test_exclude_failure(self):
61 self.filtered_result = unittest.TestResult()
62 self.filter = subunit.TestResultFilter(self.filtered_result,
63 filter_failure=True)
64 self.run_tests()
65 self.assertEqual(['error', 'skipped'],
66 [error[0].id() for error in self.filtered_result.errors])
67 self.assertEqual([],
68 [failure[0].id() for failure in
69 self.filtered_result.failures])
70 self.assertEqual(2, self.filtered_result.testsRun)
71
72 def test_exclude_skips(self):
73 self.filtered_result = subunit.TestResultStats(None)
74 self.filter = subunit.TestResultFilter(self.filtered_result,
75 filter_skip=True)
76 self.run_tests()
77 self.assertEqual(0, self.filtered_result.skipped_tests)
78 self.assertEqual(2, self.filtered_result.failed_tests)
79 self.assertEqual(2, self.filtered_result.testsRun)
80
81 def test_include_success(self):
82 """Success's can be included if requested."""
83 self.filtered_result = unittest.TestResult()
84 self.filter = subunit.TestResultFilter(self.filtered_result,
85 filter_success=False)
86 self.run_tests()
87 self.assertEqual(['error', 'skipped'],
88 [error[0].id() for error in self.filtered_result.errors])
89 self.assertEqual(['failed'],
90 [failure[0].id() for failure in
91 self.filtered_result.failures])
92 self.assertEqual(5, self.filtered_result.testsRun)
93
94 def run_tests(self):
95 self.setUpTestStream()
96 self.test = subunit.ProtocolTestCase(self.input_stream)
97 self.test.run(self.filter)
98
99 def setUpTestStream(self):
100 # While TestResultFilter works on python objects, using a subunit
101 # stream is an easy pithy way of getting a series of test objects to
102 # call into the TestResult, and as TestResultFilter is intended for use
103 # with subunit also has the benefit of detecting any interface skew issues.
104 self.input_stream = StringIO()
105 self.input_stream.write("""tags: global
106test passed
107success passed
108test failed
109tags: local
110failure failed
111test error
112error error
113test skipped
114skip skipped
115test todo
116xfail todo
117""")
118 self.input_stream.seek(0)
119
120
121
122def test_suite():
123 loader = subunit.tests.TestUtil.TestLoader()
124 result = loader.loadTestsFromName(__name__)
125 return result
0126
=== modified file 'python/subunit/tests/test_subunit_stats.py'
--- python/subunit/tests/test_subunit_stats.py 2008-12-09 01:00:03 +0000
+++ python/subunit/tests/test_subunit_stats.py 2009-02-28 09:27:25 +0000
@@ -62,15 +62,17 @@
62 # Statistics are calculated usefully.62 # Statistics are calculated usefully.
63 self.setUpUsedStream()63 self.setUpUsedStream()
64 self.assertEqual(5, self.result.total_tests)64 self.assertEqual(5, self.result.total_tests)
65 self.assertEqual(3, self.result.passed_tests)65 self.assertEqual(2, self.result.passed_tests)
66 self.assertEqual(2, self.result.failed_tests)66 self.assertEqual(2, self.result.failed_tests)
67 self.assertEqual(1, self.result.skipped_tests)
67 self.assertEqual(set(["global", "local"]), self.result.tags)68 self.assertEqual(set(["global", "local"]), self.result.tags)
6869
69 def test_stat_formatting(self):70 def test_stat_formatting(self):
70 expected = ("""71 expected = ("""
71Total tests: 572Total tests: 5
72Passed tests: 373Passed tests: 2
73Failed tests: 274Failed tests: 2
75Skipped tests: 1
74Tags: global, local76Tags: global, local
75""")[1:]77""")[1:]
76 self.setUpUsedStream()78 self.setUpUsedStream()
7779
=== modified file 'python/subunit/tests/test_test_protocol.py'
--- python/subunit/tests/test_test_protocol.py 2008-12-14 18:37:08 +0000
+++ python/subunit/tests/test_test_protocol.py 2009-02-28 09:27:25 +0000
@@ -32,6 +32,7 @@
32 self.end_calls = []32 self.end_calls = []
33 self.error_calls = []33 self.error_calls = []
34 self.failure_calls = []34 self.failure_calls = []
35 self.skip_calls = []
35 self.start_calls = []36 self.start_calls = []
36 self.success_calls = []37 self.success_calls = []
37 super(MockTestProtocolServerClient, self).__init__()38 super(MockTestProtocolServerClient, self).__init__()
@@ -42,6 +43,9 @@
42 def addFailure(self, test, error):43 def addFailure(self, test, error):
43 self.failure_calls.append((test, error))44 self.failure_calls.append((test, error))
4445
46 def addSkip(self, test, reason):
47 self.skip_calls.append((test, reason))
48
45 def addSuccess(self, test):49 def addSuccess(self, test):
46 self.success_calls.append(test)50 self.success_calls.append(test)
4751
@@ -589,8 +593,8 @@
589class TestTestProtocolServerAddSkip(unittest.TestCase):593class TestTestProtocolServerAddSkip(unittest.TestCase):
590 """Tests for the skip keyword.594 """Tests for the skip keyword.
591595
592 In Python this thunks through to Success due to stdlib limitations. (See596 In python this meets the testtools extended TestResult contract.
593 README).597 (See https://launchpad.net/testtools).
594 """598 """
595599
596 def setUp(self):600 def setUp(self):
@@ -606,7 +610,9 @@
606 self.assertEqual(self.client.end_calls, [self.test])610 self.assertEqual(self.client.end_calls, [self.test])
607 self.assertEqual(self.client.error_calls, [])611 self.assertEqual(self.client.error_calls, [])
608 self.assertEqual(self.client.failure_calls, [])612 self.assertEqual(self.client.failure_calls, [])
609 self.assertEqual(self.client.success_calls, [self.test])613 self.assertEqual(self.client.success_calls, [])
614 self.assertEqual(self.client.skip_calls,
615 [(self.test, 'No reason given')])
610616
611 def test_simple_skip(self):617 def test_simple_skip(self):
612 self.simple_skip_keyword("skip")618 self.simple_skip_keyword("skip")
@@ -621,7 +627,9 @@
621 self.assertEqual(self.client.end_calls, [self.test])627 self.assertEqual(self.client.end_calls, [self.test])
622 self.assertEqual(self.client.error_calls, [])628 self.assertEqual(self.client.error_calls, [])
623 self.assertEqual(self.client.failure_calls, [])629 self.assertEqual(self.client.failure_calls, [])
624 self.assertEqual(self.client.success_calls, [self.test])630 self.assertEqual(self.client.success_calls, [])
631 self.assertEqual(self.client.skip_calls,
632 [(self.test, "No reason given")])
625633
626 def skip_quoted_bracket(self, keyword):634 def skip_quoted_bracket(self, keyword):
627 # This tests it is accepted, but cannot test it is used today, because635 # This tests it is accepted, but cannot test it is used today, because
@@ -633,7 +641,9 @@
633 self.assertEqual(self.client.end_calls, [self.test])641 self.assertEqual(self.client.end_calls, [self.test])
634 self.assertEqual(self.client.error_calls, [])642 self.assertEqual(self.client.error_calls, [])
635 self.assertEqual(self.client.failure_calls, [])643 self.assertEqual(self.client.failure_calls, [])
636 self.assertEqual(self.client.success_calls, [self.test])644 self.assertEqual(self.client.success_calls, [])
645 self.assertEqual(self.client.skip_calls,
646 [(self.test, "]\n")])
637647
638 def test_skip_quoted_bracket(self):648 def test_skip_quoted_bracket(self):
639 self.skip_quoted_bracket("skip")649 self.skip_quoted_bracket("skip")
@@ -772,7 +782,7 @@
772 self.assertRaises(NotImplementedError, test.tearDown)782 self.assertRaises(NotImplementedError, test.tearDown)
773 self.assertEqual("A test description",783 self.assertEqual("A test description",
774 test.shortDescription())784 test.shortDescription())
775 self.assertEqual("subunit.RemotedTestCase.A test description",785 self.assertEqual("A test description",
776 test.id())786 test.id())
777 self.assertEqual("A test description (subunit.RemotedTestCase)", "%s" % test)787 self.assertEqual("A test description (subunit.RemotedTestCase)", "%s" % test)
778 self.assertEqual("<subunit.RemotedTestCase description="788 self.assertEqual("<subunit.RemotedTestCase description="
@@ -933,7 +943,6 @@
933 self.protocol = subunit.TestProtocolClient(self.io)943 self.protocol = subunit.TestProtocolClient(self.io)
934 self.test = TestTestProtocolClient("test_start_test")944 self.test = TestTestProtocolClient("test_start_test")
935945
936
937 def test_start_test(self):946 def test_start_test(self):
938 """Test startTest on a TestProtocolClient."""947 """Test startTest on a TestProtocolClient."""
939 self.protocol.startTest(self.test)948 self.protocol.startTest(self.test)
@@ -968,6 +977,14 @@
968 "RemoteException: phwoar crikey\n"977 "RemoteException: phwoar crikey\n"
969 "]\n" % self.test.id())978 "]\n" % self.test.id())
970979
980 def test_add_skip(self):
981 """Test addSkip on a TestProtocolClient."""
982 self.protocol.addSkip(
983 self.test, "Has it really?")
984 self.assertEqual(
985 self.io.getvalue(),
986 'skip: %s [\nHas it really?\n]\n' % self.test.id())
987
971988
972def test_suite():989def test_suite():
973 loader = subunit.tests.TestUtil.TestLoader()990 loader = subunit.tests.TestUtil.TestLoader()

Subscribers

People subscribed via source and target branches