Merge lp:~lifeless/subunit/nopassthrough into lp:~subunit/subunit/trunk
- nopassthrough
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | not available |
Proposed branch: | lp:~lifeless/subunit/nopassthrough |
Merge into: | lp:~subunit/subunit/trunk |
Diff against target: | None lines |
To merge this branch: | bzr merge lp:~lifeless/subunit/nopassthrough |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jelmer Vernooij | Approve | ||
Jonathan Lange | Approve | ||
Review via email: mp+9557@code.launchpad.net |
Commit message
Description of the change
Robert Collins (lifeless) wrote : | # |
- 76. By Robert Collins
-
Fix optparse sense inversion in new option.
Jonathan Lange (jml) wrote : | # |
> This adds --no-passthrough to most filers, which is useful for ensuring there
> is no noise in a stream. This is important for some uses, like when outputting
> structured data other programs will be reading.
Hey Rob,
This seems like a good feature & I can't fault the code. From the description in the MP though, I was expecting the behaviour to be that --no-passthrough makes the script error out when there is noise.
Perhaps the option should be 'discard-noise' or something similar?
jml
Jelmer Vernooij (jelmer) wrote : | # |
Other than the two space issue this seems fine to me.
Bonus points for a test that proves that only non-subunit data is written to the output stream.
Robert Collins (lifeless) wrote : | # |
On Tue, 2009-08-04 at 08:53 +0000, Jonathan Lange wrote:
> Review: Approve
> > This adds --no-passthrough to most filers, which is useful for ensuring there
> > is no noise in a stream. This is important for some uses, like when outputting
> > structured data other programs will be reading.
>
> Hey Rob,
>
> This seems like a good feature & I can't fault the code. From the description in the MP though, I was expecting the behaviour to be that --no-passthrough makes the script error out when there is noise.
>
> Perhaps the option should be 'discard-noise' or something similar?
disard-passthrough perhaps?
I hesitate to call the other content 'noise' - its typically things like
'make' output, or extra debugging that faulty tests aren't capturing.
So I'd like a neutral name for it.
-Rob
Robert Collins (lifeless) wrote : | # |
I've landed this with the current name, on the basis that we have a week or so to change it before I do a 0.2 release.
Jonathan Lange (jml) wrote : | # |
On Wed, Aug 5, 2009 at 1:18 AM, Robert Collins<email address hidden> wrote:
> On Tue, 2009-08-04 at 08:53 +0000, Jonathan Lange wrote:
>> Review: Approve
>> > This adds --no-passthrough to most filers, which is useful for ensuring there
>> > is no noise in a stream. This is important for some uses, like when outputting
>> > structured data other programs will be reading.
>>
>> Hey Rob,
>>
>> This seems like a good feature & I can't fault the code. From the description in the MP though, I was expecting the behaviour to be that --no-passthrough makes the script error out when there is noise.
>>
>> Perhaps the option should be 'discard-noise' or something similar?
>
> disard-passthrough perhaps?
>
> I hesitate to call the other content 'noise' - its typically things like
> 'make' output, or extra debugging that faulty tests aren't capturing.
>
> So I'd like a neutral name for it.
>
I agree. I'm stumped for the right noun though.
jml
Preview Diff
1 | === modified file 'NEWS' | |||
2 | --- NEWS 2009-08-01 22:10:25 +0000 | |||
3 | +++ NEWS 2009-08-02 22:55:36 +0000 | |||
4 | @@ -10,6 +10,10 @@ | |||
5 | 10 | 10 | ||
6 | 11 | IMPROVEMENTS: | 11 | IMPROVEMENTS: |
7 | 12 | 12 | ||
8 | 13 | * A number of filters now support ``--no-passthrough`` to cause all | ||
9 | 14 | non-subunit content to be discarded. This is useful when precise control | ||
10 | 15 | over what is output is required - such as with subunit2junitxml. | ||
11 | 16 | |||
12 | 13 | * Subunit streams can now include optional, incremental lookahead | 17 | * Subunit streams can now include optional, incremental lookahead |
13 | 14 | information about progress. This allows reporters to make estimates | 18 | information about progress. This allows reporters to make estimates |
14 | 15 | about completion, when such information is available. See the README | 19 | about completion, when such information is available. See the README |
15 | 16 | 20 | ||
16 | === modified file 'filters/subunit-filter' | |||
17 | --- filters/subunit-filter 2009-03-01 21:39:53 +0000 | |||
18 | +++ filters/subunit-filter 2009-08-02 22:55:36 +0000 | |||
19 | @@ -26,7 +26,12 @@ | |||
20 | 26 | import sys | 26 | import sys |
21 | 27 | import unittest | 27 | import unittest |
22 | 28 | 28 | ||
24 | 29 | from subunit import ProtocolTestCase, TestResultFilter, TestProtocolClient | 29 | from subunit import ( |
25 | 30 | DiscardStream, | ||
26 | 31 | ProtocolTestCase, | ||
27 | 32 | TestProtocolClient, | ||
28 | 33 | TestResultFilter, | ||
29 | 34 | ) | ||
30 | 30 | 35 | ||
31 | 31 | parser = OptionParser(description=__doc__) | 36 | parser = OptionParser(description=__doc__) |
32 | 32 | parser.add_option("--error", action="store_false", | 37 | parser.add_option("--error", action="store_false", |
33 | @@ -37,6 +42,8 @@ | |||
34 | 37 | help="include failures", default=False, dest="failure") | 42 | help="include failures", default=False, dest="failure") |
35 | 38 | parser.add_option("-f", "--no-failure", action="store_true", | 43 | parser.add_option("-f", "--no-failure", action="store_true", |
36 | 39 | help="include failures", dest="failure") | 44 | help="include failures", dest="failure") |
37 | 45 | parser.add_option("--no-passthrough", action="store_true", | ||
38 | 46 | help="Hide all non subunit input.", default=True, dest="no_passthrough") | ||
39 | 40 | parser.add_option("-s", "--success", action="store_false", | 47 | parser.add_option("-s", "--success", action="store_false", |
40 | 41 | help="include successes", dest="success") | 48 | help="include successes", dest="success") |
41 | 42 | parser.add_option("--no-skip", action="store_true", | 49 | parser.add_option("--no-skip", action="store_true", |
42 | @@ -45,8 +52,13 @@ | |||
43 | 45 | help="exclude successes", default=True, dest="success") | 52 | help="exclude successes", default=True, dest="success") |
44 | 46 | (options, args) = parser.parse_args() | 53 | (options, args) = parser.parse_args() |
45 | 47 | result = TestProtocolClient(sys.stdout) | 54 | result = TestProtocolClient(sys.stdout) |
49 | 48 | result = TestResultFilter(result, filter_error=options.error, filter_failure=options.failure, | 55 | result = TestResultFilter(result, filter_error=options.error, |
50 | 49 | filter_success=options.success, filter_skip=options.skip) | 56 | filter_failure=options.failure, filter_success=options.success, |
51 | 50 | test = ProtocolTestCase(sys.stdin) | 57 | filter_skip=options.skip) |
52 | 58 | if options.no_passthrough: | ||
53 | 59 | passthrough_stream = DiscardStream() | ||
54 | 60 | else: | ||
55 | 61 | passthrough_stream = None | ||
56 | 62 | test = ProtocolTestCase(sys.stdin, passthrough=passthrough_stream) | ||
57 | 51 | test.run(result) | 63 | test.run(result) |
58 | 52 | sys.exit(0) | 64 | sys.exit(0) |
59 | 53 | 65 | ||
60 | === modified file 'filters/subunit-ls' | |||
61 | --- filters/subunit-ls 2009-07-20 10:12:42 +0000 | |||
62 | +++ filters/subunit-ls 2009-08-02 22:55:36 +0000 | |||
63 | @@ -23,7 +23,7 @@ | |||
64 | 23 | import sys | 23 | import sys |
65 | 24 | import unittest | 24 | import unittest |
66 | 25 | 25 | ||
68 | 26 | from subunit import ProtocolTestCase | 26 | from subunit import DiscardStream, ProtocolTestCase |
69 | 27 | 27 | ||
70 | 28 | class TestIdPrintingResult(unittest.TestResult): | 28 | class TestIdPrintingResult(unittest.TestResult): |
71 | 29 | 29 | ||
72 | @@ -79,9 +79,15 @@ | |||
73 | 79 | parser.add_option("--times", action="store_true", | 79 | parser.add_option("--times", action="store_true", |
74 | 80 | help="list the time each test took (requires a timestamped stream)", | 80 | help="list the time each test took (requires a timestamped stream)", |
75 | 81 | default=False) | 81 | default=False) |
76 | 82 | parser.add_option("--no-passthrough", action="store_true", | ||
77 | 83 | help="Hide all non subunit input.", default=True, dest="no_passthrough") | ||
78 | 82 | (options, args) = parser.parse_args() | 84 | (options, args) = parser.parse_args() |
79 | 83 | result = TestIdPrintingResult(sys.stdout, options.times) | 85 | result = TestIdPrintingResult(sys.stdout, options.times) |
81 | 84 | test = ProtocolTestCase(sys.stdin) | 86 | if options.no_passthrough: |
82 | 87 | passthrough_stream = DiscardStream() | ||
83 | 88 | else: | ||
84 | 89 | passthrough_stream = None | ||
85 | 90 | test = ProtocolTestCase(sys.stdin, passthrough=passthrough_stream) | ||
86 | 85 | test.run(result) | 91 | test.run(result) |
87 | 86 | if result.wasSuccessful(): | 92 | if result.wasSuccessful(): |
88 | 87 | exit_code = 0 | 93 | exit_code = 0 |
89 | 88 | 94 | ||
90 | === modified file 'filters/subunit-stats' | |||
91 | --- filters/subunit-stats 2009-02-15 11:55:00 +0000 | |||
92 | +++ filters/subunit-stats 2009-08-02 22:55:36 +0000 | |||
93 | @@ -19,13 +19,22 @@ | |||
94 | 19 | 19 | ||
95 | 20 | """Filter a subunit stream to get aggregate statistics.""" | 20 | """Filter a subunit stream to get aggregate statistics.""" |
96 | 21 | 21 | ||
97 | 22 | from optparse import OptionParser | ||
98 | 22 | import sys | 23 | import sys |
99 | 23 | import unittest | 24 | import unittest |
100 | 24 | 25 | ||
102 | 25 | from subunit import ProtocolTestCase, TestResultStats | 26 | from subunit import DiscardStream, ProtocolTestCase, TestResultStats |
103 | 26 | 27 | ||
104 | 28 | parser = OptionParser(description=__doc__) | ||
105 | 29 | parser.add_option("--no-passthrough", action="store_true", | ||
106 | 30 | help="Hide all non subunit input.", default=True, dest="no_passthrough") | ||
107 | 31 | (options, args) = parser.parse_args() | ||
108 | 27 | result = TestResultStats(sys.stdout) | 32 | result = TestResultStats(sys.stdout) |
110 | 28 | test = ProtocolTestCase(sys.stdin) | 33 | if options.no_passthrough: |
111 | 34 | passthrough_stream = DiscardStream() | ||
112 | 35 | else: | ||
113 | 36 | passthrough_stream = None | ||
114 | 37 | test = ProtocolTestCase(sys.stdin, passthrough=passthrough_stream) | ||
115 | 29 | test.run(result) | 38 | test.run(result) |
116 | 30 | result.formatStats() | 39 | result.formatStats() |
117 | 31 | if result.wasSuccessful(): | 40 | if result.wasSuccessful(): |
118 | 32 | 41 | ||
119 | === modified file 'filters/subunit2junitxml' | |||
120 | --- filters/subunit2junitxml 2009-08-01 08:01:27 +0000 | |||
121 | +++ filters/subunit2junitxml 2009-08-02 22:55:36 +0000 | |||
122 | @@ -19,10 +19,11 @@ | |||
123 | 19 | 19 | ||
124 | 20 | """Filter a subunit stream to get aggregate statistics.""" | 20 | """Filter a subunit stream to get aggregate statistics.""" |
125 | 21 | 21 | ||
126 | 22 | from optparse import OptionParser | ||
127 | 22 | import sys | 23 | import sys |
128 | 23 | import unittest | 24 | import unittest |
129 | 24 | 25 | ||
131 | 25 | from subunit import ProtocolTestCase | 26 | from subunit import DiscardStream, ProtocolTestCase |
132 | 26 | try: | 27 | try: |
133 | 27 | from junitxml import JUnitXmlResult | 28 | from junitxml import JUnitXmlResult |
134 | 28 | except ImportError: | 29 | except ImportError: |
135 | @@ -30,8 +31,16 @@ | |||
136 | 30 | "http://pypi.python.org/pypi/junitxml) is required for this filter.") | 31 | "http://pypi.python.org/pypi/junitxml) is required for this filter.") |
137 | 31 | raise | 32 | raise |
138 | 32 | 33 | ||
139 | 34 | parser = OptionParser(description=__doc__) | ||
140 | 35 | parser.add_option("--no-passthrough", action="store_true", | ||
141 | 36 | help="Hide all non subunit input.", default=True, dest="no_passthrough") | ||
142 | 37 | (options, args) = parser.parse_args() | ||
143 | 33 | result = JUnitXmlResult(sys.stdout) | 38 | result = JUnitXmlResult(sys.stdout) |
145 | 34 | test = ProtocolTestCase(sys.stdin) | 39 | if options.no_passthrough: |
146 | 40 | passthrough_stream = DiscardStream() | ||
147 | 41 | else: | ||
148 | 42 | passthrough_stream = None | ||
149 | 43 | test = ProtocolTestCase(sys.stdin, passthrough=passthrough_stream) | ||
150 | 35 | result.startTestRun() | 44 | result.startTestRun() |
151 | 36 | test.run(result) | 45 | test.run(result) |
152 | 37 | result.stopTestRun() | 46 | result.stopTestRun() |
153 | 38 | 47 | ||
154 | === modified file 'filters/subunit2pyunit' | |||
155 | --- filters/subunit2pyunit 2009-07-28 21:44:28 +0000 | |||
156 | +++ filters/subunit2pyunit 2009-08-02 22:55:36 +0000 | |||
157 | @@ -23,14 +23,20 @@ | |||
158 | 23 | import sys | 23 | import sys |
159 | 24 | import unittest | 24 | import unittest |
160 | 25 | 25 | ||
162 | 26 | from subunit import ProtocolTestCase, TestProtocolServer | 26 | from subunit import DiscardStream, ProtocolTestCase, TestProtocolServer |
163 | 27 | 27 | ||
164 | 28 | parser = OptionParser(description=__doc__) | 28 | parser = OptionParser(description=__doc__) |
165 | 29 | parser.add_option("--no-passthrough", action="store_true", | ||
166 | 30 | help="Hide all non subunit input.", default=True, dest="no_passthrough") | ||
167 | 29 | parser.add_option("--progress", action="store_true", | 31 | parser.add_option("--progress", action="store_true", |
168 | 30 | help="Use bzrlib's test reporter (requires bzrlib)", | 32 | help="Use bzrlib's test reporter (requires bzrlib)", |
169 | 31 | default=False) | 33 | default=False) |
170 | 32 | (options, args) = parser.parse_args() | 34 | (options, args) = parser.parse_args() |
172 | 33 | test = ProtocolTestCase(sys.stdin) | 35 | if options.no_passthrough: |
173 | 36 | passthrough_stream = DiscardStream() | ||
174 | 37 | else: | ||
175 | 38 | passthrough_stream = None | ||
176 | 39 | test = ProtocolTestCase(sys.stdin, passthrough=passthrough_stream) | ||
177 | 34 | if options.progress: | 40 | if options.progress: |
178 | 35 | from bzrlib.tests import TextTestRunner | 41 | from bzrlib.tests import TextTestRunner |
179 | 36 | from bzrlib import ui | 42 | from bzrlib import ui |
180 | 37 | 43 | ||
181 | === modified file 'python/subunit/__init__.py' | |||
182 | --- python/subunit/__init__.py 2009-07-28 13:32:10 +0000 | |||
183 | +++ python/subunit/__init__.py 2009-08-02 22:55:36 +0000 | |||
184 | @@ -63,6 +63,13 @@ | |||
185 | 63 | return new_tags, gone_tags | 63 | return new_tags, gone_tags |
186 | 64 | 64 | ||
187 | 65 | 65 | ||
188 | 66 | class DiscardStream(object): | ||
189 | 67 | """A filelike object which discards what is written to it.""" | ||
190 | 68 | |||
191 | 69 | def write(self, bytes): | ||
192 | 70 | pass | ||
193 | 71 | |||
194 | 72 | |||
195 | 66 | class TestProtocolServer(object): | 73 | class TestProtocolServer(object): |
196 | 67 | """A class for receiving results from a TestProtocol client. | 74 | """A class for receiving results from a TestProtocol client. |
197 | 68 | 75 | ||
198 | @@ -77,19 +84,19 @@ | |||
199 | 77 | READING_XFAIL = 5 | 84 | READING_XFAIL = 5 |
200 | 78 | READING_SUCCESS = 6 | 85 | READING_SUCCESS = 6 |
201 | 79 | 86 | ||
203 | 80 | def __init__(self, client, stream=sys.stdout): | 87 | def __init__(self, client, stream=None): |
204 | 81 | """Create a TestProtocol server instance. | 88 | """Create a TestProtocol server instance. |
205 | 82 | 89 | ||
213 | 83 | client should be an object that provides | 90 | :param client: An object meeting the unittest.TestResult protocol. |
214 | 84 | - startTest | 91 | :param stream: The stream that lines received which are not part of the |
215 | 85 | - addSuccess | 92 | subunit protocol should be written to. This allows custom handling |
216 | 86 | - addFailure | 93 | of mixed protocols. By default, sys.stdout will be used for |
217 | 87 | - addError | 94 | convenience. |
211 | 88 | - stopTest | ||
212 | 89 | methods, i.e. a TestResult. | ||
218 | 90 | """ | 95 | """ |
219 | 91 | self.state = TestProtocolServer.OUTSIDE_TEST | 96 | self.state = TestProtocolServer.OUTSIDE_TEST |
220 | 92 | self.client = client | 97 | self.client = client |
221 | 98 | if stream is None: | ||
222 | 99 | stream = sys.stdout | ||
223 | 93 | self._stream = stream | 100 | self._stream = stream |
224 | 94 | self.tags = set() | 101 | self.tags = set() |
225 | 95 | 102 | ||
226 | @@ -701,8 +708,16 @@ | |||
227 | 701 | class ProtocolTestCase(object): | 708 | class ProtocolTestCase(object): |
228 | 702 | """A test case which reports a subunit stream.""" | 709 | """A test case which reports a subunit stream.""" |
229 | 703 | 710 | ||
231 | 704 | def __init__(self, stream): | 711 | def __init__(self, stream, passthrough=None): |
232 | 712 | """Create a ProtocolTestCase reading from stream. | ||
233 | 713 | |||
234 | 714 | :param stream: A filelike object which a subunit stream can be read | ||
235 | 715 | from. | ||
236 | 716 | :param passthrough: A stream pass non subunit input on to. If not | ||
237 | 717 | supplied, the TestProtocolServer default is used. | ||
238 | 718 | """ | ||
239 | 705 | self._stream = stream | 719 | self._stream = stream |
240 | 720 | self._passthrough = passthrough | ||
241 | 706 | 721 | ||
242 | 707 | def __call__(self, result=None): | 722 | def __call__(self, result=None): |
243 | 708 | return self.run(result) | 723 | return self.run(result) |
244 | @@ -710,7 +725,7 @@ | |||
245 | 710 | def run(self, result=None): | 725 | def run(self, result=None): |
246 | 711 | if result is None: | 726 | if result is None: |
247 | 712 | result = self.defaultTestResult() | 727 | result = self.defaultTestResult() |
249 | 713 | protocol = TestProtocolServer(result) | 728 | protocol = TestProtocolServer(result, self._passthrough) |
250 | 714 | line = self._stream.readline() | 729 | line = self._stream.readline() |
251 | 715 | while line: | 730 | while line: |
252 | 716 | protocol.lineReceived(line) | 731 | protocol.lineReceived(line) |
253 | 717 | 732 | ||
254 | === modified file 'python/subunit/tests/test_test_protocol.py' | |||
255 | --- python/subunit/tests/test_test_protocol.py 2009-07-28 13:32:10 +0000 | |||
256 | +++ python/subunit/tests/test_test_protocol.py 2009-08-02 22:55:36 +0000 | |||
257 | @@ -131,6 +131,7 @@ | |||
258 | 131 | class TestTestImports(unittest.TestCase): | 131 | class TestTestImports(unittest.TestCase): |
259 | 132 | 132 | ||
260 | 133 | def test_imports(self): | 133 | def test_imports(self): |
261 | 134 | from subunit import DiscardStream | ||
262 | 134 | from subunit import TestProtocolServer | 135 | from subunit import TestProtocolServer |
263 | 135 | from subunit import RemotedTestCase | 136 | from subunit import RemotedTestCase |
264 | 136 | from subunit import RemoteError | 137 | from subunit import RemoteError |
265 | @@ -139,6 +140,12 @@ | |||
266 | 139 | from subunit import TestProtocolClient | 140 | from subunit import TestProtocolClient |
267 | 140 | 141 | ||
268 | 141 | 142 | ||
269 | 143 | class TestDiscardStream(unittest.TestCase): | ||
270 | 144 | |||
271 | 145 | def test_write(self): | ||
272 | 146 | subunit.DiscardStream().write("content") | ||
273 | 147 | |||
274 | 148 | |||
275 | 142 | class TestTestProtocolServerPipe(unittest.TestCase): | 149 | class TestTestProtocolServerPipe(unittest.TestCase): |
276 | 143 | 150 | ||
277 | 144 | def test_story(self): | 151 | def test_story(self): |
278 | @@ -194,7 +201,6 @@ | |||
279 | 194 | class TestTestProtocolServerPassThrough(unittest.TestCase): | 201 | class TestTestProtocolServerPassThrough(unittest.TestCase): |
280 | 195 | 202 | ||
281 | 196 | def setUp(self): | 203 | def setUp(self): |
282 | 197 | from StringIO import StringIO | ||
283 | 198 | self.stdout = StringIO() | 204 | self.stdout = StringIO() |
284 | 199 | self.test = subunit.RemotedTestCase("old mcdonald") | 205 | self.test = subunit.RemotedTestCase("old mcdonald") |
285 | 200 | self.client = MockTestProtocolServerClient() | 206 | self.client = MockTestProtocolServerClient() |
This adds --no-passthrough to most filers, which is useful for ensuring there is no noise in a stream. This is important for some uses, like when outputting structured data other programs will be reading.