Merge lp:~laurynas-biveinis/percona-server/bug1282599-5.5 into lp:percona-server/5.5
- bug1282599-5.5
- Merge into 5.5
Proposed by
Laurynas Biveinis
Status: | Merged |
---|---|
Approved by: | Laurynas Biveinis |
Approved revision: | no longer in the source branch. |
Merged at revision: | 712 |
Proposed branch: | lp:~laurynas-biveinis/percona-server/bug1282599-5.5 |
Merge into: | lp:percona-server/5.5 |
Diff against target: |
16856 lines (+0/-16518) 66 files modified
python-for-subunit2junitxml/BytesIO.py (+0/-136) python-for-subunit2junitxml/iso8601/LICENSE (+0/-20) python-for-subunit2junitxml/iso8601/README (+0/-26) python-for-subunit2junitxml/iso8601/README.subunit (+0/-5) python-for-subunit2junitxml/iso8601/setup.py (+0/-58) python-for-subunit2junitxml/iso8601/test_iso8601.py (+0/-111) python-for-subunit2junitxml/junitxml/__init__.py (+0/-221) python-for-subunit2junitxml/junitxml/tests/__init__.py (+0/-16) python-for-subunit2junitxml/junitxml/tests/test_junitxml.py (+0/-327) python-for-subunit2junitxml/subunit/__init__.py (+0/-1250) python-for-subunit2junitxml/subunit/chunked.py (+0/-185) python-for-subunit2junitxml/subunit/details.py (+0/-119) python-for-subunit2junitxml/subunit/iso8601.py (+0/-133) python-for-subunit2junitxml/subunit/progress_model.py (+0/-106) python-for-subunit2junitxml/subunit/run.py (+0/-73) python-for-subunit2junitxml/subunit/test_results.py (+0/-492) python-for-subunit2junitxml/subunit/tests/TestUtil.py (+0/-80) python-for-subunit2junitxml/subunit/tests/__init__.py (+0/-41) python-for-subunit2junitxml/subunit/tests/sample-script.py (+0/-21) python-for-subunit2junitxml/subunit/tests/sample-two-script.py (+0/-7) python-for-subunit2junitxml/subunit/tests/test_chunked.py (+0/-152) python-for-subunit2junitxml/subunit/tests/test_details.py (+0/-112) python-for-subunit2junitxml/subunit/tests/test_progress_model.py (+0/-118) python-for-subunit2junitxml/subunit/tests/test_subunit_filter.py (+0/-208) python-for-subunit2junitxml/subunit/tests/test_subunit_stats.py (+0/-84) python-for-subunit2junitxml/subunit/tests/test_subunit_tags.py (+0/-69) python-for-subunit2junitxml/subunit/tests/test_tap2subunit.py (+0/-445) python-for-subunit2junitxml/subunit/tests/test_test_protocol.py (+0/-1299) python-for-subunit2junitxml/subunit/tests/test_test_results.py (+0/-300) python-for-subunit2junitxml/testtools/__init__.py (+0/-80) python-for-subunit2junitxml/testtools/_spinner.py (+0/-316) python-for-subunit2junitxml/testtools/compat.py (+0/-286) python-for-subunit2junitxml/testtools/content.py (+0/-238) python-for-subunit2junitxml/testtools/content_type.py (+0/-33) python-for-subunit2junitxml/testtools/deferredruntest.py (+0/-335) python-for-subunit2junitxml/testtools/distutilscmd.py (+0/-62) python-for-subunit2junitxml/testtools/helpers.py (+0/-64) python-for-subunit2junitxml/testtools/matchers.py (+0/-785) python-for-subunit2junitxml/testtools/monkey.py (+0/-97) python-for-subunit2junitxml/testtools/run.py (+0/-332) python-for-subunit2junitxml/testtools/runtest.py (+0/-200) python-for-subunit2junitxml/testtools/testcase.py (+0/-724) python-for-subunit2junitxml/testtools/testresult/__init__.py (+0/-19) python-for-subunit2junitxml/testtools/testresult/doubles.py (+0/-111) python-for-subunit2junitxml/testtools/testresult/real.py (+0/-621) python-for-subunit2junitxml/testtools/tests/__init__.py (+0/-44) python-for-subunit2junitxml/testtools/tests/helpers.py (+0/-72) python-for-subunit2junitxml/testtools/tests/test_compat.py (+0/-257) python-for-subunit2junitxml/testtools/tests/test_content.py (+0/-223) python-for-subunit2junitxml/testtools/tests/test_content_type.py (+0/-46) python-for-subunit2junitxml/testtools/tests/test_deferredruntest.py (+0/-738) python-for-subunit2junitxml/testtools/tests/test_distutilscmd.py (+0/-90) python-for-subunit2junitxml/testtools/tests/test_fixturesupport.py (+0/-79) python-for-subunit2junitxml/testtools/tests/test_helpers.py (+0/-106) python-for-subunit2junitxml/testtools/tests/test_matchers.py (+0/-695) python-for-subunit2junitxml/testtools/tests/test_monkey.py (+0/-167) python-for-subunit2junitxml/testtools/tests/test_run.py (+0/-77) python-for-subunit2junitxml/testtools/tests/test_runtest.py (+0/-300) python-for-subunit2junitxml/testtools/tests/test_spinner.py (+0/-332) python-for-subunit2junitxml/testtools/tests/test_testresult.py (+0/-1372) python-for-subunit2junitxml/testtools/tests/test_testsuite.py (+0/-53) python-for-subunit2junitxml/testtools/tests/test_testtools.py (+0/-1143) python-for-subunit2junitxml/testtools/tests/test_with_with.py (+0/-42) python-for-subunit2junitxml/testtools/testsuite.py (+0/-87) python-for-subunit2junitxml/testtools/utils.py (+0/-13) subunit2junitxml (+0/-65) |
To merge this branch: | bzr merge lp:~laurynas-biveinis/percona-server/bug1282599-5.5 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Laurynas Biveinis (community) | Approve | ||
Review via email: mp+239008@code.launchpad.net |
Commit message
Description of the change
Fix bug 1282599 (python-
source tree) by removing the subunit2junitxml script and
python-
http://
To post a comment you must log in.
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === removed directory 'python-for-subunit2junitxml' |
2 | === removed file 'python-for-subunit2junitxml/BytesIO.py' |
3 | --- python-for-subunit2junitxml/BytesIO.py 2013-05-27 13:46:13 +0000 |
4 | +++ python-for-subunit2junitxml/BytesIO.py 1970-01-01 00:00:00 +0000 |
5 | @@ -1,136 +0,0 @@ |
6 | - |
7 | -# http://wiki.python.org/moin/BytesIO |
8 | -# |
9 | -# A skeleton one used for systems that don't have BytesIO. |
10 | -# |
11 | -# It's enough for subunit at least.... |
12 | - |
13 | -class BytesIO(object): |
14 | - """ A file-like API for reading and writing bytes objects. |
15 | - |
16 | - Mostly like StringIO, but write() calls modify the underlying |
17 | - bytes object. |
18 | - |
19 | - >>> b = bytes() |
20 | - >>> f = BytesIO(b, 'w') |
21 | - >>> f.write(bytes.fromhex('ca fe ba be')) |
22 | - >>> f.write(bytes.fromhex('57 41 56 45')) |
23 | - >>> b |
24 | - bytes([202, 254, 186, 190, 87, 65, 86, 69]) |
25 | - """ |
26 | - |
27 | - def __init__(self, buf, mode='r'): |
28 | - """ Create a new BytesIO for reading or writing the given buffer. |
29 | - |
30 | - buf - Back-end buffer for this BytesIO. A bytes object. |
31 | - Actually, anything that supports len(), slice-assignment, |
32 | - and += will work. |
33 | - mode - One of 'r', 'w', 'a'. |
34 | - An optional 'b' is also allowed, but it doesn't do anything. |
35 | - """ |
36 | - # XXX many 'mode' possibilities aren't allowed yet: 'rw+Ut' |
37 | - if len(mode) == 2 and mode[-1] == 'b': |
38 | - mode = mode[:-1] # binary mode goes without saying |
39 | - if mode not in ('r', 'w', 'a'): |
40 | - raise ValueError("mode must be 'r', 'w', or 'a'") |
41 | - |
42 | - self._buf = buf |
43 | - self.mode = mode |
44 | - self.closed = False |
45 | - if self.mode == 'w': |
46 | - del buf[:] |
47 | - self._point = 0 |
48 | - elif self.mode == 'r': |
49 | - self._point = 0 |
50 | - else: # 'a' |
51 | - self._point = len(buf) |
52 | - |
53 | - def close(self): |
54 | - self.closed = True |
55 | - |
56 | - def _check_closed(self): |
57 | - if self.closed: |
58 | - raise ValueError("file is closed") |
59 | - |
60 | - def flush(self): |
61 | - self._check_closed() |
62 | - |
63 | - def next(self): |
64 | - line = self.readline() |
65 | - if len(line) == 0: |
66 | - raise StopIteration |
67 | - return line |
68 | - |
69 | - def read(self, size=None): |
70 | - self._check_closed() |
71 | - if size is None: |
72 | - e = len(self._buf) |
73 | - else: |
74 | - e = min(self._point + size, len(self._buf)) |
75 | - r = self._buf[self._point:e] |
76 | - self._point = e |
77 | - return r |
78 | - |
79 | - def readline(self, size=None): |
80 | - self._check_closed() |
81 | - die # XXX TODO - assume ascii and read a line |
82 | - |
83 | - def readlines(self, sizehint=None): |
84 | - # XXX TODO handle sizehint |
85 | - return list(self) |
86 | - |
87 | - def seek(self, offset, whence=0): |
88 | - self._check_closed() |
89 | - |
90 | - if whence == 0: |
91 | - self._point = offset |
92 | - elif whence == 1: |
93 | - self._point += offset |
94 | - elif whence == 2: |
95 | - self._point = len(self._buf) + offset |
96 | - else: |
97 | - raise ValueError("whence must be 0, 1, or 2") |
98 | - |
99 | - if self._point < 0: |
100 | - self._point = 0 # XXX is this right? |
101 | - |
102 | - def tell(self): |
103 | - self._check_closed() |
104 | - return self._point |
105 | - |
106 | - def truncate(self, size=None): |
107 | - self._check_closed() |
108 | - if size is None: |
109 | - size = self.tell() |
110 | - del self._buf[size:] |
111 | - |
112 | - def write(self, data): |
113 | - self._check_closed() |
114 | - amt = len(data) |
115 | - size = len(self._buf) |
116 | - if self.mode == 'a': |
117 | - self._point = size |
118 | - |
119 | - if self._point > size: |
120 | - if isinstance(b, bytes): |
121 | - blank = bytes([0]) |
122 | - else: |
123 | - # Don't know what default value to insert, unfortunately |
124 | - raise ValueError("can't write past the end of this object") |
125 | - self._buf += blank * (self._point - size) + data |
126 | - self._point = len(self._buf) |
127 | - else: |
128 | - p = self._point |
129 | - self._buf[p:p + amt] = data |
130 | - self._point = min(p + amt, len(self._buf)) |
131 | - |
132 | - def writelines(self, seq): |
133 | - for line in seq: |
134 | - self.write(line) |
135 | - |
136 | - def __iter__(self): |
137 | - return self |
138 | - |
139 | - @property |
140 | - def name(self): |
141 | - return repr(self) |
142 | |
143 | === removed directory 'python-for-subunit2junitxml/iso8601' |
144 | === removed file 'python-for-subunit2junitxml/iso8601/LICENSE' |
145 | --- python-for-subunit2junitxml/iso8601/LICENSE 2013-05-27 13:46:13 +0000 |
146 | +++ python-for-subunit2junitxml/iso8601/LICENSE 1970-01-01 00:00:00 +0000 |
147 | @@ -1,20 +0,0 @@ |
148 | -Copyright (c) 2007 Michael Twomey |
149 | - |
150 | -Permission is hereby granted, free of charge, to any person obtaining a |
151 | -copy of this software and associated documentation files (the |
152 | -"Software"), to deal in the Software without restriction, including |
153 | -without limitation the rights to use, copy, modify, merge, publish, |
154 | -distribute, sublicense, and/or sell copies of the Software, and to |
155 | -permit persons to whom the Software is furnished to do so, subject to |
156 | -the following conditions: |
157 | - |
158 | -The above copyright notice and this permission notice shall be included |
159 | -in all copies or substantial portions of the Software. |
160 | - |
161 | -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
162 | -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
163 | -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
164 | -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
165 | -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
166 | -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
167 | -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
168 | |
169 | === removed file 'python-for-subunit2junitxml/iso8601/README' |
170 | --- python-for-subunit2junitxml/iso8601/README 2013-05-27 13:46:13 +0000 |
171 | +++ python-for-subunit2junitxml/iso8601/README 1970-01-01 00:00:00 +0000 |
172 | @@ -1,26 +0,0 @@ |
173 | -A simple package to deal with ISO 8601 date time formats. |
174 | - |
175 | -ISO 8601 defines a neutral, unambiguous date string format, which also |
176 | -has the property of sorting naturally. |
177 | - |
178 | -e.g. YYYY-MM-DDTHH:MM:SSZ or 2007-01-25T12:00:00Z |
179 | - |
180 | -Currently this covers only the most common date formats encountered, not |
181 | -all of ISO 8601 is handled. |
182 | - |
183 | -Currently the following formats are handled: |
184 | - |
185 | -* 2006-01-01T00:00:00Z |
186 | -* 2006-01-01T00:00:00[+-]00:00 |
187 | - |
188 | -I'll add more as I encounter them in my day to day life. Patches with |
189 | -new formats and tests will be gratefully accepted of course :) |
190 | - |
191 | -References: |
192 | - |
193 | -* http://www.cl.cam.ac.uk/~mgk25/iso-time.html - simple overview |
194 | - |
195 | -* http://hydracen.com/dx/iso8601.htm - more detailed enumeration of |
196 | - valid formats. |
197 | - |
198 | -See the LICENSE file for the license this package is released under. |
199 | |
200 | === removed file 'python-for-subunit2junitxml/iso8601/README.subunit' |
201 | --- python-for-subunit2junitxml/iso8601/README.subunit 2013-05-27 13:46:13 +0000 |
202 | +++ python-for-subunit2junitxml/iso8601/README.subunit 1970-01-01 00:00:00 +0000 |
203 | @@ -1,5 +0,0 @@ |
204 | -This is a [slightly rearranged] import of http://pypi.python.org/pypi/iso8601/ |
205 | -version 0.1.4. The OS X hidden files have been stripped, and the package |
206 | -turned into a single module, to simplify installation. The remainder of the |
207 | -source distribution is included in the subunit source tree at python/iso8601 |
208 | -for reference. |
209 | |
210 | === removed file 'python-for-subunit2junitxml/iso8601/setup.py' |
211 | --- python-for-subunit2junitxml/iso8601/setup.py 2013-05-27 13:46:13 +0000 |
212 | +++ python-for-subunit2junitxml/iso8601/setup.py 1970-01-01 00:00:00 +0000 |
213 | @@ -1,58 +0,0 @@ |
214 | -try: |
215 | - from setuptools import setup |
216 | -except ImportError: |
217 | - from distutils import setup |
218 | - |
219 | -long_description="""Simple module to parse ISO 8601 dates |
220 | - |
221 | -This module parses the most common forms of ISO 8601 date strings (e.g. |
222 | -2007-01-14T20:34:22+00:00) into datetime objects. |
223 | - |
224 | ->>> import iso8601 |
225 | ->>> iso8601.parse_date("2007-01-25T12:00:00Z") |
226 | -datetime.datetime(2007, 1, 25, 12, 0, tzinfo=<iso8601.iso8601.Utc ...>) |
227 | ->>> |
228 | - |
229 | -Changes |
230 | -======= |
231 | - |
232 | -0.1.4 |
233 | ------ |
234 | - |
235 | -* The default_timezone argument wasn't being passed through correctly, |
236 | - UTC was being used in every case. Fixes issue 10. |
237 | - |
238 | -0.1.3 |
239 | ------ |
240 | - |
241 | -* Fixed the microsecond handling, the generated microsecond values were |
242 | - way too small. Fixes issue 9. |
243 | - |
244 | -0.1.2 |
245 | ------ |
246 | - |
247 | -* Adding ParseError to __all__ in iso8601 module, allows people to import it. |
248 | - Addresses issue 7. |
249 | -* Be a little more flexible when dealing with dates without leading zeroes. |
250 | - This violates the spec a little, but handles more dates as seen in the |
251 | - field. Addresses issue 6. |
252 | -* Allow date/time separators other than T. |
253 | - |
254 | -0.1.1 |
255 | ------ |
256 | - |
257 | -* When parsing dates without a timezone the specified default is used. If no |
258 | - default is specified then UTC is used. Addresses issue 4. |
259 | -""" |
260 | - |
261 | -setup( |
262 | - name="iso8601", |
263 | - version="0.1.4", |
264 | - description=long_description.split("\n")[0], |
265 | - long_description=long_description, |
266 | - author="Michael Twomey", |
267 | - author_email="micktwomey+iso8601@gmail.com", |
268 | - url="http://code.google.com/p/pyiso8601/", |
269 | - packages=["iso8601"], |
270 | - license="MIT", |
271 | -) |
272 | |
273 | === removed file 'python-for-subunit2junitxml/iso8601/test_iso8601.py' |
274 | --- python-for-subunit2junitxml/iso8601/test_iso8601.py 2013-05-27 13:46:13 +0000 |
275 | +++ python-for-subunit2junitxml/iso8601/test_iso8601.py 1970-01-01 00:00:00 +0000 |
276 | @@ -1,111 +0,0 @@ |
277 | -import iso8601 |
278 | - |
279 | -def test_iso8601_regex(): |
280 | - assert iso8601.ISO8601_REGEX.match("2006-10-11T00:14:33Z") |
281 | - |
282 | -def test_timezone_regex(): |
283 | - assert iso8601.TIMEZONE_REGEX.match("+01:00") |
284 | - assert iso8601.TIMEZONE_REGEX.match("+00:00") |
285 | - assert iso8601.TIMEZONE_REGEX.match("+01:20") |
286 | - assert iso8601.TIMEZONE_REGEX.match("-01:00") |
287 | - |
288 | -def test_parse_date(): |
289 | - d = iso8601.parse_date("2006-10-20T15:34:56Z") |
290 | - assert d.year == 2006 |
291 | - assert d.month == 10 |
292 | - assert d.day == 20 |
293 | - assert d.hour == 15 |
294 | - assert d.minute == 34 |
295 | - assert d.second == 56 |
296 | - assert d.tzinfo == iso8601.UTC |
297 | - |
298 | -def test_parse_date_fraction(): |
299 | - d = iso8601.parse_date("2006-10-20T15:34:56.123Z") |
300 | - assert d.year == 2006 |
301 | - assert d.month == 10 |
302 | - assert d.day == 20 |
303 | - assert d.hour == 15 |
304 | - assert d.minute == 34 |
305 | - assert d.second == 56 |
306 | - assert d.microsecond == 123000 |
307 | - assert d.tzinfo == iso8601.UTC |
308 | - |
309 | -def test_parse_date_fraction_2(): |
310 | - """From bug 6 |
311 | - |
312 | - """ |
313 | - d = iso8601.parse_date("2007-5-7T11:43:55.328Z'") |
314 | - assert d.year == 2007 |
315 | - assert d.month == 5 |
316 | - assert d.day == 7 |
317 | - assert d.hour == 11 |
318 | - assert d.minute == 43 |
319 | - assert d.second == 55 |
320 | - assert d.microsecond == 328000 |
321 | - assert d.tzinfo == iso8601.UTC |
322 | - |
323 | -def test_parse_date_tz(): |
324 | - d = iso8601.parse_date("2006-10-20T15:34:56.123+02:30") |
325 | - assert d.year == 2006 |
326 | - assert d.month == 10 |
327 | - assert d.day == 20 |
328 | - assert d.hour == 15 |
329 | - assert d.minute == 34 |
330 | - assert d.second == 56 |
331 | - assert d.microsecond == 123000 |
332 | - assert d.tzinfo.tzname(None) == "+02:30" |
333 | - offset = d.tzinfo.utcoffset(None) |
334 | - assert offset.days == 0 |
335 | - assert offset.seconds == 60 * 60 * 2.5 |
336 | - |
337 | -def test_parse_invalid_date(): |
338 | - try: |
339 | - iso8601.parse_date(None) |
340 | - except iso8601.ParseError: |
341 | - pass |
342 | - else: |
343 | - assert 1 == 2 |
344 | - |
345 | -def test_parse_invalid_date2(): |
346 | - try: |
347 | - iso8601.parse_date("23") |
348 | - except iso8601.ParseError: |
349 | - pass |
350 | - else: |
351 | - assert 1 == 2 |
352 | - |
353 | -def test_parse_no_timezone(): |
354 | - """issue 4 - Handle datetime string without timezone |
355 | - |
356 | - This tests what happens when you parse a date with no timezone. While not |
357 | - strictly correct this is quite common. I'll assume UTC for the time zone |
358 | - in this case. |
359 | - """ |
360 | - d = iso8601.parse_date("2007-01-01T08:00:00") |
361 | - assert d.year == 2007 |
362 | - assert d.month == 1 |
363 | - assert d.day == 1 |
364 | - assert d.hour == 8 |
365 | - assert d.minute == 0 |
366 | - assert d.second == 0 |
367 | - assert d.microsecond == 0 |
368 | - assert d.tzinfo == iso8601.UTC |
369 | - |
370 | -def test_parse_no_timezone_different_default(): |
371 | - tz = iso8601.FixedOffset(2, 0, "test offset") |
372 | - d = iso8601.parse_date("2007-01-01T08:00:00", default_timezone=tz) |
373 | - assert d.tzinfo == tz |
374 | - |
375 | -def test_space_separator(): |
376 | - """Handle a separator other than T |
377 | - |
378 | - """ |
379 | - d = iso8601.parse_date("2007-06-23 06:40:34.00Z") |
380 | - assert d.year == 2007 |
381 | - assert d.month == 6 |
382 | - assert d.day == 23 |
383 | - assert d.hour == 6 |
384 | - assert d.minute == 40 |
385 | - assert d.second == 34 |
386 | - assert d.microsecond == 0 |
387 | - assert d.tzinfo == iso8601.UTC |
388 | |
389 | === removed directory 'python-for-subunit2junitxml/junitxml' |
390 | === removed file 'python-for-subunit2junitxml/junitxml/__init__.py' |
391 | --- python-for-subunit2junitxml/junitxml/__init__.py 2013-05-27 13:46:13 +0000 |
392 | +++ python-for-subunit2junitxml/junitxml/__init__.py 1970-01-01 00:00:00 +0000 |
393 | @@ -1,221 +0,0 @@ |
394 | -# |
395 | -# junitxml: extensions to Python unittest to get output junitxml |
396 | -# Copyright (C) 2009 Robert Collins <robertc@robertcollins.net> |
397 | -# |
398 | -# Copying permitted under the LGPL-3 licence, included with this library. |
399 | - |
400 | -"""unittest compatible JUnit XML output.""" |
401 | - |
402 | - |
403 | -import datetime |
404 | -import re |
405 | -import time |
406 | -import unittest |
407 | - |
408 | -# same format as sys.version_info: "A tuple containing the five components of |
409 | -# the version number: major, minor, micro, releaselevel, and serial. All |
410 | -# values except releaselevel are integers; the release level is 'alpha', |
411 | -# 'beta', 'candidate', or 'final'. The version_info value corresponding to the |
412 | -# Python version 2.0 is (2, 0, 0, 'final', 0)." Additionally we use a |
413 | -# releaselevel of 'dev' for unreleased under-development code. |
414 | -# |
415 | -# If the releaselevel is 'alpha' then the major/minor/micro components are not |
416 | -# established at this point, and setup.py will use a version of next-$(revno). |
417 | -# If the releaselevel is 'final', then the tarball will be major.minor.micro. |
418 | -# Otherwise it is major.minor.micro~$(revno). |
419 | -__version__ = (0, 7, 0, 'alpha', 0) |
420 | - |
421 | - |
422 | -def test_suite(): |
423 | - import junitxml.tests |
424 | - return junitxml.tests.test_suite() |
425 | - |
426 | - |
427 | -class LocalTimezone(datetime.tzinfo): |
428 | - |
429 | - def __init__(self): |
430 | - self._offset = None |
431 | - |
432 | - # It seems that the minimal possible implementation is to just return all |
433 | - # None for every function, but then it breaks... |
434 | - def utcoffset(self, dt): |
435 | - if self._offset is None: |
436 | - t = 1260423030 # arbitrary, but doesn't handle dst very well |
437 | - dt = datetime.datetime |
438 | - self._offset = (dt.fromtimestamp(t) - dt.utcfromtimestamp(t)) |
439 | - return self._offset |
440 | - |
441 | - def dst(self, dt): |
442 | - return datetime.timedelta(0) |
443 | - |
444 | - def tzname(self, dt): |
445 | - return None |
446 | - |
447 | - |
448 | -def _error_name(eclass): |
449 | - module = eclass.__module__ |
450 | - if module not in ("__main__", "builtins", "exceptions"): |
451 | - return ".".join([module, eclass.__name__]) |
452 | - return eclass.__name__ |
453 | - |
454 | - |
455 | -_non_cdata = "[\0-\b\x0B-\x1F\uD800-\uDFFF\uFFFE\uFFFF]+" |
456 | -if "\\u" in _non_cdata: |
457 | - _non_cdata = _non_cdata.decode("unicode-escape") |
458 | - def _strip_invalid_chars(s, _sub=re.compile(_non_cdata, re.UNICODE).sub): |
459 | - if not isinstance(s, unicode): |
460 | - try: |
461 | - s = s.decode("utf-8") |
462 | - except UnicodeDecodeError: |
463 | - s = s.decode("ascii", "replace") |
464 | - return _sub("", s).encode("utf-8") |
465 | -else: |
466 | - def _strip_invalid_chars(s, _sub=re.compile(_non_cdata, re.UNICODE).sub): |
467 | - return _sub("", s) |
468 | -def _escape_content(s): |
469 | - return (_strip_invalid_chars(s) |
470 | - .replace("&", "&") |
471 | - .replace("<", "<") |
472 | - .replace("]]>", "]]>")) |
473 | -def _escape_attr(s): |
474 | - return (_strip_invalid_chars(s) |
475 | - .replace("&", "&") |
476 | - .replace("<", "<") |
477 | - .replace("]]>", "]]>") |
478 | - .replace('"', """) |
479 | - .replace("\t", "	") |
480 | - .replace("\n", "
")) |
481 | - |
482 | - |
483 | -class JUnitXmlResult(unittest.TestResult): |
484 | - """A TestResult which outputs JUnit compatible XML.""" |
485 | - |
486 | - def __init__(self, stream): |
487 | - """Create a JUnitXmlResult. |
488 | - |
489 | - :param stream: A stream to write results to. Note that due to the |
490 | - nature of JUnit XML output, nnothing will be written to the stream |
491 | - until stopTestRun() is called. |
492 | - """ |
493 | - self.__super = super(JUnitXmlResult, self) |
494 | - self.__super.__init__() |
495 | - # GZ 2010-09-03: We have a problem if passed a text stream in Python 3 |
496 | - # as really we want to write raw UTF-8 to ensure that |
497 | - # the encoding is not mangled later |
498 | - self._stream = stream |
499 | - self._results = [] |
500 | - self._set_time = None |
501 | - self._test_start = None |
502 | - self._run_start = None |
503 | - self._tz_info = None |
504 | - |
505 | - def startTestRun(self): |
506 | - """Start a test run.""" |
507 | - self._run_start = self._now() |
508 | - |
509 | - def _get_tzinfo(self): |
510 | - if self._tz_info is None: |
511 | - self._tz_info = LocalTimezone() |
512 | - return self._tz_info |
513 | - |
514 | - def _now(self): |
515 | - if self._set_time is not None: |
516 | - return self._set_time |
517 | - else: |
518 | - return datetime.datetime.now(self._get_tzinfo()) |
519 | - |
520 | - def time(self, a_datetime): |
521 | - self._set_time = a_datetime |
522 | - if (self._run_start is not None and |
523 | - self._run_start > a_datetime): |
524 | - self._run_start = a_datetime |
525 | - |
526 | - def startTest(self, test): |
527 | - self.__super.startTest(test) |
528 | - self._test_start = self._now() |
529 | - |
530 | - def _duration(self, from_datetime): |
531 | - try: |
532 | - delta = self._now() - from_datetime |
533 | - except TypeError: |
534 | - n = self._now() |
535 | - delta = datetime.timedelta(-1) |
536 | - seconds = delta.days * 3600*24 + delta.seconds |
537 | - return seconds + 0.000001 * delta.microseconds |
538 | - |
539 | - def _test_case_string(self, test): |
540 | - duration = self._duration(self._test_start) |
541 | - test_id = test.id() |
542 | - # Split on the last dot not inside a parameter |
543 | - class_end = test_id.rfind(".", 0, test_id.find("(")) |
544 | - if class_end == -1: |
545 | - classname, name = "", test_id |
546 | - else: |
547 | - classname, name = test_id[:class_end], test_id[class_end+1:] |
548 | - self._results.append('<testcase classname="%s" name="%s" ' |
549 | - 'time="%0.3f"' % (_escape_attr(classname), _escape_attr(name), duration)) |
550 | - |
551 | - def stopTestRun(self): |
552 | - """Stop a test run. |
553 | - |
554 | - This allows JUnitXmlResult to output the XML representation of the test |
555 | - run. |
556 | - """ |
557 | - duration = self._duration(self._run_start) |
558 | - self._stream.write('<testsuite errors="%d" failures="%d" name="" ' |
559 | - 'tests="%d" time="%0.3f">\n' % (len(self.errors), |
560 | - len(self.failures) + len(getattr(self, "unexpectedSuccesses", ())), |
561 | - self.testsRun, duration)) |
562 | - self._stream.write(''.join(self._results)) |
563 | - self._stream.write('</testsuite>\n') |
564 | - |
565 | - def addError(self, test, error): |
566 | - self.__super.addError(test, error) |
567 | - self._test_case_string(test) |
568 | - self._results.append('>\n') |
569 | - self._results.append('<error type="%s">%s</error>\n</testcase>\n' % ( |
570 | - _escape_attr(_error_name(error[0])), |
571 | - _escape_content(self._exc_info_to_string(error, test)))) |
572 | - |
573 | - def addFailure(self, test, error): |
574 | - self.__super.addFailure(test, error) |
575 | - self._test_case_string(test) |
576 | - self._results.append('>\n') |
577 | - self._results.append('<failure type="%s">%s</failure>\n</testcase>\n' % |
578 | - (_escape_attr(_error_name(error[0])), |
579 | - _escape_content(self._exc_info_to_string(error, test)))) |
580 | - |
581 | - def addSuccess(self, test): |
582 | - self.__super.addSuccess(test) |
583 | - self._test_case_string(test) |
584 | - self._results.append('/>\n') |
585 | - |
586 | - def addSkip(self, test, reason): |
587 | - try: |
588 | - self.__super.addSkip(test, reason) |
589 | - except AttributeError: |
590 | - # Python < 2.7|3.1 |
591 | - pass |
592 | - self._test_case_string(test) |
593 | - self._results.append('>\n') |
594 | - self._results.append('<skip>%s</skip>\n</testcase>\n'% _escape_attr(reason)) |
595 | - |
596 | - def addUnexpectedSuccess(self, test): |
597 | - try: |
598 | - self.__super.addUnexpectedSuccess(test) |
599 | - except AttributeError: |
600 | - # Python < 2.7|3.1 |
601 | - pass |
602 | - self._test_case_string(test) |
603 | - self._results.append('>\n') |
604 | - self._results.append('<failure type="unittest.case._UnexpectedSuccess"/>\n</testcase>\n') |
605 | - |
606 | - def addExpectedFailure(self, test, error): |
607 | - try: |
608 | - self.__super.addExpectedFailure(test, error) |
609 | - except AttributeError: |
610 | - # Python < 2.7|3.1 |
611 | - pass |
612 | - self._test_case_string(test) |
613 | - self._results.append('/>\n') |
614 | - |
615 | |
616 | === removed directory 'python-for-subunit2junitxml/junitxml/tests' |
617 | === removed file 'python-for-subunit2junitxml/junitxml/tests/__init__.py' |
618 | --- python-for-subunit2junitxml/junitxml/tests/__init__.py 2013-05-27 13:46:13 +0000 |
619 | +++ python-for-subunit2junitxml/junitxml/tests/__init__.py 1970-01-01 00:00:00 +0000 |
620 | @@ -1,16 +0,0 @@ |
621 | -# |
622 | -# junitxml: extensions to Python unittest to get output junitxml |
623 | -# Copyright (C) 2009 Robert Collins <robertc@robertcollins.net> |
624 | -# |
625 | -# Copying permitted under the LGPL-3 licence, included with this library. |
626 | - |
627 | -import unittest |
628 | - |
629 | -from junitxml.tests import ( |
630 | - test_junitxml, |
631 | - ) |
632 | - |
633 | -def test_suite(): |
634 | - return unittest.TestLoader().loadTestsFromNames([ |
635 | - 'junitxml.tests.test_junitxml', |
636 | - ]) |
637 | |
638 | === removed file 'python-for-subunit2junitxml/junitxml/tests/test_junitxml.py' |
639 | --- python-for-subunit2junitxml/junitxml/tests/test_junitxml.py 2013-05-27 13:46:13 +0000 |
640 | +++ python-for-subunit2junitxml/junitxml/tests/test_junitxml.py 1970-01-01 00:00:00 +0000 |
641 | @@ -1,327 +0,0 @@ |
642 | -# |
643 | -# junitxml: extensions to Python unittest to get output junitxml |
644 | -# Copyright (C) 2009 Robert Collins <robertc@robertcollins.net> |
645 | -# |
646 | -# Copying permitted under the LGPL-3 licence, included with this library. |
647 | - |
648 | - |
649 | -try: |
650 | - from cStringIO import StringIO |
651 | -except ImportError: |
652 | - from io import StringIO |
653 | -import datetime |
654 | -import re |
655 | -import sys |
656 | -import unittest |
657 | -import xml.dom.minidom |
658 | - |
659 | -import junitxml |
660 | - |
661 | -class TestImports(unittest.TestCase): |
662 | - |
663 | - def test_result(self): |
664 | - from junitxml import JUnitXmlResult |
665 | - |
666 | - |
667 | -class TestJUnitXmlResult__init__(unittest.TestCase): |
668 | - |
669 | - def test_with_stream(self): |
670 | - result = junitxml.JUnitXmlResult(StringIO()) |
671 | - |
672 | - |
673 | -class TestJUnitXmlResult(unittest.TestCase): |
674 | - |
675 | - def setUp(self): |
676 | - self.output = StringIO() |
677 | - self.result = junitxml.JUnitXmlResult(self.output) |
678 | - |
679 | - def get_output(self): |
680 | - output = self.output.getvalue() |
681 | - # Collapse detailed regions into specific strings we can match on |
682 | - return re.sub(r'(?s)<failure (.*?)>.*?</failure>', |
683 | - r'<failure \1>failure</failure>', re.sub( |
684 | - r'(?s)<error (.*?)>.*?</error>', r'<error \1>error</error>', |
685 | - re.sub(r'time="\d+\.\d+"', 'time="0.000"', output))) |
686 | - |
687 | - def run_test_or_simulate(self, test, method_name, manual_method, |
688 | - *manual_args): |
689 | - if getattr(test, method_name, None): |
690 | - test.run(self.result) |
691 | - else: |
692 | - # older python - manually execute |
693 | - self.result.startTest(test) |
694 | - manual_method(test, *manual_args) |
695 | - self.result.stopTest(test) |
696 | - |
697 | - def test_run_duration_handles_datestamping_in_the_past(self): |
698 | - # When used via subunit2junitxml, startTestRun is called before |
699 | - # any tz info in the test stream has been seen. |
700 | - # So, we use the earliest reported timestamp as the start time, |
701 | - # replacing _test_start if needed. |
702 | - self.result.startTestRun() # the time is now. |
703 | - # Lose an hour (peeks inside, a little naughty but not very). |
704 | - self.result.time(self.result._run_start - datetime.timedelta(0, 3600)) |
705 | - self.result.stopTestRun() |
706 | - self.assertEqual("""<testsuite errors="0" failures="0" name="" tests="0" time="0.000"> |
707 | -</testsuite> |
708 | -""", self.get_output()) |
709 | - |
710 | - def test_startTestRun_no_output(self): |
711 | - # startTestRun doesn't output anything, because JUnit wants an up-front |
712 | - # summary. |
713 | - self.result.startTestRun() |
714 | - self.assertEqual('', self.get_output()) |
715 | - |
716 | - def test_stopTestRun_outputs(self): |
717 | - # When stopTestRun is called, everything is output. |
718 | - self.result.startTestRun() |
719 | - self.result.stopTestRun() |
720 | - self.assertEqual("""<testsuite errors="0" failures="0" name="" tests="0" time="0.000"> |
721 | -</testsuite> |
722 | -""", self.get_output()) |
723 | - |
724 | - def test_test_count(self): |
725 | - class Passes(unittest.TestCase): |
726 | - def test_me(self): |
727 | - pass |
728 | - self.result.startTestRun() |
729 | - Passes("test_me").run(self.result) |
730 | - Passes("test_me").run(self.result) |
731 | - self.result.stopTestRun() |
732 | - # When tests are run, the number of tests is counted. |
733 | - output = self.get_output() |
734 | - self.assertTrue('tests="2"' in output) |
735 | - |
736 | - def test_test_id_with_parameter(self): |
737 | - class Passes(unittest.TestCase): |
738 | - def id(self): |
739 | - return unittest.TestCase.id(self) + '(version_1.6)' |
740 | - def test_me(self): |
741 | - pass |
742 | - self.result.startTestRun() |
743 | - Passes("test_me").run(self.result) |
744 | - self.result.stopTestRun() |
745 | - output = self.get_output() |
746 | - self.assertTrue('Passes" name="test_me(version_1.6)"' in output) |
747 | - |
748 | - def test_erroring_test(self): |
749 | - class Errors(unittest.TestCase): |
750 | - def test_me(self): |
751 | - 1/0 |
752 | - self.result.startTestRun() |
753 | - Errors("test_me").run(self.result) |
754 | - self.result.stopTestRun() |
755 | - self.assertEqual("""<testsuite errors="1" failures="0" name="" tests="1" time="0.000"> |
756 | -<testcase classname="junitxml.tests.test_junitxml.Errors" name="test_me" time="0.000"> |
757 | -<error type="ZeroDivisionError">error</error> |
758 | -</testcase> |
759 | -</testsuite> |
760 | -""", self.get_output()) |
761 | - |
762 | - def test_failing_test(self): |
763 | - class Fails(unittest.TestCase): |
764 | - def test_me(self): |
765 | - self.fail() |
766 | - self.result.startTestRun() |
767 | - Fails("test_me").run(self.result) |
768 | - self.result.stopTestRun() |
769 | - self.assertEqual("""<testsuite errors="0" failures="1" name="" tests="1" time="0.000"> |
770 | -<testcase classname="junitxml.tests.test_junitxml.Fails" name="test_me" time="0.000"> |
771 | -<failure type="AssertionError">failure</failure> |
772 | -</testcase> |
773 | -</testsuite> |
774 | -""", self.get_output()) |
775 | - |
776 | - def test_successful_test(self): |
777 | - class Passes(unittest.TestCase): |
778 | - def test_me(self): |
779 | - pass |
780 | - self.result.startTestRun() |
781 | - Passes("test_me").run(self.result) |
782 | - self.result.stopTestRun() |
783 | - self.assertEqual("""<testsuite errors="0" failures="0" name="" tests="1" time="0.000"> |
784 | -<testcase classname="junitxml.tests.test_junitxml.Passes" name="test_me" time="0.000"/> |
785 | -</testsuite> |
786 | -""", self.get_output()) |
787 | - |
788 | - def test_skip_test(self): |
789 | - class Skips(unittest.TestCase): |
790 | - def test_me(self): |
791 | - self.skipTest("yo") |
792 | - self.result.startTestRun() |
793 | - test = Skips("test_me") |
794 | - self.run_test_or_simulate(test, 'skipTest', self.result.addSkip, 'yo') |
795 | - self.result.stopTestRun() |
796 | - output = self.get_output() |
797 | - expected = """<testsuite errors="0" failures="0" name="" tests="1" time="0.000"> |
798 | -<testcase classname="junitxml.tests.test_junitxml.Skips" name="test_me" time="0.000"> |
799 | -<skip>yo</skip> |
800 | -</testcase> |
801 | -</testsuite> |
802 | -""" |
803 | - self.assertEqual(expected, output) |
804 | - |
805 | - def test_unexpected_success_test(self): |
806 | - class Succeeds(unittest.TestCase): |
807 | - def test_me(self): |
808 | - pass |
809 | - try: |
810 | - test_me = unittest.expectedFailure(test_me) |
811 | - except AttributeError: |
812 | - pass # Older python - just let the test pass |
813 | - self.result.startTestRun() |
814 | - Succeeds("test_me").run(self.result) |
815 | - self.result.stopTestRun() |
816 | - output = self.get_output() |
817 | - expected = """<testsuite errors="0" failures="1" name="" tests="1" time="0.000"> |
818 | -<testcase classname="junitxml.tests.test_junitxml.Succeeds" name="test_me" time="0.000"> |
819 | -<failure type="unittest.case._UnexpectedSuccess"/> |
820 | -</testcase> |
821 | -</testsuite> |
822 | -""" |
823 | - expected_old = """<testsuite errors="0" failures="0" name="" tests="1" time="0.000"> |
824 | -<testcase classname="junitxml.tests.test_junitxml.Succeeds" name="test_me" time="0.000"/> |
825 | -</testsuite> |
826 | -""" |
827 | - if output != expected_old: |
828 | - self.assertEqual(expected, output) |
829 | - |
830 | - def test_expected_failure_test(self): |
831 | - expected_failure_support = [True] |
832 | - class ExpectedFail(unittest.TestCase): |
833 | - def test_me(self): |
834 | - self.fail("fail") |
835 | - try: |
836 | - test_me = unittest.expectedFailure(test_me) |
837 | - except AttributeError: |
838 | - # Older python - just let the test fail |
839 | - expected_failure_support[0] = False |
840 | - self.result.startTestRun() |
841 | - ExpectedFail("test_me").run(self.result) |
842 | - self.result.stopTestRun() |
843 | - output = self.get_output() |
844 | - expected = """<testsuite errors="0" failures="0" name="" tests="1" time="0.000"> |
845 | -<testcase classname="junitxml.tests.test_junitxml.ExpectedFail" name="test_me" time="0.000"/> |
846 | -</testsuite> |
847 | -""" |
848 | - expected_old = """<testsuite errors="0" failures="1" name="" tests="1" time="0.000"> |
849 | -<testcase classname="junitxml.tests.test_junitxml.ExpectedFail" name="test_me" time="0.000"> |
850 | -<failure type="AssertionError">failure</failure> |
851 | -</testcase> |
852 | -</testsuite> |
853 | -""" |
854 | - if expected_failure_support[0]: |
855 | - self.assertEqual(expected, output) |
856 | - else: |
857 | - self.assertEqual(expected_old, output) |
858 | - |
859 | - |
860 | -class TestWellFormedXml(unittest.TestCase): |
861 | - """XML created should always be well formed even with odd test cases""" |
862 | - |
863 | - def _run_and_parse_test(self, case): |
864 | - output = StringIO() |
865 | - result = junitxml.JUnitXmlResult(output) |
866 | - result.startTestRun() |
867 | - case.run(result) |
868 | - result.stopTestRun() |
869 | - return xml.dom.minidom.parseString(output.getvalue()) |
870 | - |
871 | - def test_failure_with_amp(self): |
872 | - """Check the failure element content is escaped""" |
873 | - class FailWithAmp(unittest.TestCase): |
874 | - def runTest(self): |
875 | - self.fail("& should be escaped as &") |
876 | - doc = self._run_and_parse_test(FailWithAmp()) |
877 | - self.assertTrue( |
878 | - doc.getElementsByTagName("failure")[0].firstChild.nodeValue |
879 | - .endswith("AssertionError: & should be escaped as &\n")) |
880 | - |
881 | - def test_quotes_in_test_case_id(self): |
882 | - """Check that quotes in an attribute are escaped""" |
883 | - class QuoteId(unittest.TestCase): |
884 | - def id(self): |
885 | - return unittest.TestCase.id(self) + '("quotes")' |
886 | - def runTest(self): |
887 | - pass |
888 | - doc = self._run_and_parse_test(QuoteId()) |
889 | - self.assertEqual('runTest("quotes")', |
890 | - doc.getElementsByTagName("testcase")[0].getAttribute("name")) |
891 | - |
892 | - def test_skip_reason(self): |
893 | - """Check the skip element content is escaped""" |
894 | - class SkipWithLt(unittest.TestCase): |
895 | - def runTest(self): |
896 | - self.fail("version < 2.7") |
897 | - try: |
898 | - runTest = unittest.skip("2.7 <= version")(runTest) |
899 | - except AttributeError: |
900 | - self.has_skip = False |
901 | - else: |
902 | - self.has_skip = True |
903 | - doc = self._run_and_parse_test(SkipWithLt()) |
904 | - if self.has_skip: |
905 | - self.assertEqual('2.7 <= version', |
906 | - doc.getElementsByTagName("skip")[0].firstChild.nodeValue) |
907 | - else: |
908 | - self.assertTrue( |
909 | - doc.getElementsByTagName("failure")[0].firstChild.nodeValue |
910 | - .endswith("AssertionError: version < 2.7\n")) |
911 | - |
912 | - def test_error_with_control_characters(self): |
913 | - """Check C0 control characters are stripped rather than output""" |
914 | - class ErrorWithC0(unittest.TestCase): |
915 | - def runTest(self): |
916 | - raise ValueError("\x1F\x0E\x0C\x0B\x08\x01\x00lost control") |
917 | - doc = self._run_and_parse_test(ErrorWithC0()) |
918 | - self.assertTrue( |
919 | - doc.getElementsByTagName("error")[0].firstChild.nodeValue |
920 | - .endswith("ValueError: lost control\n")) |
921 | - |
922 | - def test_error_with_invalid_cdata(self): |
923 | - """Check unicode outside the valid cdata range is stripped""" |
924 | - if len("\uffff") == 1: |
925 | - # Basic str type supports unicode |
926 | - exception = ValueError("\ufffe\uffffEOF") |
927 | - else: |
928 | - class UTF8_Error(Exception): |
929 | - def __unicode__(self): |
930 | - return str(self).decode("UTF-8") |
931 | - exception = UTF8_Error("\xef\xbf\xbe\xef\xbf\xbfEOF") |
932 | - class ErrorWithBadUnicode(unittest.TestCase): |
933 | - def runTest(self): |
934 | - raise exception |
935 | - doc = self._run_and_parse_test(ErrorWithBadUnicode()) |
936 | - self.assertTrue( |
937 | - doc.getElementsByTagName("error")[0].firstChild.nodeValue |
938 | - .endswith("Error: EOF\n")) |
939 | - |
940 | - def test_error_with_surrogates(self): |
941 | - """Check unicode surrogates are handled properly, paired or otherwise |
942 | - |
943 | - This is a pain due to suboptimal unicode support in Python and the |
944 | - various changes in Python 3. On UCS-2 builds there is no easy way of |
945 | - getting rid of unpaired surrogates while leaving valid pairs alone, so |
946 | - this test doesn't require astral characters are kept there. |
947 | - """ |
948 | - if len("\uffff") == 1: |
949 | - exception = ValueError("paired: \U000201a2" |
950 | - " unpaired: "+chr(0xD800)+"-"+chr(0xDFFF)) |
951 | - astral_char = "\U000201a2" |
952 | - else: |
953 | - class UTF8_Error(Exception): |
954 | - def __unicode__(self): |
955 | - return str(self).decode("UTF-8") |
956 | - exception = UTF8_Error("paired: \xf0\xa0\x86\xa2" |
957 | - " unpaired: \xed\xa0\x80-\xed\xbf\xbf") |
958 | - astral_char = "\U000201a2".decode("unicode-escape") |
959 | - class ErrorWithSurrogates(unittest.TestCase): |
960 | - def runTest(self): |
961 | - raise exception |
962 | - doc = self._run_and_parse_test(ErrorWithSurrogates()) |
963 | - traceback = doc.getElementsByTagName("error")[0].firstChild.nodeValue |
964 | - if sys.maxunicode == 0xFFFF: |
965 | - pass # would be nice to handle astral characters properly even so |
966 | - else: |
967 | - self.assertTrue(astral_char in traceback) |
968 | - self.assertTrue(traceback.endswith(" unpaired: -\n")) |
969 | |
970 | === removed directory 'python-for-subunit2junitxml/subunit' |
971 | === removed file 'python-for-subunit2junitxml/subunit/__init__.py' |
972 | --- python-for-subunit2junitxml/subunit/__init__.py 2013-05-27 13:46:13 +0000 |
973 | +++ python-for-subunit2junitxml/subunit/__init__.py 1970-01-01 00:00:00 +0000 |
974 | @@ -1,1250 +0,0 @@ |
975 | -# |
976 | -# subunit: extensions to Python unittest to get test results from subprocesses. |
977 | -# Copyright (C) 2005 Robert Collins <robertc@robertcollins.net> |
978 | -# |
979 | -# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause |
980 | -# license at the users choice. A copy of both licenses are available in the |
981 | -# project source as Apache-2.0 and BSD. You may not use this file except in |
982 | -# compliance with one of these two licences. |
983 | -# |
984 | -# Unless required by applicable law or agreed to in writing, software |
985 | -# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT |
986 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
987 | -# license you chose for the specific language governing permissions and |
988 | -# limitations under that license. |
989 | -# |
990 | - |
991 | -"""Subunit - a streaming test protocol |
992 | - |
993 | -Overview |
994 | -++++++++ |
995 | - |
996 | -The ``subunit`` Python package provides a number of ``unittest`` extensions |
997 | -which can be used to cause tests to output Subunit, to parse Subunit streams |
998 | -into test activity, perform seamless test isolation within a regular test |
999 | -case and variously sort, filter and report on test runs. |
1000 | - |
1001 | - |
1002 | -Key Classes |
1003 | ------------ |
1004 | - |
1005 | -The ``subunit.TestProtocolClient`` class is a ``unittest.TestResult`` |
1006 | -extension which will translate a test run into a Subunit stream. |
1007 | - |
1008 | -The ``subunit.ProtocolTestCase`` class is an adapter between the Subunit wire |
1009 | -protocol and the ``unittest.TestCase`` object protocol. It is used to translate |
1010 | -a stream into a test run, which regular ``unittest.TestResult`` objects can |
1011 | -process and report/inspect. |
1012 | - |
1013 | -Subunit has support for non-blocking usage too, for use with asyncore or |
1014 | -Twisted. See the ``TestProtocolServer`` parser class for more details. |
1015 | - |
1016 | -Subunit includes extensions to the Python ``TestResult`` protocol. These are |
1017 | -all done in a compatible manner: ``TestResult`` objects that do not implement |
1018 | -the extension methods will not cause errors to be raised, instead the extension |
1019 | -will either lose fidelity (for instance, folding expected failures to success |
1020 | -in Python versions < 2.7 or 3.1), or discard the extended data (for extra |
1021 | -details, tags, timestamping and progress markers). |
1022 | - |
1023 | -The test outcome methods ``addSuccess``, ``addError``, ``addExpectedFailure``, |
1024 | -``addFailure``, ``addSkip`` take an optional keyword parameter ``details`` |
1025 | -which can be used instead of the usual python unittest parameter. |
1026 | -When used the value of details should be a dict from ``string`` to |
1027 | -``testtools.content.Content`` objects. This is a draft API being worked on with |
1028 | -the Python Testing In Python mail list, with the goal of permitting a common |
1029 | -way to provide additional data beyond a traceback, such as captured data from |
1030 | -disk, logging messages etc. The reference for this API is in testtools (0.9.0 |
1031 | -and newer). |
1032 | - |
1033 | -The ``tags(new_tags, gone_tags)`` method is called (if present) to add or |
1034 | -remove tags in the test run that is currently executing. If called when no |
1035 | -test is in progress (that is, if called outside of the ``startTest``, |
1036 | -``stopTest`` pair), the the tags apply to all sebsequent tests. If called |
1037 | -when a test is in progress, then the tags only apply to that test. |
1038 | - |
1039 | -The ``time(a_datetime)`` method is called (if present) when a ``time:`` |
1040 | -directive is encountered in a Subunit stream. This is used to tell a TestResult |
1041 | -about the time that events in the stream occured at, to allow reconstructing |
1042 | -test timing from a stream. |
1043 | - |
1044 | -The ``progress(offset, whence)`` method controls progress data for a stream. |
1045 | -The offset parameter is an int, and whence is one of subunit.PROGRESS_CUR, |
1046 | -subunit.PROGRESS_SET, PROGRESS_PUSH, PROGRESS_POP. Push and pop operations |
1047 | -ignore the offset parameter. |
1048 | - |
1049 | - |
1050 | -Python test support |
1051 | -------------------- |
1052 | - |
1053 | -``subunit.run`` is a convenience wrapper to run a Python test suite via |
1054 | -the command line, reporting via Subunit:: |
1055 | - |
1056 | - $ python -m subunit.run mylib.tests.test_suite |
1057 | - |
1058 | -The ``IsolatedTestSuite`` class is a TestSuite that forks before running its |
1059 | -tests, allowing isolation between the test runner and some tests. |
1060 | - |
1061 | -Similarly, ``IsolatedTestCase`` is a base class which can be subclassed to get |
1062 | -tests that will fork() before that individual test is run. |
1063 | - |
1064 | -`ExecTestCase`` is a convenience wrapper for running an external |
1065 | -program to get a Subunit stream and then report that back to an arbitrary |
1066 | -result object:: |
1067 | - |
1068 | - class AggregateTests(subunit.ExecTestCase): |
1069 | - |
1070 | - def test_script_one(self): |
1071 | - './bin/script_one' |
1072 | - |
1073 | - def test_script_two(self): |
1074 | - './bin/script_two' |
1075 | - |
1076 | - # Normally your normal test loading would take of this automatically, |
1077 | - # It is only spelt out in detail here for clarity. |
1078 | - suite = unittest.TestSuite([AggregateTests("test_script_one"), |
1079 | - AggregateTests("test_script_two")]) |
1080 | - # Create any TestResult class you like. |
1081 | - result = unittest._TextTestResult(sys.stdout) |
1082 | - # And run your suite as normal, Subunit will exec each external script as |
1083 | - # needed and report to your result object. |
1084 | - suite.run(result) |
1085 | - |
1086 | -Utility modules |
1087 | ---------------- |
1088 | - |
1089 | -* subunit.chunked contains HTTP chunked encoding/decoding logic. |
1090 | -* subunit.test_results contains TestResult helper classes. |
1091 | -""" |
1092 | - |
1093 | -import os |
1094 | -import re |
1095 | -import subprocess |
1096 | -import sys |
1097 | -import unittest |
1098 | - |
1099 | -from testtools import content, content_type, ExtendedToOriginalDecorator |
1100 | -from testtools.compat import _b, _u, BytesIO, StringIO |
1101 | -try: |
1102 | - from testtools.testresult.real import _StringException |
1103 | - RemoteException = _StringException |
1104 | - # For testing: different pythons have different str() implementations. |
1105 | - if sys.version_info > (3, 0): |
1106 | - _remote_exception_str = "testtools.testresult.real._StringException" |
1107 | - _remote_exception_str_chunked = "34\r\n" + _remote_exception_str |
1108 | - else: |
1109 | - _remote_exception_str = "_StringException" |
1110 | - _remote_exception_str_chunked = "1A\r\n" + _remote_exception_str |
1111 | -except ImportError: |
1112 | - raise ImportError ("testtools.testresult.real does not contain " |
1113 | - "_StringException, check your version.") |
1114 | -from testtools import testresult |
1115 | - |
1116 | -from subunit import chunked, details, iso8601, test_results |
1117 | - |
1118 | - |
1119 | -PROGRESS_SET = 0 |
1120 | -PROGRESS_CUR = 1 |
1121 | -PROGRESS_PUSH = 2 |
1122 | -PROGRESS_POP = 3 |
1123 | - |
1124 | - |
1125 | -def test_suite(): |
1126 | - import subunit.tests |
1127 | - return subunit.tests.test_suite() |
1128 | - |
1129 | - |
1130 | -def join_dir(base_path, path): |
1131 | - """ |
1132 | - Returns an absolute path to C{path}, calculated relative to the parent |
1133 | - of C{base_path}. |
1134 | - |
1135 | - @param base_path: A path to a file or directory. |
1136 | - @param path: An absolute path, or a path relative to the containing |
1137 | - directory of C{base_path}. |
1138 | - |
1139 | - @return: An absolute path to C{path}. |
1140 | - """ |
1141 | - return os.path.join(os.path.dirname(os.path.abspath(base_path)), path) |
1142 | - |
1143 | - |
1144 | -def tags_to_new_gone(tags): |
1145 | - """Split a list of tags into a new_set and a gone_set.""" |
1146 | - new_tags = set() |
1147 | - gone_tags = set() |
1148 | - for tag in tags: |
1149 | - if tag[0] == '-': |
1150 | - gone_tags.add(tag[1:]) |
1151 | - else: |
1152 | - new_tags.add(tag) |
1153 | - return new_tags, gone_tags |
1154 | - |
1155 | - |
1156 | -class DiscardStream(object): |
1157 | - """A filelike object which discards what is written to it.""" |
1158 | - |
1159 | - def write(self, bytes): |
1160 | - pass |
1161 | - |
1162 | - |
1163 | -class _ParserState(object): |
1164 | - """State for the subunit parser.""" |
1165 | - |
1166 | - def __init__(self, parser): |
1167 | - self.parser = parser |
1168 | - self._test_sym = (_b('test'), _b('testing')) |
1169 | - self._colon_sym = _b(':') |
1170 | - self._error_sym = (_b('error'),) |
1171 | - self._failure_sym = (_b('failure'),) |
1172 | - self._progress_sym = (_b('progress'),) |
1173 | - self._skip_sym = _b('skip') |
1174 | - self._success_sym = (_b('success'), _b('successful')) |
1175 | - self._tags_sym = (_b('tags'),) |
1176 | - self._time_sym = (_b('time'),) |
1177 | - self._xfail_sym = (_b('xfail'),) |
1178 | - self._uxsuccess_sym = (_b('uxsuccess'),) |
1179 | - self._start_simple = _u(" [") |
1180 | - self._start_multipart = _u(" [ multipart") |
1181 | - |
1182 | - def addError(self, offset, line): |
1183 | - """An 'error:' directive has been read.""" |
1184 | - self.parser.stdOutLineReceived(line) |
1185 | - |
1186 | - def addExpectedFail(self, offset, line): |
1187 | - """An 'xfail:' directive has been read.""" |
1188 | - self.parser.stdOutLineReceived(line) |
1189 | - |
1190 | - def addFailure(self, offset, line): |
1191 | - """A 'failure:' directive has been read.""" |
1192 | - self.parser.stdOutLineReceived(line) |
1193 | - |
1194 | - def addSkip(self, offset, line): |
1195 | - """A 'skip:' directive has been read.""" |
1196 | - self.parser.stdOutLineReceived(line) |
1197 | - |
1198 | - def addSuccess(self, offset, line): |
1199 | - """A 'success:' directive has been read.""" |
1200 | - self.parser.stdOutLineReceived(line) |
1201 | - |
1202 | - def lineReceived(self, line): |
1203 | - """a line has been received.""" |
1204 | - parts = line.split(None, 1) |
1205 | - if len(parts) == 2 and line.startswith(parts[0]): |
1206 | - cmd, rest = parts |
1207 | - offset = len(cmd) + 1 |
1208 | - cmd = cmd.rstrip(self._colon_sym) |
1209 | - if cmd in self._test_sym: |
1210 | - self.startTest(offset, line) |
1211 | - elif cmd in self._error_sym: |
1212 | - self.addError(offset, line) |
1213 | - elif cmd in self._failure_sym: |
1214 | - self.addFailure(offset, line) |
1215 | - elif cmd in self._progress_sym: |
1216 | - self.parser._handleProgress(offset, line) |
1217 | - elif cmd in self._skip_sym: |
1218 | - self.addSkip(offset, line) |
1219 | - elif cmd in self._success_sym: |
1220 | - self.addSuccess(offset, line) |
1221 | - elif cmd in self._tags_sym: |
1222 | - self.parser._handleTags(offset, line) |
1223 | - self.parser.subunitLineReceived(line) |
1224 | - elif cmd in self._time_sym: |
1225 | - self.parser._handleTime(offset, line) |
1226 | - self.parser.subunitLineReceived(line) |
1227 | - elif cmd in self._xfail_sym: |
1228 | - self.addExpectedFail(offset, line) |
1229 | - elif cmd in self._uxsuccess_sym: |
1230 | - self.addUnexpectedSuccess(offset, line) |
1231 | - else: |
1232 | - self.parser.stdOutLineReceived(line) |
1233 | - else: |
1234 | - self.parser.stdOutLineReceived(line) |
1235 | - |
1236 | - def lostConnection(self): |
1237 | - """Connection lost.""" |
1238 | - self.parser._lostConnectionInTest(_u('unknown state of ')) |
1239 | - |
1240 | - def startTest(self, offset, line): |
1241 | - """A test start command received.""" |
1242 | - self.parser.stdOutLineReceived(line) |
1243 | - |
1244 | - |
1245 | -class _InTest(_ParserState): |
1246 | - """State for the subunit parser after reading a test: directive.""" |
1247 | - |
1248 | - def _outcome(self, offset, line, no_details, details_state): |
1249 | - """An outcome directive has been read. |
1250 | - |
1251 | - :param no_details: Callable to call when no details are presented. |
1252 | - :param details_state: The state to switch to for details |
1253 | - processing of this outcome. |
1254 | - """ |
1255 | - test_name = line[offset:-1].decode('utf8') |
1256 | - if self.parser.current_test_description == test_name: |
1257 | - self.parser._state = self.parser._outside_test |
1258 | - self.parser.current_test_description = None |
1259 | - no_details() |
1260 | - self.parser.client.stopTest(self.parser._current_test) |
1261 | - self.parser._current_test = None |
1262 | - self.parser.subunitLineReceived(line) |
1263 | - elif self.parser.current_test_description + self._start_simple == \ |
1264 | - test_name: |
1265 | - self.parser._state = details_state |
1266 | - details_state.set_simple() |
1267 | - self.parser.subunitLineReceived(line) |
1268 | - elif self.parser.current_test_description + self._start_multipart == \ |
1269 | - test_name: |
1270 | - self.parser._state = details_state |
1271 | - details_state.set_multipart() |
1272 | - self.parser.subunitLineReceived(line) |
1273 | - else: |
1274 | - self.parser.stdOutLineReceived(line) |
1275 | - |
1276 | - def _error(self): |
1277 | - self.parser.client.addError(self.parser._current_test, |
1278 | - details={}) |
1279 | - |
1280 | - def addError(self, offset, line): |
1281 | - """An 'error:' directive has been read.""" |
1282 | - self._outcome(offset, line, self._error, |
1283 | - self.parser._reading_error_details) |
1284 | - |
1285 | - def _xfail(self): |
1286 | - self.parser.client.addExpectedFailure(self.parser._current_test, |
1287 | - details={}) |
1288 | - |
1289 | - def addExpectedFail(self, offset, line): |
1290 | - """An 'xfail:' directive has been read.""" |
1291 | - self._outcome(offset, line, self._xfail, |
1292 | - self.parser._reading_xfail_details) |
1293 | - |
1294 | - def _uxsuccess(self): |
1295 | - self.parser.client.addUnexpectedSuccess(self.parser._current_test) |
1296 | - |
1297 | - def addUnexpectedSuccess(self, offset, line): |
1298 | - """A 'uxsuccess:' directive has been read.""" |
1299 | - self._outcome(offset, line, self._uxsuccess, |
1300 | - self.parser._reading_uxsuccess_details) |
1301 | - |
1302 | - def _failure(self): |
1303 | - self.parser.client.addFailure(self.parser._current_test, details={}) |
1304 | - |
1305 | - def addFailure(self, offset, line): |
1306 | - """A 'failure:' directive has been read.""" |
1307 | - self._outcome(offset, line, self._failure, |
1308 | - self.parser._reading_failure_details) |
1309 | - |
1310 | - def _skip(self): |
1311 | - self.parser.client.addSkip(self.parser._current_test, details={}) |
1312 | - |
1313 | - def addSkip(self, offset, line): |
1314 | - """A 'skip:' directive has been read.""" |
1315 | - self._outcome(offset, line, self._skip, |
1316 | - self.parser._reading_skip_details) |
1317 | - |
1318 | - def _succeed(self): |
1319 | - self.parser.client.addSuccess(self.parser._current_test, details={}) |
1320 | - |
1321 | - def addSuccess(self, offset, line): |
1322 | - """A 'success:' directive has been read.""" |
1323 | - self._outcome(offset, line, self._succeed, |
1324 | - self.parser._reading_success_details) |
1325 | - |
1326 | - def lostConnection(self): |
1327 | - """Connection lost.""" |
1328 | - self.parser._lostConnectionInTest(_u('')) |
1329 | - |
1330 | - |
1331 | -class _OutSideTest(_ParserState): |
1332 | - """State for the subunit parser outside of a test context.""" |
1333 | - |
1334 | - def lostConnection(self): |
1335 | - """Connection lost.""" |
1336 | - |
1337 | - def startTest(self, offset, line): |
1338 | - """A test start command received.""" |
1339 | - self.parser._state = self.parser._in_test |
1340 | - test_name = line[offset:-1].decode('utf8') |
1341 | - self.parser._current_test = RemotedTestCase(test_name) |
1342 | - self.parser.current_test_description = test_name |
1343 | - self.parser.client.startTest(self.parser._current_test) |
1344 | - self.parser.subunitLineReceived(line) |
1345 | - |
1346 | - |
1347 | -class _ReadingDetails(_ParserState): |
1348 | - """Common logic for readin state details.""" |
1349 | - |
1350 | - def endDetails(self): |
1351 | - """The end of a details section has been reached.""" |
1352 | - self.parser._state = self.parser._outside_test |
1353 | - self.parser.current_test_description = None |
1354 | - self._report_outcome() |
1355 | - self.parser.client.stopTest(self.parser._current_test) |
1356 | - |
1357 | - def lineReceived(self, line): |
1358 | - """a line has been received.""" |
1359 | - self.details_parser.lineReceived(line) |
1360 | - self.parser.subunitLineReceived(line) |
1361 | - |
1362 | - def lostConnection(self): |
1363 | - """Connection lost.""" |
1364 | - self.parser._lostConnectionInTest(_u('%s report of ') % |
1365 | - self._outcome_label()) |
1366 | - |
1367 | - def _outcome_label(self): |
1368 | - """The label to describe this outcome.""" |
1369 | - raise NotImplementedError(self._outcome_label) |
1370 | - |
1371 | - def set_simple(self): |
1372 | - """Start a simple details parser.""" |
1373 | - self.details_parser = details.SimpleDetailsParser(self) |
1374 | - |
1375 | - def set_multipart(self): |
1376 | - """Start a multipart details parser.""" |
1377 | - self.details_parser = details.MultipartDetailsParser(self) |
1378 | - |
1379 | - |
1380 | -class _ReadingFailureDetails(_ReadingDetails): |
1381 | - """State for the subunit parser when reading failure details.""" |
1382 | - |
1383 | - def _report_outcome(self): |
1384 | - self.parser.client.addFailure(self.parser._current_test, |
1385 | - details=self.details_parser.get_details()) |
1386 | - |
1387 | - def _outcome_label(self): |
1388 | - return "failure" |
1389 | - |
1390 | - |
1391 | -class _ReadingErrorDetails(_ReadingDetails): |
1392 | - """State for the subunit parser when reading error details.""" |
1393 | - |
1394 | - def _report_outcome(self): |
1395 | - self.parser.client.addError(self.parser._current_test, |
1396 | - details=self.details_parser.get_details()) |
1397 | - |
1398 | - def _outcome_label(self): |
1399 | - return "error" |
1400 | - |
1401 | - |
1402 | -class _ReadingExpectedFailureDetails(_ReadingDetails): |
1403 | - """State for the subunit parser when reading xfail details.""" |
1404 | - |
1405 | - def _report_outcome(self): |
1406 | - self.parser.client.addExpectedFailure(self.parser._current_test, |
1407 | - details=self.details_parser.get_details()) |
1408 | - |
1409 | - def _outcome_label(self): |
1410 | - return "xfail" |
1411 | - |
1412 | - |
1413 | -class _ReadingUnexpectedSuccessDetails(_ReadingDetails): |
1414 | - """State for the subunit parser when reading uxsuccess details.""" |
1415 | - |
1416 | - def _report_outcome(self): |
1417 | - self.parser.client.addUnexpectedSuccess(self.parser._current_test, |
1418 | - details=self.details_parser.get_details()) |
1419 | - |
1420 | - def _outcome_label(self): |
1421 | - return "uxsuccess" |
1422 | - |
1423 | - |
1424 | -class _ReadingSkipDetails(_ReadingDetails): |
1425 | - """State for the subunit parser when reading skip details.""" |
1426 | - |
1427 | - def _report_outcome(self): |
1428 | - self.parser.client.addSkip(self.parser._current_test, |
1429 | - details=self.details_parser.get_details("skip")) |
1430 | - |
1431 | - def _outcome_label(self): |
1432 | - return "skip" |
1433 | - |
1434 | - |
1435 | -class _ReadingSuccessDetails(_ReadingDetails): |
1436 | - """State for the subunit parser when reading success details.""" |
1437 | - |
1438 | - def _report_outcome(self): |
1439 | - self.parser.client.addSuccess(self.parser._current_test, |
1440 | - details=self.details_parser.get_details("success")) |
1441 | - |
1442 | - def _outcome_label(self): |
1443 | - return "success" |
1444 | - |
1445 | - |
1446 | -class TestProtocolServer(object): |
1447 | - """A parser for subunit. |
1448 | - |
1449 | - :ivar tags: The current tags associated with the protocol stream. |
1450 | - """ |
1451 | - |
1452 | - def __init__(self, client, stream=None, forward_stream=None): |
1453 | - """Create a TestProtocolServer instance. |
1454 | - |
1455 | - :param client: An object meeting the unittest.TestResult protocol. |
1456 | - :param stream: The stream that lines received which are not part of the |
1457 | - subunit protocol should be written to. This allows custom handling |
1458 | - of mixed protocols. By default, sys.stdout will be used for |
1459 | - convenience. It should accept bytes to its write() method. |
1460 | - :param forward_stream: A stream to forward subunit lines to. This |
1461 | - allows a filter to forward the entire stream while still parsing |
1462 | - and acting on it. By default forward_stream is set to |
1463 | - DiscardStream() and no forwarding happens. |
1464 | - """ |
1465 | - self.client = ExtendedToOriginalDecorator(client) |
1466 | - if stream is None: |
1467 | - stream = sys.stdout |
1468 | - if sys.version_info > (3, 0): |
1469 | - stream = stream.buffer |
1470 | - self._stream = stream |
1471 | - self._forward_stream = forward_stream or DiscardStream() |
1472 | - # state objects we can switch too |
1473 | - self._in_test = _InTest(self) |
1474 | - self._outside_test = _OutSideTest(self) |
1475 | - self._reading_error_details = _ReadingErrorDetails(self) |
1476 | - self._reading_failure_details = _ReadingFailureDetails(self) |
1477 | - self._reading_skip_details = _ReadingSkipDetails(self) |
1478 | - self._reading_success_details = _ReadingSuccessDetails(self) |
1479 | - self._reading_xfail_details = _ReadingExpectedFailureDetails(self) |
1480 | - self._reading_uxsuccess_details = _ReadingUnexpectedSuccessDetails(self) |
1481 | - # start with outside test. |
1482 | - self._state = self._outside_test |
1483 | - # Avoid casts on every call |
1484 | - self._plusminus = _b('+-') |
1485 | - self._push_sym = _b('push') |
1486 | - self._pop_sym = _b('pop') |
1487 | - |
1488 | - def _handleProgress(self, offset, line): |
1489 | - """Process a progress directive.""" |
1490 | - line = line[offset:].strip() |
1491 | - if line[0] in self._plusminus: |
1492 | - whence = PROGRESS_CUR |
1493 | - delta = int(line) |
1494 | - elif line == self._push_sym: |
1495 | - whence = PROGRESS_PUSH |
1496 | - delta = None |
1497 | - elif line == self._pop_sym: |
1498 | - whence = PROGRESS_POP |
1499 | - delta = None |
1500 | - else: |
1501 | - whence = PROGRESS_SET |
1502 | - delta = int(line) |
1503 | - self.client.progress(delta, whence) |
1504 | - |
1505 | - def _handleTags(self, offset, line): |
1506 | - """Process a tags command.""" |
1507 | - tags = line[offset:].decode('utf8').split() |
1508 | - new_tags, gone_tags = tags_to_new_gone(tags) |
1509 | - self.client.tags(new_tags, gone_tags) |
1510 | - |
1511 | - def _handleTime(self, offset, line): |
1512 | - # Accept it, but do not do anything with it yet. |
1513 | - try: |
1514 | - event_time = iso8601.parse_date(line[offset:-1]) |
1515 | - except TypeError: |
1516 | - raise TypeError(_u("Failed to parse %r, got %r") |
1517 | - % (line, sys.exec_info[1])) |
1518 | - self.client.time(event_time) |
1519 | - |
1520 | - def lineReceived(self, line): |
1521 | - """Call the appropriate local method for the received line.""" |
1522 | - self._state.lineReceived(line) |
1523 | - |
1524 | - def _lostConnectionInTest(self, state_string): |
1525 | - error_string = _u("lost connection during %stest '%s'") % ( |
1526 | - state_string, self.current_test_description) |
1527 | - self.client.addError(self._current_test, RemoteError(error_string)) |
1528 | - self.client.stopTest(self._current_test) |
1529 | - |
1530 | - def lostConnection(self): |
1531 | - """The input connection has finished.""" |
1532 | - self._state.lostConnection() |
1533 | - |
1534 | - def readFrom(self, pipe): |
1535 | - """Blocking convenience API to parse an entire stream. |
1536 | - |
1537 | - :param pipe: A file-like object supporting readlines(). |
1538 | - :return: None. |
1539 | - """ |
1540 | - for line in pipe.readlines(): |
1541 | - self.lineReceived(line) |
1542 | - self.lostConnection() |
1543 | - |
1544 | - def _startTest(self, offset, line): |
1545 | - """Internal call to change state machine. Override startTest().""" |
1546 | - self._state.startTest(offset, line) |
1547 | - |
1548 | - def subunitLineReceived(self, line): |
1549 | - self._forward_stream.write(line) |
1550 | - |
1551 | - def stdOutLineReceived(self, line): |
1552 | - self._stream.write(line) |
1553 | - |
1554 | - |
1555 | -class TestProtocolClient(testresult.TestResult): |
1556 | - """A TestResult which generates a subunit stream for a test run. |
1557 | - |
1558 | - # Get a TestSuite or TestCase to run |
1559 | - suite = make_suite() |
1560 | - # Create a stream (any object with a 'write' method). This should accept |
1561 | - # bytes not strings: subunit is a byte orientated protocol. |
1562 | - stream = file('tests.log', 'wb') |
1563 | - # Create a subunit result object which will output to the stream |
1564 | - result = subunit.TestProtocolClient(stream) |
1565 | - # Optionally, to get timing data for performance analysis, wrap the |
1566 | - # serialiser with a timing decorator |
1567 | - result = subunit.test_results.AutoTimingTestResultDecorator(result) |
1568 | - # Run the test suite reporting to the subunit result object |
1569 | - suite.run(result) |
1570 | - # Close the stream. |
1571 | - stream.close() |
1572 | - """ |
1573 | - |
1574 | - def __init__(self, stream): |
1575 | - testresult.TestResult.__init__(self) |
1576 | - self._stream = stream |
1577 | - _make_stream_binary(stream) |
1578 | - self._progress_fmt = _b("progress: ") |
1579 | - self._bytes_eol = _b("\n") |
1580 | - self._progress_plus = _b("+") |
1581 | - self._progress_push = _b("push") |
1582 | - self._progress_pop = _b("pop") |
1583 | - self._empty_bytes = _b("") |
1584 | - self._start_simple = _b(" [\n") |
1585 | - self._end_simple = _b("]\n") |
1586 | - |
1587 | - def addError(self, test, error=None, details=None): |
1588 | - """Report an error in test test. |
1589 | - |
1590 | - Only one of error and details should be provided: conceptually there |
1591 | - are two separate methods: |
1592 | - addError(self, test, error) |
1593 | - addError(self, test, details) |
1594 | - |
1595 | - :param error: Standard unittest positional argument form - an |
1596 | - exc_info tuple. |
1597 | - :param details: New Testing-in-python drafted API; a dict from string |
1598 | - to subunit.Content objects. |
1599 | - """ |
1600 | - self._addOutcome("error", test, error=error, details=details) |
1601 | - |
1602 | - def addExpectedFailure(self, test, error=None, details=None): |
1603 | - """Report an expected failure in test test. |
1604 | - |
1605 | - Only one of error and details should be provided: conceptually there |
1606 | - are two separate methods: |
1607 | - addError(self, test, error) |
1608 | - addError(self, test, details) |
1609 | - |
1610 | - :param error: Standard unittest positional argument form - an |
1611 | - exc_info tuple. |
1612 | - :param details: New Testing-in-python drafted API; a dict from string |
1613 | - to subunit.Content objects. |
1614 | - """ |
1615 | - self._addOutcome("xfail", test, error=error, details=details) |
1616 | - |
1617 | - def addFailure(self, test, error=None, details=None): |
1618 | - """Report a failure in test test. |
1619 | - |
1620 | - Only one of error and details should be provided: conceptually there |
1621 | - are two separate methods: |
1622 | - addFailure(self, test, error) |
1623 | - addFailure(self, test, details) |
1624 | - |
1625 | - :param error: Standard unittest positional argument form - an |
1626 | - exc_info tuple. |
1627 | - :param details: New Testing-in-python drafted API; a dict from string |
1628 | - to subunit.Content objects. |
1629 | - """ |
1630 | - self._addOutcome("failure", test, error=error, details=details) |
1631 | - |
1632 | - def _addOutcome(self, outcome, test, error=None, details=None, |
1633 | - error_permitted=True): |
1634 | - """Report a failure in test test. |
1635 | - |
1636 | - Only one of error and details should be provided: conceptually there |
1637 | - are two separate methods: |
1638 | - addOutcome(self, test, error) |
1639 | - addOutcome(self, test, details) |
1640 | - |
1641 | - :param outcome: A string describing the outcome - used as the |
1642 | - event name in the subunit stream. |
1643 | - :param error: Standard unittest positional argument form - an |
1644 | - exc_info tuple. |
1645 | - :param details: New Testing-in-python drafted API; a dict from string |
1646 | - to subunit.Content objects. |
1647 | - :param error_permitted: If True then one and only one of error or |
1648 | - details must be supplied. If False then error must not be supplied |
1649 | - and details is still optional. """ |
1650 | - self._stream.write(_b("%s: %s" % (outcome, test.id()))) |
1651 | - if error_permitted: |
1652 | - if error is None and details is None: |
1653 | - raise ValueError |
1654 | - else: |
1655 | - if error is not None: |
1656 | - raise ValueError |
1657 | - if error is not None: |
1658 | - self._stream.write(self._start_simple) |
1659 | - # XXX: this needs to be made much stricter, along the lines of |
1660 | - # Martin[gz]'s work in testtools. Perhaps subunit can use that? |
1661 | - for line in self._exc_info_to_unicode(error, test).splitlines(): |
1662 | - self._stream.write(("%s\n" % line).encode('utf8')) |
1663 | - elif details is not None: |
1664 | - self._write_details(details) |
1665 | - else: |
1666 | - self._stream.write(_b("\n")) |
1667 | - if details is not None or error is not None: |
1668 | - self._stream.write(self._end_simple) |
1669 | - |
1670 | - def addSkip(self, test, reason=None, details=None): |
1671 | - """Report a skipped test.""" |
1672 | - if reason is None: |
1673 | - self._addOutcome("skip", test, error=None, details=details) |
1674 | - else: |
1675 | - self._stream.write(_b("skip: %s [\n" % test.id())) |
1676 | - self._stream.write(_b("%s\n" % reason)) |
1677 | - self._stream.write(self._end_simple) |
1678 | - |
1679 | - def addSuccess(self, test, details=None): |
1680 | - """Report a success in a test.""" |
1681 | - self._addOutcome("successful", test, details=details, error_permitted=False) |
1682 | - |
1683 | - def addUnexpectedSuccess(self, test, details=None): |
1684 | - """Report an unexpected success in test test. |
1685 | - |
1686 | - Details can optionally be provided: conceptually there |
1687 | - are two separate methods: |
1688 | - addError(self, test) |
1689 | - addError(self, test, details) |
1690 | - |
1691 | - :param details: New Testing-in-python drafted API; a dict from string |
1692 | - to subunit.Content objects. |
1693 | - """ |
1694 | - self._addOutcome("uxsuccess", test, details=details, |
1695 | - error_permitted=False) |
1696 | - |
1697 | - def startTest(self, test): |
1698 | - """Mark a test as starting its test run.""" |
1699 | - super(TestProtocolClient, self).startTest(test) |
1700 | - self._stream.write(_b("test: %s\n" % test.id())) |
1701 | - self._stream.flush() |
1702 | - |
1703 | - def stopTest(self, test): |
1704 | - super(TestProtocolClient, self).stopTest(test) |
1705 | - self._stream.flush() |
1706 | - |
1707 | - def progress(self, offset, whence): |
1708 | - """Provide indication about the progress/length of the test run. |
1709 | - |
1710 | - :param offset: Information about the number of tests remaining. If |
1711 | - whence is PROGRESS_CUR, then offset increases/decreases the |
1712 | - remaining test count. If whence is PROGRESS_SET, then offset |
1713 | - specifies exactly the remaining test count. |
1714 | - :param whence: One of PROGRESS_CUR, PROGRESS_SET, PROGRESS_PUSH, |
1715 | - PROGRESS_POP. |
1716 | - """ |
1717 | - if whence == PROGRESS_CUR and offset > -1: |
1718 | - prefix = self._progress_plus |
1719 | - offset = _b(str(offset)) |
1720 | - elif whence == PROGRESS_PUSH: |
1721 | - prefix = self._empty_bytes |
1722 | - offset = self._progress_push |
1723 | - elif whence == PROGRESS_POP: |
1724 | - prefix = self._empty_bytes |
1725 | - offset = self._progress_pop |
1726 | - else: |
1727 | - prefix = self._empty_bytes |
1728 | - offset = _b(str(offset)) |
1729 | - self._stream.write(self._progress_fmt + prefix + offset + |
1730 | - self._bytes_eol) |
1731 | - |
1732 | - def time(self, a_datetime): |
1733 | - """Inform the client of the time. |
1734 | - |
1735 | - ":param datetime: A datetime.datetime object. |
1736 | - """ |
1737 | - time = a_datetime.astimezone(iso8601.Utc()) |
1738 | - self._stream.write(_b("time: %04d-%02d-%02d %02d:%02d:%02d.%06dZ\n" % ( |
1739 | - time.year, time.month, time.day, time.hour, time.minute, |
1740 | - time.second, time.microsecond))) |
1741 | - |
1742 | - def _write_details(self, details): |
1743 | - """Output details to the stream. |
1744 | - |
1745 | - :param details: An extended details dict for a test outcome. |
1746 | - """ |
1747 | - self._stream.write(_b(" [ multipart\n")) |
1748 | - for name, content in sorted(details.items()): |
1749 | - self._stream.write(_b("Content-Type: %s/%s" % |
1750 | - (content.content_type.type, content.content_type.subtype))) |
1751 | - parameters = content.content_type.parameters |
1752 | - if parameters: |
1753 | - self._stream.write(_b(";")) |
1754 | - param_strs = [] |
1755 | - for param, value in parameters.items(): |
1756 | - param_strs.append("%s=%s" % (param, value)) |
1757 | - self._stream.write(_b(",".join(param_strs))) |
1758 | - self._stream.write(_b("\n%s\n" % name)) |
1759 | - encoder = chunked.Encoder(self._stream) |
1760 | - list(map(encoder.write, content.iter_bytes())) |
1761 | - encoder.close() |
1762 | - |
1763 | - def done(self): |
1764 | - """Obey the testtools result.done() interface.""" |
1765 | - |
1766 | - |
1767 | -def RemoteError(description=_u("")): |
1768 | - return (_StringException, _StringException(description), None) |
1769 | - |
1770 | - |
1771 | -class RemotedTestCase(unittest.TestCase): |
1772 | - """A class to represent test cases run in child processes. |
1773 | - |
1774 | - Instances of this class are used to provide the Python test API a TestCase |
1775 | - that can be printed to the screen, introspected for metadata and so on. |
1776 | - However, as they are a simply a memoisation of a test that was actually |
1777 | - run in the past by a separate process, they cannot perform any interactive |
1778 | - actions. |
1779 | - """ |
1780 | - |
1781 | - def __eq__ (self, other): |
1782 | - try: |
1783 | - return self.__description == other.__description |
1784 | - except AttributeError: |
1785 | - return False |
1786 | - |
1787 | - def __init__(self, description): |
1788 | - """Create a psuedo test case with description description.""" |
1789 | - self.__description = description |
1790 | - |
1791 | - def error(self, label): |
1792 | - raise NotImplementedError("%s on RemotedTestCases is not permitted." % |
1793 | - label) |
1794 | - |
1795 | - def setUp(self): |
1796 | - self.error("setUp") |
1797 | - |
1798 | - def tearDown(self): |
1799 | - self.error("tearDown") |
1800 | - |
1801 | - def shortDescription(self): |
1802 | - return self.__description |
1803 | - |
1804 | - def id(self): |
1805 | - return "%s" % (self.__description,) |
1806 | - |
1807 | - def __str__(self): |
1808 | - return "%s (%s)" % (self.__description, self._strclass()) |
1809 | - |
1810 | - def __repr__(self): |
1811 | - return "<%s description='%s'>" % \ |
1812 | - (self._strclass(), self.__description) |
1813 | - |
1814 | - def run(self, result=None): |
1815 | - if result is None: result = self.defaultTestResult() |
1816 | - result.startTest(self) |
1817 | - result.addError(self, RemoteError(_u("Cannot run RemotedTestCases.\n"))) |
1818 | - result.stopTest(self) |
1819 | - |
1820 | - def _strclass(self): |
1821 | - cls = self.__class__ |
1822 | - return "%s.%s" % (cls.__module__, cls.__name__) |
1823 | - |
1824 | - |
1825 | -class ExecTestCase(unittest.TestCase): |
1826 | - """A test case which runs external scripts for test fixtures.""" |
1827 | - |
1828 | - def __init__(self, methodName='runTest'): |
1829 | - """Create an instance of the class that will use the named test |
1830 | - method when executed. Raises a ValueError if the instance does |
1831 | - not have a method with the specified name. |
1832 | - """ |
1833 | - unittest.TestCase.__init__(self, methodName) |
1834 | - testMethod = getattr(self, methodName) |
1835 | - self.script = join_dir(sys.modules[self.__class__.__module__].__file__, |
1836 | - testMethod.__doc__) |
1837 | - |
1838 | - def countTestCases(self): |
1839 | - return 1 |
1840 | - |
1841 | - def run(self, result=None): |
1842 | - if result is None: result = self.defaultTestResult() |
1843 | - self._run(result) |
1844 | - |
1845 | - def debug(self): |
1846 | - """Run the test without collecting errors in a TestResult""" |
1847 | - self._run(testresult.TestResult()) |
1848 | - |
1849 | - def _run(self, result): |
1850 | - protocol = TestProtocolServer(result) |
1851 | - process = subprocess.Popen(self.script, shell=True, |
1852 | - stdout=subprocess.PIPE) |
1853 | - _make_stream_binary(process.stdout) |
1854 | - output = process.communicate()[0] |
1855 | - protocol.readFrom(BytesIO(output)) |
1856 | - |
1857 | - |
1858 | -class IsolatedTestCase(unittest.TestCase): |
1859 | - """A TestCase which executes in a forked process. |
1860 | - |
1861 | - Each test gets its own process, which has a performance overhead but will |
1862 | - provide excellent isolation from global state (such as django configs, |
1863 | - zope utilities and so on). |
1864 | - """ |
1865 | - |
1866 | - def run(self, result=None): |
1867 | - if result is None: result = self.defaultTestResult() |
1868 | - run_isolated(unittest.TestCase, self, result) |
1869 | - |
1870 | - |
1871 | -class IsolatedTestSuite(unittest.TestSuite): |
1872 | - """A TestSuite which runs its tests in a forked process. |
1873 | - |
1874 | - This decorator that will fork() before running the tests and report the |
1875 | - results from the child process using a Subunit stream. This is useful for |
1876 | - handling tests that mutate global state, or are testing C extensions that |
1877 | - could crash the VM. |
1878 | - """ |
1879 | - |
1880 | - def run(self, result=None): |
1881 | - if result is None: result = testresult.TestResult() |
1882 | - run_isolated(unittest.TestSuite, self, result) |
1883 | - |
1884 | - |
1885 | -def run_isolated(klass, self, result): |
1886 | - """Run a test suite or case in a subprocess, using the run method on klass. |
1887 | - """ |
1888 | - c2pread, c2pwrite = os.pipe() |
1889 | - # fixme - error -> result |
1890 | - # now fork |
1891 | - pid = os.fork() |
1892 | - if pid == 0: |
1893 | - # Child |
1894 | - # Close parent's pipe ends |
1895 | - os.close(c2pread) |
1896 | - # Dup fds for child |
1897 | - os.dup2(c2pwrite, 1) |
1898 | - # Close pipe fds. |
1899 | - os.close(c2pwrite) |
1900 | - |
1901 | - # at this point, sys.stdin is redirected, now we want |
1902 | - # to filter it to escape ]'s. |
1903 | - ### XXX: test and write that bit. |
1904 | - stream = os.fdopen(1, 'wb') |
1905 | - result = TestProtocolClient(stream) |
1906 | - klass.run(self, result) |
1907 | - stream.flush() |
1908 | - sys.stderr.flush() |
1909 | - # exit HARD, exit NOW. |
1910 | - os._exit(0) |
1911 | - else: |
1912 | - # Parent |
1913 | - # Close child pipe ends |
1914 | - os.close(c2pwrite) |
1915 | - # hookup a protocol engine |
1916 | - protocol = TestProtocolServer(result) |
1917 | - fileobj = os.fdopen(c2pread, 'rb') |
1918 | - protocol.readFrom(fileobj) |
1919 | - os.waitpid(pid, 0) |
1920 | - # TODO return code evaluation. |
1921 | - return result |
1922 | - |
1923 | - |
1924 | -def TAP2SubUnit(tap, subunit): |
1925 | - """Filter a TAP pipe into a subunit pipe. |
1926 | - |
1927 | - :param tap: A tap pipe/stream/file object. |
1928 | - :param subunit: A pipe/stream/file object to write subunit results to. |
1929 | - :return: The exit code to exit with. |
1930 | - """ |
1931 | - BEFORE_PLAN = 0 |
1932 | - AFTER_PLAN = 1 |
1933 | - SKIP_STREAM = 2 |
1934 | - state = BEFORE_PLAN |
1935 | - plan_start = 1 |
1936 | - plan_stop = 0 |
1937 | - def _skipped_test(subunit, plan_start): |
1938 | - # Some tests were skipped. |
1939 | - subunit.write('test test %d\n' % plan_start) |
1940 | - subunit.write('error test %d [\n' % plan_start) |
1941 | - subunit.write('test missing from TAP output\n') |
1942 | - subunit.write(']\n') |
1943 | - return plan_start + 1 |
1944 | - # Test data for the next test to emit |
1945 | - test_name = None |
1946 | - log = [] |
1947 | - result = None |
1948 | - def _emit_test(): |
1949 | - "write out a test" |
1950 | - if test_name is None: |
1951 | - return |
1952 | - subunit.write("test %s\n" % test_name) |
1953 | - if not log: |
1954 | - subunit.write("%s %s\n" % (result, test_name)) |
1955 | - else: |
1956 | - subunit.write("%s %s [\n" % (result, test_name)) |
1957 | - if log: |
1958 | - for line in log: |
1959 | - subunit.write("%s\n" % line) |
1960 | - subunit.write("]\n") |
1961 | - del log[:] |
1962 | - for line in tap: |
1963 | - if state == BEFORE_PLAN: |
1964 | - match = re.match("(\d+)\.\.(\d+)\s*(?:\#\s+(.*))?\n", line) |
1965 | - if match: |
1966 | - state = AFTER_PLAN |
1967 | - _, plan_stop, comment = match.groups() |
1968 | - plan_stop = int(plan_stop) |
1969 | - if plan_start > plan_stop and plan_stop == 0: |
1970 | - # skipped file |
1971 | - state = SKIP_STREAM |
1972 | - subunit.write("test file skip\n") |
1973 | - subunit.write("skip file skip [\n") |
1974 | - subunit.write("%s\n" % comment) |
1975 | - subunit.write("]\n") |
1976 | - continue |
1977 | - # not a plan line, or have seen one before |
1978 | - match = re.match("(ok|not ok)(?:\s+(\d+)?)?(?:\s+([^#]*[^#\s]+)\s*)?(?:\s+#\s+(TODO|SKIP|skip|todo)(?:\s+(.*))?)?\n", line) |
1979 | - if match: |
1980 | - # new test, emit current one. |
1981 | - _emit_test() |
1982 | - status, number, description, directive, directive_comment = match.groups() |
1983 | - if status == 'ok': |
1984 | - result = 'success' |
1985 | - else: |
1986 | - result = "failure" |
1987 | - if description is None: |
1988 | - description = '' |
1989 | - else: |
1990 | - description = ' ' + description |
1991 | - if directive is not None: |
1992 | - if directive.upper() == 'TODO': |
1993 | - result = 'xfail' |
1994 | - elif directive.upper() == 'SKIP': |
1995 | - result = 'skip' |
1996 | - if directive_comment is not None: |
1997 | - log.append(directive_comment) |
1998 | - if number is not None: |
1999 | - number = int(number) |
2000 | - while plan_start < number: |
2001 | - plan_start = _skipped_test(subunit, plan_start) |
2002 | - test_name = "test %d%s" % (plan_start, description) |
2003 | - plan_start += 1 |
2004 | - continue |
2005 | - match = re.match("Bail out\!(?:\s*(.*))?\n", line) |
2006 | - if match: |
2007 | - reason, = match.groups() |
2008 | - if reason is None: |
2009 | - extra = '' |
2010 | - else: |
2011 | - extra = ' %s' % reason |
2012 | - _emit_test() |
2013 | - test_name = "Bail out!%s" % extra |
2014 | - result = "error" |
2015 | - state = SKIP_STREAM |
2016 | - continue |
2017 | - match = re.match("\#.*\n", line) |
2018 | - if match: |
2019 | - log.append(line[:-1]) |
2020 | - continue |
2021 | - subunit.write(line) |
2022 | - _emit_test() |
2023 | - while plan_start <= plan_stop: |
2024 | - # record missed tests |
2025 | - plan_start = _skipped_test(subunit, plan_start) |
2026 | - return 0 |
2027 | - |
2028 | - |
2029 | -def tag_stream(original, filtered, tags): |
2030 | - """Alter tags on a stream. |
2031 | - |
2032 | - :param original: The input stream. |
2033 | - :param filtered: The output stream. |
2034 | - :param tags: The tags to apply. As in a normal stream - a list of 'TAG' or |
2035 | - '-TAG' commands. |
2036 | - |
2037 | - A 'TAG' command will add the tag to the output stream, |
2038 | - and override any existing '-TAG' command in that stream. |
2039 | - Specifically: |
2040 | - * A global 'tags: TAG' will be added to the start of the stream. |
2041 | - * Any tags commands with -TAG will have the -TAG removed. |
2042 | - |
2043 | - A '-TAG' command will remove the TAG command from the stream. |
2044 | - Specifically: |
2045 | - * A 'tags: -TAG' command will be added to the start of the stream. |
2046 | - * Any 'tags: TAG' command will have 'TAG' removed from it. |
2047 | - Additionally, any redundant tagging commands (adding a tag globally |
2048 | - present, or removing a tag globally removed) are stripped as a |
2049 | - by-product of the filtering. |
2050 | - :return: 0 |
2051 | - """ |
2052 | - new_tags, gone_tags = tags_to_new_gone(tags) |
2053 | - def write_tags(new_tags, gone_tags): |
2054 | - if new_tags or gone_tags: |
2055 | - filtered.write("tags: " + ' '.join(new_tags)) |
2056 | - if gone_tags: |
2057 | - for tag in gone_tags: |
2058 | - filtered.write("-" + tag) |
2059 | - filtered.write("\n") |
2060 | - write_tags(new_tags, gone_tags) |
2061 | - # TODO: use the protocol parser and thus don't mangle test comments. |
2062 | - for line in original: |
2063 | - if line.startswith("tags:"): |
2064 | - line_tags = line[5:].split() |
2065 | - line_new, line_gone = tags_to_new_gone(line_tags) |
2066 | - line_new = line_new - gone_tags |
2067 | - line_gone = line_gone - new_tags |
2068 | - write_tags(line_new, line_gone) |
2069 | - else: |
2070 | - filtered.write(line) |
2071 | - return 0 |
2072 | - |
2073 | - |
2074 | -class ProtocolTestCase(object): |
2075 | - """Subunit wire protocol to unittest.TestCase adapter. |
2076 | - |
2077 | - ProtocolTestCase honours the core of ``unittest.TestCase`` protocol - |
2078 | - calling a ProtocolTestCase or invoking the run() method will make a 'test |
2079 | - run' happen. The 'test run' will simply be a replay of the test activity |
2080 | - that has been encoded into the stream. The ``unittest.TestCase`` ``debug`` |
2081 | - and ``countTestCases`` methods are not supported because there isn't a |
2082 | - sensible mapping for those methods. |
2083 | - |
2084 | - # Get a stream (any object with a readline() method), in this case the |
2085 | - # stream output by the example from ``subunit.TestProtocolClient``. |
2086 | - stream = file('tests.log', 'rb') |
2087 | - # Create a parser which will read from the stream and emit |
2088 | - # activity to a unittest.TestResult when run() is called. |
2089 | - suite = subunit.ProtocolTestCase(stream) |
2090 | - # Create a result object to accept the contents of that stream. |
2091 | - result = unittest._TextTestResult(sys.stdout) |
2092 | - # 'run' the tests - process the stream and feed its contents to result. |
2093 | - suite.run(result) |
2094 | - stream.close() |
2095 | - |
2096 | - :seealso: TestProtocolServer (the subunit wire protocol parser). |
2097 | - """ |
2098 | - |
2099 | - def __init__(self, stream, passthrough=None, forward=False): |
2100 | - """Create a ProtocolTestCase reading from stream. |
2101 | - |
2102 | - :param stream: A filelike object which a subunit stream can be read |
2103 | - from. |
2104 | - :param passthrough: A stream pass non subunit input on to. If not |
2105 | - supplied, the TestProtocolServer default is used. |
2106 | - :param forward: A stream to pass subunit input on to. If not supplied |
2107 | - subunit input is not forwarded. |
2108 | - """ |
2109 | - self._stream = stream |
2110 | - _make_stream_binary(stream) |
2111 | - self._passthrough = passthrough |
2112 | - self._forward = forward |
2113 | - |
2114 | - def __call__(self, result=None): |
2115 | - return self.run(result) |
2116 | - |
2117 | - def run(self, result=None): |
2118 | - if result is None: |
2119 | - result = self.defaultTestResult() |
2120 | - protocol = TestProtocolServer(result, self._passthrough, self._forward) |
2121 | - line = self._stream.readline() |
2122 | - while line: |
2123 | - protocol.lineReceived(line) |
2124 | - line = self._stream.readline() |
2125 | - protocol.lostConnection() |
2126 | - |
2127 | - |
2128 | -class TestResultStats(testresult.TestResult): |
2129 | - """A pyunit TestResult interface implementation for making statistics. |
2130 | - |
2131 | - :ivar total_tests: The total tests seen. |
2132 | - :ivar passed_tests: The tests that passed. |
2133 | - :ivar failed_tests: The tests that failed. |
2134 | - :ivar seen_tags: The tags seen across all tests. |
2135 | - """ |
2136 | - |
2137 | - def __init__(self, stream): |
2138 | - """Create a TestResultStats which outputs to stream.""" |
2139 | - testresult.TestResult.__init__(self) |
2140 | - self._stream = stream |
2141 | - self.failed_tests = 0 |
2142 | - self.skipped_tests = 0 |
2143 | - self.seen_tags = set() |
2144 | - |
2145 | - @property |
2146 | - def total_tests(self): |
2147 | - return self.testsRun |
2148 | - |
2149 | - def addError(self, test, err, details=None): |
2150 | - self.failed_tests += 1 |
2151 | - |
2152 | - def addFailure(self, test, err, details=None): |
2153 | - self.failed_tests += 1 |
2154 | - |
2155 | - def addSkip(self, test, reason, details=None): |
2156 | - self.skipped_tests += 1 |
2157 | - |
2158 | - def formatStats(self): |
2159 | - self._stream.write("Total tests: %5d\n" % self.total_tests) |
2160 | - self._stream.write("Passed tests: %5d\n" % self.passed_tests) |
2161 | - self._stream.write("Failed tests: %5d\n" % self.failed_tests) |
2162 | - self._stream.write("Skipped tests: %5d\n" % self.skipped_tests) |
2163 | - tags = sorted(self.seen_tags) |
2164 | - self._stream.write("Seen tags: %s\n" % (", ".join(tags))) |
2165 | - |
2166 | - @property |
2167 | - def passed_tests(self): |
2168 | - return self.total_tests - self.failed_tests - self.skipped_tests |
2169 | - |
2170 | - def tags(self, new_tags, gone_tags): |
2171 | - """Accumulate the seen tags.""" |
2172 | - self.seen_tags.update(new_tags) |
2173 | - |
2174 | - def wasSuccessful(self): |
2175 | - """Tells whether or not this result was a success""" |
2176 | - return self.failed_tests == 0 |
2177 | - |
2178 | - |
2179 | -def get_default_formatter(): |
2180 | - """Obtain the default formatter to write to. |
2181 | - |
2182 | - :return: A file-like object. |
2183 | - """ |
2184 | - formatter = os.getenv("SUBUNIT_FORMATTER") |
2185 | - if formatter: |
2186 | - return os.popen(formatter, "w") |
2187 | - else: |
2188 | - stream = sys.stdout |
2189 | - if sys.version_info > (3, 0): |
2190 | - stream = stream.buffer |
2191 | - return stream |
2192 | - |
2193 | - |
2194 | -if sys.version_info > (3, 0): |
2195 | - from io import UnsupportedOperation as _NoFilenoError |
2196 | -else: |
2197 | - _NoFilenoError = AttributeError |
2198 | - |
2199 | -def read_test_list(path): |
2200 | - """Read a list of test ids from a file on disk. |
2201 | - |
2202 | - :param path: Path to the file |
2203 | - :return: Sequence of test ids |
2204 | - """ |
2205 | - f = open(path, 'rb') |
2206 | - try: |
2207 | - return [l.rstrip("\n") for l in f.readlines()] |
2208 | - finally: |
2209 | - f.close() |
2210 | - |
2211 | - |
2212 | -def _make_stream_binary(stream): |
2213 | - """Ensure that a stream will be binary safe. See _make_binary_on_windows.""" |
2214 | - try: |
2215 | - fileno = stream.fileno() |
2216 | - except _NoFilenoError: |
2217 | - return |
2218 | - _make_binary_on_windows(fileno) |
2219 | - |
2220 | -def _make_binary_on_windows(fileno): |
2221 | - """Win32 mangles \r\n to \n and that breaks streams. See bug lp:505078.""" |
2222 | - if sys.platform == "win32": |
2223 | - import msvcrt |
2224 | - msvcrt.setmode(fileno, os.O_BINARY) |
2225 | |
2226 | === removed file 'python-for-subunit2junitxml/subunit/chunked.py' |
2227 | --- python-for-subunit2junitxml/subunit/chunked.py 2013-05-27 13:46:13 +0000 |
2228 | +++ python-for-subunit2junitxml/subunit/chunked.py 1970-01-01 00:00:00 +0000 |
2229 | @@ -1,185 +0,0 @@ |
2230 | -# |
2231 | -# subunit: extensions to python unittest to get test results from subprocesses. |
2232 | -# Copyright (C) 2005 Robert Collins <robertc@robertcollins.net> |
2233 | -# Copyright (C) 2011 Martin Pool <mbp@sourcefrog.net> |
2234 | -# |
2235 | -# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause |
2236 | -# license at the users choice. A copy of both licenses are available in the |
2237 | -# project source as Apache-2.0 and BSD. You may not use this file except in |
2238 | -# compliance with one of these two licences. |
2239 | -# |
2240 | -# Unless required by applicable law or agreed to in writing, software |
2241 | -# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT |
2242 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
2243 | -# license you chose for the specific language governing permissions and |
2244 | -# limitations under that license. |
2245 | -# |
2246 | - |
2247 | -"""Encoder/decoder for http style chunked encoding.""" |
2248 | - |
2249 | -from testtools.compat import _b |
2250 | - |
2251 | -empty = _b('') |
2252 | - |
2253 | -class Decoder(object): |
2254 | - """Decode chunked content to a byte stream.""" |
2255 | - |
2256 | - def __init__(self, output, strict=True): |
2257 | - """Create a decoder decoding to output. |
2258 | - |
2259 | - :param output: A file-like object. Bytes written to the Decoder are |
2260 | - decoded to strip off the chunking and written to the output. |
2261 | - Up to a full write worth of data or a single control line may be |
2262 | - buffered (whichever is larger). The close method should be called |
2263 | - when no more data is available, to detect short streams; the |
2264 | - write method will return none-None when the end of a stream is |
2265 | - detected. The output object must accept bytes objects. |
2266 | - |
2267 | - :param strict: If True (the default), the decoder will not knowingly |
2268 | - accept input that is not conformant to the HTTP specification. |
2269 | - (This does not imply that it will catch every nonconformance.) |
2270 | - If False, it will accept incorrect input that is still |
2271 | - unambiguous. |
2272 | - """ |
2273 | - self.output = output |
2274 | - self.buffered_bytes = [] |
2275 | - self.state = self._read_length |
2276 | - self.body_length = 0 |
2277 | - self.strict = strict |
2278 | - self._match_chars = _b("0123456789abcdefABCDEF\r\n") |
2279 | - self._slash_n = _b('\n') |
2280 | - self._slash_r = _b('\r') |
2281 | - self._slash_rn = _b('\r\n') |
2282 | - self._slash_nr = _b('\n\r') |
2283 | - |
2284 | - def close(self): |
2285 | - """Close the decoder. |
2286 | - |
2287 | - :raises ValueError: If the stream is incomplete ValueError is raised. |
2288 | - """ |
2289 | - if self.state != self._finished: |
2290 | - raise ValueError("incomplete stream") |
2291 | - |
2292 | - def _finished(self): |
2293 | - """Finished reading, return any remaining bytes.""" |
2294 | - if self.buffered_bytes: |
2295 | - buffered_bytes = self.buffered_bytes |
2296 | - self.buffered_bytes = [] |
2297 | - return empty.join(buffered_bytes) |
2298 | - else: |
2299 | - raise ValueError("stream is finished") |
2300 | - |
2301 | - def _read_body(self): |
2302 | - """Pass body bytes to the output.""" |
2303 | - while self.body_length and self.buffered_bytes: |
2304 | - if self.body_length >= len(self.buffered_bytes[0]): |
2305 | - self.output.write(self.buffered_bytes[0]) |
2306 | - self.body_length -= len(self.buffered_bytes[0]) |
2307 | - del self.buffered_bytes[0] |
2308 | - # No more data available. |
2309 | - if not self.body_length: |
2310 | - self.state = self._read_length |
2311 | - else: |
2312 | - self.output.write(self.buffered_bytes[0][:self.body_length]) |
2313 | - self.buffered_bytes[0] = \ |
2314 | - self.buffered_bytes[0][self.body_length:] |
2315 | - self.body_length = 0 |
2316 | - self.state = self._read_length |
2317 | - return self.state() |
2318 | - |
2319 | - def _read_length(self): |
2320 | - """Try to decode a length from the bytes.""" |
2321 | - count_chars = [] |
2322 | - for bytes in self.buffered_bytes: |
2323 | - for pos in range(len(bytes)): |
2324 | - byte = bytes[pos:pos+1] |
2325 | - if byte not in self._match_chars: |
2326 | - break |
2327 | - count_chars.append(byte) |
2328 | - if byte == self._slash_n: |
2329 | - break |
2330 | - if not count_chars: |
2331 | - return |
2332 | - if count_chars[-1] != self._slash_n: |
2333 | - return |
2334 | - count_str = empty.join(count_chars) |
2335 | - if self.strict: |
2336 | - if count_str[-2:] != self._slash_rn: |
2337 | - raise ValueError("chunk header invalid: %r" % count_str) |
2338 | - if self._slash_r in count_str[:-2]: |
2339 | - raise ValueError("too many CRs in chunk header %r" % count_str) |
2340 | - self.body_length = int(count_str.rstrip(self._slash_nr), 16) |
2341 | - excess_bytes = len(count_str) |
2342 | - while excess_bytes: |
2343 | - if excess_bytes >= len(self.buffered_bytes[0]): |
2344 | - excess_bytes -= len(self.buffered_bytes[0]) |
2345 | - del self.buffered_bytes[0] |
2346 | - else: |
2347 | - self.buffered_bytes[0] = self.buffered_bytes[0][excess_bytes:] |
2348 | - excess_bytes = 0 |
2349 | - if not self.body_length: |
2350 | - self.state = self._finished |
2351 | - if not self.buffered_bytes: |
2352 | - # May not call into self._finished with no buffered data. |
2353 | - return empty |
2354 | - else: |
2355 | - self.state = self._read_body |
2356 | - return self.state() |
2357 | - |
2358 | - def write(self, bytes): |
2359 | - """Decode bytes to the output stream. |
2360 | - |
2361 | - :raises ValueError: If the stream has already seen the end of file |
2362 | - marker. |
2363 | - :returns: None, or the excess bytes beyond the end of file marker. |
2364 | - """ |
2365 | - if bytes: |
2366 | - self.buffered_bytes.append(bytes) |
2367 | - return self.state() |
2368 | - |
2369 | - |
2370 | -class Encoder(object): |
2371 | - """Encode content to a stream using HTTP Chunked coding.""" |
2372 | - |
2373 | - def __init__(self, output): |
2374 | - """Create an encoder encoding to output. |
2375 | - |
2376 | - :param output: A file-like object. Bytes written to the Encoder |
2377 | - will be encoded using HTTP chunking. Small writes may be buffered |
2378 | - and the ``close`` method must be called to finish the stream. |
2379 | - """ |
2380 | - self.output = output |
2381 | - self.buffered_bytes = [] |
2382 | - self.buffer_size = 0 |
2383 | - |
2384 | - def flush(self, extra_len=0): |
2385 | - """Flush the encoder to the output stream. |
2386 | - |
2387 | - :param extra_len: Increase the size of the chunk by this many bytes |
2388 | - to allow for a subsequent write. |
2389 | - """ |
2390 | - if not self.buffer_size and not extra_len: |
2391 | - return |
2392 | - buffered_bytes = self.buffered_bytes |
2393 | - buffer_size = self.buffer_size |
2394 | - self.buffered_bytes = [] |
2395 | - self.buffer_size = 0 |
2396 | - self.output.write(_b("%X\r\n" % (buffer_size + extra_len))) |
2397 | - if buffer_size: |
2398 | - self.output.write(empty.join(buffered_bytes)) |
2399 | - return True |
2400 | - |
2401 | - def write(self, bytes): |
2402 | - """Encode bytes to the output stream.""" |
2403 | - bytes_len = len(bytes) |
2404 | - if self.buffer_size + bytes_len >= 65536: |
2405 | - self.flush(bytes_len) |
2406 | - self.output.write(bytes) |
2407 | - else: |
2408 | - self.buffered_bytes.append(bytes) |
2409 | - self.buffer_size += bytes_len |
2410 | - |
2411 | - def close(self): |
2412 | - """Finish the stream. This does not close the output stream.""" |
2413 | - self.flush() |
2414 | - self.output.write(_b("0\r\n")) |
2415 | |
2416 | === removed file 'python-for-subunit2junitxml/subunit/details.py' |
2417 | --- python-for-subunit2junitxml/subunit/details.py 2013-05-27 13:46:13 +0000 |
2418 | +++ python-for-subunit2junitxml/subunit/details.py 1970-01-01 00:00:00 +0000 |
2419 | @@ -1,119 +0,0 @@ |
2420 | -# |
2421 | -# subunit: extensions to Python unittest to get test results from subprocesses. |
2422 | -# Copyright (C) 2005 Robert Collins <robertc@robertcollins.net> |
2423 | -# |
2424 | -# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause |
2425 | -# license at the users choice. A copy of both licenses are available in the |
2426 | -# project source as Apache-2.0 and BSD. You may not use this file except in |
2427 | -# compliance with one of these two licences. |
2428 | -# |
2429 | -# Unless required by applicable law or agreed to in writing, software |
2430 | -# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT |
2431 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
2432 | -# license you chose for the specific language governing permissions and |
2433 | -# limitations under that license. |
2434 | -# |
2435 | - |
2436 | -"""Handlers for outcome details.""" |
2437 | - |
2438 | -from testtools import content, content_type |
2439 | -from testtools.compat import _b, BytesIO |
2440 | - |
2441 | -from subunit import chunked |
2442 | - |
2443 | -end_marker = _b("]\n") |
2444 | -quoted_marker = _b(" ]") |
2445 | -empty = _b('') |
2446 | - |
2447 | - |
2448 | -class DetailsParser(object): |
2449 | - """Base class/API reference for details parsing.""" |
2450 | - |
2451 | - |
2452 | -class SimpleDetailsParser(DetailsParser): |
2453 | - """Parser for single-part [] delimited details.""" |
2454 | - |
2455 | - def __init__(self, state): |
2456 | - self._message = _b("") |
2457 | - self._state = state |
2458 | - |
2459 | - def lineReceived(self, line): |
2460 | - if line == end_marker: |
2461 | - self._state.endDetails() |
2462 | - return |
2463 | - if line[0:2] == quoted_marker: |
2464 | - # quoted ] start |
2465 | - self._message += line[1:] |
2466 | - else: |
2467 | - self._message += line |
2468 | - |
2469 | - def get_details(self, style=None): |
2470 | - result = {} |
2471 | - if not style: |
2472 | - # We know that subunit/testtools serialise [] formatted |
2473 | - # tracebacks as utf8, but perhaps we need a ReplacingContent |
2474 | - # or something like that. |
2475 | - result['traceback'] = content.Content( |
2476 | - content_type.ContentType("text", "x-traceback", |
2477 | - {"charset": "utf8"}), |
2478 | - lambda:[self._message]) |
2479 | - else: |
2480 | - if style == 'skip': |
2481 | - name = 'reason' |
2482 | - else: |
2483 | - name = 'message' |
2484 | - result[name] = content.Content( |
2485 | - content_type.ContentType("text", "plain"), |
2486 | - lambda:[self._message]) |
2487 | - return result |
2488 | - |
2489 | - def get_message(self): |
2490 | - return self._message |
2491 | - |
2492 | - |
2493 | -class MultipartDetailsParser(DetailsParser): |
2494 | - """Parser for multi-part [] surrounded MIME typed chunked details.""" |
2495 | - |
2496 | - def __init__(self, state): |
2497 | - self._state = state |
2498 | - self._details = {} |
2499 | - self._parse_state = self._look_for_content |
2500 | - |
2501 | - def _look_for_content(self, line): |
2502 | - if line == end_marker: |
2503 | - self._state.endDetails() |
2504 | - return |
2505 | - # TODO error handling |
2506 | - field, value = line[:-1].decode('utf8').split(' ', 1) |
2507 | - try: |
2508 | - main, sub = value.split('/') |
2509 | - except ValueError: |
2510 | - raise ValueError("Invalid MIME type %r" % value) |
2511 | - self._content_type = content_type.ContentType(main, sub) |
2512 | - self._parse_state = self._get_name |
2513 | - |
2514 | - def _get_name(self, line): |
2515 | - self._name = line[:-1].decode('utf8') |
2516 | - self._body = BytesIO() |
2517 | - self._chunk_parser = chunked.Decoder(self._body) |
2518 | - self._parse_state = self._feed_chunks |
2519 | - |
2520 | - def _feed_chunks(self, line): |
2521 | - residue = self._chunk_parser.write(line) |
2522 | - if residue is not None: |
2523 | - # Line based use always ends on no residue. |
2524 | - assert residue == empty, 'residue: %r' % (residue,) |
2525 | - body = self._body |
2526 | - self._details[self._name] = content.Content( |
2527 | - self._content_type, lambda:[body.getvalue()]) |
2528 | - self._chunk_parser.close() |
2529 | - self._parse_state = self._look_for_content |
2530 | - |
2531 | - def get_details(self, for_skip=False): |
2532 | - return self._details |
2533 | - |
2534 | - def get_message(self): |
2535 | - return None |
2536 | - |
2537 | - def lineReceived(self, line): |
2538 | - self._parse_state(line) |
2539 | |
2540 | === removed file 'python-for-subunit2junitxml/subunit/iso8601.py' |
2541 | --- python-for-subunit2junitxml/subunit/iso8601.py 2013-05-27 13:46:13 +0000 |
2542 | +++ python-for-subunit2junitxml/subunit/iso8601.py 1970-01-01 00:00:00 +0000 |
2543 | @@ -1,133 +0,0 @@ |
2544 | -# Copyright (c) 2007 Michael Twomey |
2545 | -# |
2546 | -# Permission is hereby granted, free of charge, to any person obtaining a |
2547 | -# copy of this software and associated documentation files (the |
2548 | -# "Software"), to deal in the Software without restriction, including |
2549 | -# without limitation the rights to use, copy, modify, merge, publish, |
2550 | -# distribute, sublicense, and/or sell copies of the Software, and to |
2551 | -# permit persons to whom the Software is furnished to do so, subject to |
2552 | -# the following conditions: |
2553 | -# |
2554 | -# The above copyright notice and this permission notice shall be included |
2555 | -# in all copies or substantial portions of the Software. |
2556 | -# |
2557 | -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
2558 | -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
2559 | -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
2560 | -# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
2561 | -# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
2562 | -# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
2563 | -# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
2564 | - |
2565 | -"""ISO 8601 date time string parsing |
2566 | - |
2567 | -Basic usage: |
2568 | ->>> import iso8601 |
2569 | ->>> iso8601.parse_date("2007-01-25T12:00:00Z") |
2570 | -datetime.datetime(2007, 1, 25, 12, 0, tzinfo=<iso8601.iso8601.Utc ...>) |
2571 | ->>> |
2572 | - |
2573 | -""" |
2574 | - |
2575 | -from datetime import datetime, timedelta, tzinfo |
2576 | -import re |
2577 | -import sys |
2578 | - |
2579 | -__all__ = ["parse_date", "ParseError"] |
2580 | - |
2581 | -# Adapted from http://delete.me.uk/2005/03/iso8601.html |
2582 | -ISO8601_REGEX_PATTERN = (r"(?P<year>[0-9]{4})(-(?P<month>[0-9]{1,2})(-(?P<day>[0-9]{1,2})" |
2583 | - r"((?P<separator>.)(?P<hour>[0-9]{2}):(?P<minute>[0-9]{2})(:(?P<second>[0-9]{2})(\.(?P<fraction>[0-9]+))?)?" |
2584 | - r"(?P<timezone>Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?" |
2585 | -) |
2586 | -TIMEZONE_REGEX_PATTERN = "(?P<prefix>[+-])(?P<hours>[0-9]{2}).(?P<minutes>[0-9]{2})" |
2587 | -ISO8601_REGEX = re.compile(ISO8601_REGEX_PATTERN.encode('utf8')) |
2588 | -TIMEZONE_REGEX = re.compile(TIMEZONE_REGEX_PATTERN.encode('utf8')) |
2589 | - |
2590 | -zulu = "Z".encode('latin-1') |
2591 | -minus = "-".encode('latin-1') |
2592 | - |
2593 | -if sys.version_info < (3, 0): |
2594 | - bytes = str |
2595 | - |
2596 | - |
2597 | -class ParseError(Exception): |
2598 | - """Raised when there is a problem parsing a date string""" |
2599 | - |
2600 | -# Yoinked from python docs |
2601 | -ZERO = timedelta(0) |
2602 | -class Utc(tzinfo): |
2603 | - """UTC |
2604 | - |
2605 | - """ |
2606 | - def utcoffset(self, dt): |
2607 | - return ZERO |
2608 | - |
2609 | - def tzname(self, dt): |
2610 | - return "UTC" |
2611 | - |
2612 | - def dst(self, dt): |
2613 | - return ZERO |
2614 | -UTC = Utc() |
2615 | - |
2616 | -class FixedOffset(tzinfo): |
2617 | - """Fixed offset in hours and minutes from UTC |
2618 | - |
2619 | - """ |
2620 | - def __init__(self, offset_hours, offset_minutes, name): |
2621 | - self.__offset = timedelta(hours=offset_hours, minutes=offset_minutes) |
2622 | - self.__name = name |
2623 | - |
2624 | - def utcoffset(self, dt): |
2625 | - return self.__offset |
2626 | - |
2627 | - def tzname(self, dt): |
2628 | - return self.__name |
2629 | - |
2630 | - def dst(self, dt): |
2631 | - return ZERO |
2632 | - |
2633 | - def __repr__(self): |
2634 | - return "<FixedOffset %r>" % self.__name |
2635 | - |
2636 | -def parse_timezone(tzstring, default_timezone=UTC): |
2637 | - """Parses ISO 8601 time zone specs into tzinfo offsets |
2638 | - |
2639 | - """ |
2640 | - if tzstring == zulu: |
2641 | - return default_timezone |
2642 | - # This isn't strictly correct, but it's common to encounter dates without |
2643 | - # timezones so I'll assume the default (which defaults to UTC). |
2644 | - # Addresses issue 4. |
2645 | - if tzstring is None: |
2646 | - return default_timezone |
2647 | - m = TIMEZONE_REGEX.match(tzstring) |
2648 | - prefix, hours, minutes = m.groups() |
2649 | - hours, minutes = int(hours), int(minutes) |
2650 | - if prefix == minus: |
2651 | - hours = -hours |
2652 | - minutes = -minutes |
2653 | - return FixedOffset(hours, minutes, tzstring) |
2654 | - |
2655 | -def parse_date(datestring, default_timezone=UTC): |
2656 | - """Parses ISO 8601 dates into datetime objects |
2657 | - |
2658 | - The timezone is parsed from the date string. However it is quite common to |
2659 | - have dates without a timezone (not strictly correct). In this case the |
2660 | - default timezone specified in default_timezone is used. This is UTC by |
2661 | - default. |
2662 | - """ |
2663 | - if not isinstance(datestring, bytes): |
2664 | - raise ParseError("Expecting bytes %r" % datestring) |
2665 | - m = ISO8601_REGEX.match(datestring) |
2666 | - if not m: |
2667 | - raise ParseError("Unable to parse date string %r" % datestring) |
2668 | - groups = m.groupdict() |
2669 | - tz = parse_timezone(groups["timezone"], default_timezone=default_timezone) |
2670 | - if groups["fraction"] is None: |
2671 | - groups["fraction"] = 0 |
2672 | - else: |
2673 | - groups["fraction"] = int(float("0.%s" % groups["fraction"]) * 1e6) |
2674 | - return datetime(int(groups["year"]), int(groups["month"]), int(groups["day"]), |
2675 | - int(groups["hour"]), int(groups["minute"]), int(groups["second"]), |
2676 | - int(groups["fraction"]), tz) |
2677 | |
2678 | === removed file 'python-for-subunit2junitxml/subunit/progress_model.py' |
2679 | --- python-for-subunit2junitxml/subunit/progress_model.py 2013-05-27 13:46:13 +0000 |
2680 | +++ python-for-subunit2junitxml/subunit/progress_model.py 1970-01-01 00:00:00 +0000 |
2681 | @@ -1,106 +0,0 @@ |
2682 | -# |
2683 | -# subunit: extensions to Python unittest to get test results from subprocesses. |
2684 | -# Copyright (C) 2009 Robert Collins <robertc@robertcollins.net> |
2685 | -# |
2686 | -# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause |
2687 | -# license at the users choice. A copy of both licenses are available in the |
2688 | -# project source as Apache-2.0 and BSD. You may not use this file except in |
2689 | -# compliance with one of these two licences. |
2690 | -# |
2691 | -# Unless required by applicable law or agreed to in writing, software |
2692 | -# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT |
2693 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
2694 | -# license you chose for the specific language governing permissions and |
2695 | -# limitations under that license. |
2696 | -# |
2697 | - |
2698 | -"""Support for dealing with progress state.""" |
2699 | - |
2700 | -class ProgressModel(object): |
2701 | - """A model of progress indicators as subunit defines it. |
2702 | - |
2703 | - Instances of this class represent a single logical operation that is |
2704 | - progressing. The operation may have many steps, and some of those steps may |
2705 | - supply their own progress information. ProgressModel uses a nested concept |
2706 | - where the overall state can be pushed, creating new starting state, and |
2707 | - later pushed to return to the prior state. Many user interfaces will want |
2708 | - to display an overall summary though, and accordingly the pos() and width() |
2709 | - methods return overall summary information rather than information on the |
2710 | - current subtask. |
2711 | - |
2712 | - The default state is 0/0 - indicating that the overall progress is unknown. |
2713 | - Anytime the denominator of pos/width is 0, rendering of a ProgressModel |
2714 | - should should take this into consideration. |
2715 | - |
2716 | - :ivar: _tasks. This private attribute stores the subtasks. Each is a tuple: |
2717 | - pos, width, overall_numerator, overall_denominator. The overall fields |
2718 | - store the calculated overall numerator and denominator for the state |
2719 | - that was pushed. |
2720 | - """ |
2721 | - |
2722 | - def __init__(self): |
2723 | - """Create a ProgressModel. |
2724 | - |
2725 | - The new model has no progress data at all - it will claim a summary |
2726 | - width of zero and position of 0. |
2727 | - """ |
2728 | - self._tasks = [] |
2729 | - self.push() |
2730 | - |
2731 | - def adjust_width(self, offset): |
2732 | - """Adjust the with of the current subtask.""" |
2733 | - self._tasks[-1][1] += offset |
2734 | - |
2735 | - def advance(self): |
2736 | - """Advance the current subtask.""" |
2737 | - self._tasks[-1][0] += 1 |
2738 | - |
2739 | - def pop(self): |
2740 | - """Pop a subtask off the ProgressModel. |
2741 | - |
2742 | - See push for a description of how push and pop work. |
2743 | - """ |
2744 | - self._tasks.pop() |
2745 | - |
2746 | - def pos(self): |
2747 | - """Return how far through the operation has progressed.""" |
2748 | - if not self._tasks: |
2749 | - return 0 |
2750 | - task = self._tasks[-1] |
2751 | - if len(self._tasks) > 1: |
2752 | - # scale up the overall pos by the current task or preserve it if |
2753 | - # no current width is known. |
2754 | - offset = task[2] * (task[1] or 1) |
2755 | - else: |
2756 | - offset = 0 |
2757 | - return offset + task[0] |
2758 | - |
2759 | - def push(self): |
2760 | - """Push a new subtask. |
2761 | - |
2762 | - After pushing a new subtask, the overall progress hasn't changed. Calls |
2763 | - to adjust_width, advance, set_width will only after the progress within |
2764 | - the range that calling 'advance' would have before - the subtask |
2765 | - represents progressing one step in the earlier task. |
2766 | - |
2767 | - Call pop() to restore the progress model to the state before push was |
2768 | - called. |
2769 | - """ |
2770 | - self._tasks.append([0, 0, self.pos(), self.width()]) |
2771 | - |
2772 | - def set_width(self, width): |
2773 | - """Set the width of the current subtask.""" |
2774 | - self._tasks[-1][1] = width |
2775 | - |
2776 | - def width(self): |
2777 | - """Return the total width of the operation.""" |
2778 | - if not self._tasks: |
2779 | - return 0 |
2780 | - task = self._tasks[-1] |
2781 | - if len(self._tasks) > 1: |
2782 | - # scale up the overall width by the current task or preserve it if |
2783 | - # no current width is known. |
2784 | - return task[3] * (task[1] or 1) |
2785 | - else: |
2786 | - return task[1] |
2787 | - |
2788 | |
2789 | === removed file 'python-for-subunit2junitxml/subunit/run.py' |
2790 | --- python-for-subunit2junitxml/subunit/run.py 2013-05-27 13:46:13 +0000 |
2791 | +++ python-for-subunit2junitxml/subunit/run.py 1970-01-01 00:00:00 +0000 |
2792 | @@ -1,73 +0,0 @@ |
2793 | -#!/usr/bin/python |
2794 | -# |
2795 | -# Simple subunit testrunner for python |
2796 | -# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007 |
2797 | -# |
2798 | -# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause |
2799 | -# license at the users choice. A copy of both licenses are available in the |
2800 | -# project source as Apache-2.0 and BSD. You may not use this file except in |
2801 | -# compliance with one of these two licences. |
2802 | -# |
2803 | -# Unless required by applicable law or agreed to in writing, software |
2804 | -# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT |
2805 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
2806 | -# license you chose for the specific language governing permissions and |
2807 | -# limitations under that license. |
2808 | -# |
2809 | - |
2810 | -"""Run a unittest testcase reporting results as Subunit. |
2811 | - |
2812 | - $ python -m subunit.run mylib.tests.test_suite |
2813 | -""" |
2814 | - |
2815 | -import sys |
2816 | - |
2817 | -from subunit import TestProtocolClient, get_default_formatter |
2818 | -from testtools.run import ( |
2819 | - BUFFEROUTPUT, |
2820 | - CATCHBREAK, |
2821 | - FAILFAST, |
2822 | - TestProgram, |
2823 | - USAGE_AS_MAIN, |
2824 | - ) |
2825 | - |
2826 | - |
2827 | -class SubunitTestRunner(object): |
2828 | - def __init__(self, stream=sys.stdout): |
2829 | - self.stream = stream |
2830 | - |
2831 | - def run(self, test): |
2832 | - "Run the given test case or test suite." |
2833 | - result = TestProtocolClient(self.stream) |
2834 | - test(result) |
2835 | - return result |
2836 | - |
2837 | - |
2838 | -class SubunitTestProgram(TestProgram): |
2839 | - |
2840 | - USAGE = USAGE_AS_MAIN |
2841 | - |
2842 | - def usageExit(self, msg=None): |
2843 | - if msg: |
2844 | - print msg |
2845 | - usage = {'progName': self.progName, 'catchbreak': '', 'failfast': '', |
2846 | - 'buffer': ''} |
2847 | - if self.failfast != False: |
2848 | - usage['failfast'] = FAILFAST |
2849 | - if self.catchbreak != False: |
2850 | - usage['catchbreak'] = CATCHBREAK |
2851 | - if self.buffer != False: |
2852 | - usage['buffer'] = BUFFEROUTPUT |
2853 | - usage_text = self.USAGE % usage |
2854 | - usage_lines = usage_text.split('\n') |
2855 | - usage_lines.insert(2, "Run a test suite with a subunit reporter.") |
2856 | - usage_lines.insert(3, "") |
2857 | - print('\n'.join(usage_lines)) |
2858 | - sys.exit(2) |
2859 | - |
2860 | - |
2861 | -if __name__ == '__main__': |
2862 | - stream = get_default_formatter() |
2863 | - runner = SubunitTestRunner(stream) |
2864 | - SubunitTestProgram(module=None, argv=sys.argv, testRunner=runner, |
2865 | - stdout=sys.stdout) |
2866 | |
2867 | === removed file 'python-for-subunit2junitxml/subunit/test_results.py' |
2868 | --- python-for-subunit2junitxml/subunit/test_results.py 2013-05-27 13:46:13 +0000 |
2869 | +++ python-for-subunit2junitxml/subunit/test_results.py 1970-01-01 00:00:00 +0000 |
2870 | @@ -1,492 +0,0 @@ |
2871 | -# |
2872 | -# subunit: extensions to Python unittest to get test results from subprocesses. |
2873 | -# Copyright (C) 2009 Robert Collins <robertc@robertcollins.net> |
2874 | -# |
2875 | -# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause |
2876 | -# license at the users choice. A copy of both licenses are available in the |
2877 | -# project source as Apache-2.0 and BSD. You may not use this file except in |
2878 | -# compliance with one of these two licences. |
2879 | -# |
2880 | -# Unless required by applicable law or agreed to in writing, software |
2881 | -# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT |
2882 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
2883 | -# license you chose for the specific language governing permissions and |
2884 | -# limitations under that license. |
2885 | -# |
2886 | - |
2887 | -"""TestResult helper classes used to by subunit.""" |
2888 | - |
2889 | -import datetime |
2890 | - |
2891 | -import testtools |
2892 | - |
2893 | -from subunit import iso8601 |
2894 | - |
2895 | - |
2896 | -# NOT a TestResult, because we are implementing the interface, not inheriting |
2897 | -# it. |
2898 | -class TestResultDecorator(object): |
2899 | - """General pass-through decorator. |
2900 | - |
2901 | - This provides a base that other TestResults can inherit from to |
2902 | - gain basic forwarding functionality. It also takes care of |
2903 | - handling the case where the target doesn't support newer methods |
2904 | - or features by degrading them. |
2905 | - """ |
2906 | - |
2907 | - def __init__(self, decorated): |
2908 | - """Create a TestResultDecorator forwarding to decorated.""" |
2909 | - # Make every decorator degrade gracefully. |
2910 | - self.decorated = testtools.ExtendedToOriginalDecorator(decorated) |
2911 | - |
2912 | - def startTest(self, test): |
2913 | - return self.decorated.startTest(test) |
2914 | - |
2915 | - def startTestRun(self): |
2916 | - return self.decorated.startTestRun() |
2917 | - |
2918 | - def stopTest(self, test): |
2919 | - return self.decorated.stopTest(test) |
2920 | - |
2921 | - def stopTestRun(self): |
2922 | - return self.decorated.stopTestRun() |
2923 | - |
2924 | - def addError(self, test, err=None, details=None): |
2925 | - return self.decorated.addError(test, err, details=details) |
2926 | - |
2927 | - def addFailure(self, test, err=None, details=None): |
2928 | - return self.decorated.addFailure(test, err, details=details) |
2929 | - |
2930 | - def addSuccess(self, test, details=None): |
2931 | - return self.decorated.addSuccess(test, details=details) |
2932 | - |
2933 | - def addSkip(self, test, reason=None, details=None): |
2934 | - return self.decorated.addSkip(test, reason, details=details) |
2935 | - |
2936 | - def addExpectedFailure(self, test, err=None, details=None): |
2937 | - return self.decorated.addExpectedFailure(test, err, details=details) |
2938 | - |
2939 | - def addUnexpectedSuccess(self, test, details=None): |
2940 | - return self.decorated.addUnexpectedSuccess(test, details=details) |
2941 | - |
2942 | - def progress(self, offset, whence): |
2943 | - return self.decorated.progress(offset, whence) |
2944 | - |
2945 | - def wasSuccessful(self): |
2946 | - return self.decorated.wasSuccessful() |
2947 | - |
2948 | - @property |
2949 | - def shouldStop(self): |
2950 | - return self.decorated.shouldStop |
2951 | - |
2952 | - def stop(self): |
2953 | - return self.decorated.stop() |
2954 | - |
2955 | - @property |
2956 | - def testsRun(self): |
2957 | - return self.decorated.testsRun |
2958 | - |
2959 | - def tags(self, new_tags, gone_tags): |
2960 | - return self.decorated.tags(new_tags, gone_tags) |
2961 | - |
2962 | - def time(self, a_datetime): |
2963 | - return self.decorated.time(a_datetime) |
2964 | - |
2965 | - |
2966 | -class HookedTestResultDecorator(TestResultDecorator): |
2967 | - """A TestResult which calls a hook on every event.""" |
2968 | - |
2969 | - def __init__(self, decorated): |
2970 | - self.super = super(HookedTestResultDecorator, self) |
2971 | - self.super.__init__(decorated) |
2972 | - |
2973 | - def startTest(self, test): |
2974 | - self._before_event() |
2975 | - return self.super.startTest(test) |
2976 | - |
2977 | - def startTestRun(self): |
2978 | - self._before_event() |
2979 | - return self.super.startTestRun() |
2980 | - |
2981 | - def stopTest(self, test): |
2982 | - self._before_event() |
2983 | - return self.super.stopTest(test) |
2984 | - |
2985 | - def stopTestRun(self): |
2986 | - self._before_event() |
2987 | - return self.super.stopTestRun() |
2988 | - |
2989 | - def addError(self, test, err=None, details=None): |
2990 | - self._before_event() |
2991 | - return self.super.addError(test, err, details=details) |
2992 | - |
2993 | - def addFailure(self, test, err=None, details=None): |
2994 | - self._before_event() |
2995 | - return self.super.addFailure(test, err, details=details) |
2996 | - |
2997 | - def addSuccess(self, test, details=None): |
2998 | - self._before_event() |
2999 | - return self.super.addSuccess(test, details=details) |
3000 | - |
3001 | - def addSkip(self, test, reason=None, details=None): |
3002 | - self._before_event() |
3003 | - return self.super.addSkip(test, reason, details=details) |
3004 | - |
3005 | - def addExpectedFailure(self, test, err=None, details=None): |
3006 | - self._before_event() |
3007 | - return self.super.addExpectedFailure(test, err, details=details) |
3008 | - |
3009 | - def addUnexpectedSuccess(self, test, details=None): |
3010 | - self._before_event() |
3011 | - return self.super.addUnexpectedSuccess(test, details=details) |
3012 | - |
3013 | - def progress(self, offset, whence): |
3014 | - self._before_event() |
3015 | - return self.super.progress(offset, whence) |
3016 | - |
3017 | - def wasSuccessful(self): |
3018 | - self._before_event() |
3019 | - return self.super.wasSuccessful() |
3020 | - |
3021 | - @property |
3022 | - def shouldStop(self): |
3023 | - self._before_event() |
3024 | - return self.super.shouldStop |
3025 | - |
3026 | - def stop(self): |
3027 | - self._before_event() |
3028 | - return self.super.stop() |
3029 | - |
3030 | - def time(self, a_datetime): |
3031 | - self._before_event() |
3032 | - return self.super.time(a_datetime) |
3033 | - |
3034 | - |
3035 | -class AutoTimingTestResultDecorator(HookedTestResultDecorator): |
3036 | - """Decorate a TestResult to add time events to a test run. |
3037 | - |
3038 | - By default this will cause a time event before every test event, |
3039 | - but if explicit time data is being provided by the test run, then |
3040 | - this decorator will turn itself off to prevent causing confusion. |
3041 | - """ |
3042 | - |
3043 | - def __init__(self, decorated): |
3044 | - self._time = None |
3045 | - super(AutoTimingTestResultDecorator, self).__init__(decorated) |
3046 | - |
3047 | - def _before_event(self): |
3048 | - time = self._time |
3049 | - if time is not None: |
3050 | - return |
3051 | - time = datetime.datetime.utcnow().replace(tzinfo=iso8601.Utc()) |
3052 | - self.decorated.time(time) |
3053 | - |
3054 | - def progress(self, offset, whence): |
3055 | - return self.decorated.progress(offset, whence) |
3056 | - |
3057 | - @property |
3058 | - def shouldStop(self): |
3059 | - return self.decorated.shouldStop |
3060 | - |
3061 | - def time(self, a_datetime): |
3062 | - """Provide a timestamp for the current test activity. |
3063 | - |
3064 | - :param a_datetime: If None, automatically add timestamps before every |
3065 | - event (this is the default behaviour if time() is not called at |
3066 | - all). If not None, pass the provided time onto the decorated |
3067 | - result object and disable automatic timestamps. |
3068 | - """ |
3069 | - self._time = a_datetime |
3070 | - return self.decorated.time(a_datetime) |
3071 | - |
3072 | - |
3073 | -class TagCollapsingDecorator(TestResultDecorator): |
3074 | - """Collapses many 'tags' calls into one where possible.""" |
3075 | - |
3076 | - def __init__(self, result): |
3077 | - super(TagCollapsingDecorator, self).__init__(result) |
3078 | - # The (new, gone) tags for the current test. |
3079 | - self._current_test_tags = None |
3080 | - |
3081 | - def startTest(self, test): |
3082 | - """Start a test. |
3083 | - |
3084 | - Not directly passed to the client, but used for handling of tags |
3085 | - correctly. |
3086 | - """ |
3087 | - self.decorated.startTest(test) |
3088 | - self._current_test_tags = set(), set() |
3089 | - |
3090 | - def stopTest(self, test): |
3091 | - """Stop a test. |
3092 | - |
3093 | - Not directly passed to the client, but used for handling of tags |
3094 | - correctly. |
3095 | - """ |
3096 | - # Tags to output for this test. |
3097 | - if self._current_test_tags[0] or self._current_test_tags[1]: |
3098 | - self.decorated.tags(*self._current_test_tags) |
3099 | - self.decorated.stopTest(test) |
3100 | - self._current_test_tags = None |
3101 | - |
3102 | - def tags(self, new_tags, gone_tags): |
3103 | - """Handle tag instructions. |
3104 | - |
3105 | - Adds and removes tags as appropriate. If a test is currently running, |
3106 | - tags are not affected for subsequent tests. |
3107 | - |
3108 | - :param new_tags: Tags to add, |
3109 | - :param gone_tags: Tags to remove. |
3110 | - """ |
3111 | - if self._current_test_tags is not None: |
3112 | - # gather the tags until the test stops. |
3113 | - self._current_test_tags[0].update(new_tags) |
3114 | - self._current_test_tags[0].difference_update(gone_tags) |
3115 | - self._current_test_tags[1].update(gone_tags) |
3116 | - self._current_test_tags[1].difference_update(new_tags) |
3117 | - else: |
3118 | - return self.decorated.tags(new_tags, gone_tags) |
3119 | - |
3120 | - |
3121 | -class TimeCollapsingDecorator(HookedTestResultDecorator): |
3122 | - """Only pass on the first and last of a consecutive sequence of times.""" |
3123 | - |
3124 | - def __init__(self, decorated): |
3125 | - super(TimeCollapsingDecorator, self).__init__(decorated) |
3126 | - self._last_received_time = None |
3127 | - self._last_sent_time = None |
3128 | - |
3129 | - def _before_event(self): |
3130 | - if self._last_received_time is None: |
3131 | - return |
3132 | - if self._last_received_time != self._last_sent_time: |
3133 | - self.decorated.time(self._last_received_time) |
3134 | - self._last_sent_time = self._last_received_time |
3135 | - self._last_received_time = None |
3136 | - |
3137 | - def time(self, a_time): |
3138 | - # Don't upcall, because we don't want to call _before_event, it's only |
3139 | - # for non-time events. |
3140 | - if self._last_received_time is None: |
3141 | - self.decorated.time(a_time) |
3142 | - self._last_sent_time = a_time |
3143 | - self._last_received_time = a_time |
3144 | - |
3145 | - |
3146 | -def all_true(bools): |
3147 | - """Return True if all of 'bools' are True. False otherwise.""" |
3148 | - for b in bools: |
3149 | - if not b: |
3150 | - return False |
3151 | - return True |
3152 | - |
3153 | - |
3154 | -class TestResultFilter(TestResultDecorator): |
3155 | - """A pyunit TestResult interface implementation which filters tests. |
3156 | - |
3157 | - Tests that pass the filter are handed on to another TestResult instance |
3158 | - for further processing/reporting. To obtain the filtered results, |
3159 | - the other instance must be interrogated. |
3160 | - |
3161 | - :ivar result: The result that tests are passed to after filtering. |
3162 | - :ivar filter_predicate: The callback run to decide whether to pass |
3163 | - a result. |
3164 | - """ |
3165 | - |
3166 | - def __init__(self, result, filter_error=False, filter_failure=False, |
3167 | - filter_success=True, filter_skip=False, |
3168 | - filter_predicate=None, fixup_expected_failures=None): |
3169 | - """Create a FilterResult object filtering to result. |
3170 | - |
3171 | - :param filter_error: Filter out errors. |
3172 | - :param filter_failure: Filter out failures. |
3173 | - :param filter_success: Filter out successful tests. |
3174 | - :param filter_skip: Filter out skipped tests. |
3175 | - :param filter_predicate: A callable taking (test, outcome, err, |
3176 | - details) and returning True if the result should be passed |
3177 | - through. err and details may be none if no error or extra |
3178 | - metadata is available. outcome is the name of the outcome such |
3179 | - as 'success' or 'failure'. |
3180 | - :param fixup_expected_failures: Set of test ids to consider known |
3181 | - failing. |
3182 | - """ |
3183 | - super(TestResultFilter, self).__init__(result) |
3184 | - self.decorated = TimeCollapsingDecorator( |
3185 | - TagCollapsingDecorator(self.decorated)) |
3186 | - predicates = [] |
3187 | - if filter_error: |
3188 | - predicates.append(lambda t, outcome, e, d: outcome != 'error') |
3189 | - if filter_failure: |
3190 | - predicates.append(lambda t, outcome, e, d: outcome != 'failure') |
3191 | - if filter_success: |
3192 | - predicates.append(lambda t, outcome, e, d: outcome != 'success') |
3193 | - if filter_skip: |
3194 | - predicates.append(lambda t, outcome, e, d: outcome != 'skip') |
3195 | - if filter_predicate is not None: |
3196 | - predicates.append(filter_predicate) |
3197 | - self.filter_predicate = ( |
3198 | - lambda test, outcome, err, details: |
3199 | - all_true(p(test, outcome, err, details) for p in predicates)) |
3200 | - # The current test (for filtering tags) |
3201 | - self._current_test = None |
3202 | - # Has the current test been filtered (for outputting test tags) |
3203 | - self._current_test_filtered = None |
3204 | - # Calls to this result that we don't know whether to forward on yet. |
3205 | - self._buffered_calls = [] |
3206 | - if fixup_expected_failures is None: |
3207 | - self._fixup_expected_failures = frozenset() |
3208 | - else: |
3209 | - self._fixup_expected_failures = fixup_expected_failures |
3210 | - |
3211 | - def addError(self, test, err=None, details=None): |
3212 | - if (self.filter_predicate(test, 'error', err, details)): |
3213 | - if self._failure_expected(test): |
3214 | - self._buffered_calls.append( |
3215 | - ('addExpectedFailure', [test, err], {'details': details})) |
3216 | - else: |
3217 | - self._buffered_calls.append( |
3218 | - ('addError', [test, err], {'details': details})) |
3219 | - else: |
3220 | - self._filtered() |
3221 | - |
3222 | - def addFailure(self, test, err=None, details=None): |
3223 | - if (self.filter_predicate(test, 'failure', err, details)): |
3224 | - if self._failure_expected(test): |
3225 | - self._buffered_calls.append( |
3226 | - ('addExpectedFailure', [test, err], {'details': details})) |
3227 | - else: |
3228 | - self._buffered_calls.append( |
3229 | - ('addFailure', [test, err], {'details': details})) |
3230 | - else: |
3231 | - self._filtered() |
3232 | - |
3233 | - def addSkip(self, test, reason=None, details=None): |
3234 | - if (self.filter_predicate(test, 'skip', reason, details)): |
3235 | - self._buffered_calls.append( |
3236 | - ('addSkip', [test, reason], {'details': details})) |
3237 | - else: |
3238 | - self._filtered() |
3239 | - |
3240 | - def addSuccess(self, test, details=None): |
3241 | - if (self.filter_predicate(test, 'success', None, details)): |
3242 | - if self._failure_expected(test): |
3243 | - self._buffered_calls.append( |
3244 | - ('addUnexpectedSuccess', [test], {'details': details})) |
3245 | - else: |
3246 | - self._buffered_calls.append( |
3247 | - ('addSuccess', [test], {'details': details})) |
3248 | - else: |
3249 | - self._filtered() |
3250 | - |
3251 | - def addExpectedFailure(self, test, err=None, details=None): |
3252 | - if self.filter_predicate(test, 'expectedfailure', err, details): |
3253 | - self._buffered_calls.append( |
3254 | - ('addExpectedFailure', [test, err], {'details': details})) |
3255 | - else: |
3256 | - self._filtered() |
3257 | - |
3258 | - def addUnexpectedSuccess(self, test, details=None): |
3259 | - self._buffered_calls.append( |
3260 | - ('addUnexpectedSuccess', [test], {'details': details})) |
3261 | - |
3262 | - def _filtered(self): |
3263 | - self._current_test_filtered = True |
3264 | - |
3265 | - def _failure_expected(self, test): |
3266 | - return (test.id() in self._fixup_expected_failures) |
3267 | - |
3268 | - def startTest(self, test): |
3269 | - """Start a test. |
3270 | - |
3271 | - Not directly passed to the client, but used for handling of tags |
3272 | - correctly. |
3273 | - """ |
3274 | - self._current_test = test |
3275 | - self._current_test_filtered = False |
3276 | - self._buffered_calls.append(('startTest', [test], {})) |
3277 | - |
3278 | - def stopTest(self, test): |
3279 | - """Stop a test. |
3280 | - |
3281 | - Not directly passed to the client, but used for handling of tags |
3282 | - correctly. |
3283 | - """ |
3284 | - if not self._current_test_filtered: |
3285 | - # Tags to output for this test. |
3286 | - for method, args, kwargs in self._buffered_calls: |
3287 | - getattr(self.decorated, method)(*args, **kwargs) |
3288 | - self.decorated.stopTest(test) |
3289 | - self._current_test = None |
3290 | - self._current_test_filtered = None |
3291 | - self._buffered_calls = [] |
3292 | - |
3293 | - def time(self, a_time): |
3294 | - if self._current_test is not None: |
3295 | - self._buffered_calls.append(('time', [a_time], {})) |
3296 | - else: |
3297 | - return self.decorated.time(a_time) |
3298 | - |
3299 | - def id_to_orig_id(self, id): |
3300 | - if id.startswith("subunit.RemotedTestCase."): |
3301 | - return id[len("subunit.RemotedTestCase."):] |
3302 | - return id |
3303 | - |
3304 | - |
3305 | -class TestIdPrintingResult(testtools.TestResult): |
3306 | - |
3307 | - def __init__(self, stream, show_times=False): |
3308 | - """Create a FilterResult object outputting to stream.""" |
3309 | - super(TestIdPrintingResult, self).__init__() |
3310 | - self._stream = stream |
3311 | - self.failed_tests = 0 |
3312 | - self.__time = None |
3313 | - self.show_times = show_times |
3314 | - self._test = None |
3315 | - self._test_duration = 0 |
3316 | - |
3317 | - def addError(self, test, err): |
3318 | - self.failed_tests += 1 |
3319 | - self._test = test |
3320 | - |
3321 | - def addFailure(self, test, err): |
3322 | - self.failed_tests += 1 |
3323 | - self._test = test |
3324 | - |
3325 | - def addSuccess(self, test): |
3326 | - self._test = test |
3327 | - |
3328 | - def addSkip(self, test, reason=None, details=None): |
3329 | - self._test = test |
3330 | - |
3331 | - def addUnexpectedSuccess(self, test, details=None): |
3332 | - self.failed_tests += 1 |
3333 | - self._test = test |
3334 | - |
3335 | - def addExpectedFailure(self, test, err=None, details=None): |
3336 | - self._test = test |
3337 | - |
3338 | - def reportTest(self, test, duration): |
3339 | - if self.show_times: |
3340 | - seconds = duration.seconds |
3341 | - seconds += duration.days * 3600 * 24 |
3342 | - seconds += duration.microseconds / 1000000.0 |
3343 | - self._stream.write(test.id() + ' %0.3f\n' % seconds) |
3344 | - else: |
3345 | - self._stream.write(test.id() + '\n') |
3346 | - |
3347 | - def startTest(self, test): |
3348 | - self._start_time = self._time() |
3349 | - |
3350 | - def stopTest(self, test): |
3351 | - test_duration = self._time() - self._start_time |
3352 | - self.reportTest(self._test, test_duration) |
3353 | - |
3354 | - def time(self, time): |
3355 | - self.__time = time |
3356 | - |
3357 | - def _time(self): |
3358 | - return self.__time |
3359 | - |
3360 | - def wasSuccessful(self): |
3361 | - "Tells whether or not this result was a success" |
3362 | - return self.failed_tests == 0 |
3363 | |
3364 | === removed directory 'python-for-subunit2junitxml/subunit/tests' |
3365 | === removed file 'python-for-subunit2junitxml/subunit/tests/TestUtil.py' |
3366 | --- python-for-subunit2junitxml/subunit/tests/TestUtil.py 2013-05-27 13:46:13 +0000 |
3367 | +++ python-for-subunit2junitxml/subunit/tests/TestUtil.py 1970-01-01 00:00:00 +0000 |
3368 | @@ -1,80 +0,0 @@ |
3369 | -# Copyright (c) 2004 Canonical Limited |
3370 | -# Author: Robert Collins <robert.collins@canonical.com> |
3371 | -# |
3372 | -# This program is free software; you can redistribute it and/or modify |
3373 | -# it under the terms of the GNU General Public License as published by |
3374 | -# the Free Software Foundation; either version 2 of the License, or |
3375 | -# (at your option) any later version. |
3376 | -# |
3377 | -# This program is distributed in the hope that it will be useful, |
3378 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
3379 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3380 | -# GNU General Public License for more details. |
3381 | -# |
3382 | -# You should have received a copy of the GNU General Public License |
3383 | -# along with this program; if not, write to the Free Software |
3384 | -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
3385 | -# |
3386 | - |
3387 | -import sys |
3388 | -import logging |
3389 | -import unittest |
3390 | - |
3391 | - |
3392 | -class LogCollector(logging.Handler): |
3393 | - def __init__(self): |
3394 | - logging.Handler.__init__(self) |
3395 | - self.records=[] |
3396 | - def emit(self, record): |
3397 | - self.records.append(record.getMessage()) |
3398 | - |
3399 | - |
3400 | -def makeCollectingLogger(): |
3401 | - """I make a logger instance that collects its logs for programmatic analysis |
3402 | - -> (logger, collector)""" |
3403 | - logger=logging.Logger("collector") |
3404 | - handler=LogCollector() |
3405 | - handler.setFormatter(logging.Formatter("%(levelname)s: %(message)s")) |
3406 | - logger.addHandler(handler) |
3407 | - return logger, handler |
3408 | - |
3409 | - |
3410 | -def visitTests(suite, visitor): |
3411 | - """A foreign method for visiting the tests in a test suite.""" |
3412 | - for test in suite._tests: |
3413 | - #Abusing types to avoid monkey patching unittest.TestCase. |
3414 | - # Maybe that would be better? |
3415 | - try: |
3416 | - test.visit(visitor) |
3417 | - except AttributeError: |
3418 | - if isinstance(test, unittest.TestCase): |
3419 | - visitor.visitCase(test) |
3420 | - elif isinstance(test, unittest.TestSuite): |
3421 | - visitor.visitSuite(test) |
3422 | - visitTests(test, visitor) |
3423 | - else: |
3424 | - print ("unvisitable non-unittest.TestCase element %r (%r)" % (test, test.__class__)) |
3425 | - |
3426 | - |
3427 | -class TestSuite(unittest.TestSuite): |
3428 | - """I am an extended TestSuite with a visitor interface. |
3429 | - This is primarily to allow filtering of tests - and suites or |
3430 | - more in the future. An iterator of just tests wouldn't scale...""" |
3431 | - |
3432 | - def visit(self, visitor): |
3433 | - """visit the composite. Visiting is depth-first. |
3434 | - current callbacks are visitSuite and visitCase.""" |
3435 | - visitor.visitSuite(self) |
3436 | - visitTests(self, visitor) |
3437 | - |
3438 | - |
3439 | -class TestLoader(unittest.TestLoader): |
3440 | - """Custome TestLoader to set the right TestSuite class.""" |
3441 | - suiteClass = TestSuite |
3442 | - |
3443 | -class TestVisitor(object): |
3444 | - """A visitor for Tests""" |
3445 | - def visitSuite(self, aTestSuite): |
3446 | - pass |
3447 | - def visitCase(self, aTestCase): |
3448 | - pass |
3449 | |
3450 | === removed file 'python-for-subunit2junitxml/subunit/tests/__init__.py' |
3451 | --- python-for-subunit2junitxml/subunit/tests/__init__.py 2013-05-27 13:46:13 +0000 |
3452 | +++ python-for-subunit2junitxml/subunit/tests/__init__.py 1970-01-01 00:00:00 +0000 |
3453 | @@ -1,41 +0,0 @@ |
3454 | -# |
3455 | -# subunit: extensions to python unittest to get test results from subprocesses. |
3456 | -# Copyright (C) 2005 Robert Collins <robertc@robertcollins.net> |
3457 | -# |
3458 | -# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause |
3459 | -# license at the users choice. A copy of both licenses are available in the |
3460 | -# project source as Apache-2.0 and BSD. You may not use this file except in |
3461 | -# compliance with one of these two licences. |
3462 | -# |
3463 | -# Unless required by applicable law or agreed to in writing, software |
3464 | -# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT |
3465 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
3466 | -# license you chose for the specific language governing permissions and |
3467 | -# limitations under that license. |
3468 | -# |
3469 | - |
3470 | -from subunit.tests import ( |
3471 | - TestUtil, |
3472 | - test_chunked, |
3473 | - test_details, |
3474 | - test_progress_model, |
3475 | - test_subunit_filter, |
3476 | - test_subunit_stats, |
3477 | - test_subunit_tags, |
3478 | - test_tap2subunit, |
3479 | - test_test_protocol, |
3480 | - test_test_results, |
3481 | - ) |
3482 | - |
3483 | -def test_suite(): |
3484 | - result = TestUtil.TestSuite() |
3485 | - result.addTest(test_chunked.test_suite()) |
3486 | - result.addTest(test_details.test_suite()) |
3487 | - result.addTest(test_progress_model.test_suite()) |
3488 | - result.addTest(test_test_results.test_suite()) |
3489 | - result.addTest(test_test_protocol.test_suite()) |
3490 | - result.addTest(test_tap2subunit.test_suite()) |
3491 | - result.addTest(test_subunit_filter.test_suite()) |
3492 | - result.addTest(test_subunit_tags.test_suite()) |
3493 | - result.addTest(test_subunit_stats.test_suite()) |
3494 | - return result |
3495 | |
3496 | === removed file 'python-for-subunit2junitxml/subunit/tests/sample-script.py' |
3497 | --- python-for-subunit2junitxml/subunit/tests/sample-script.py 2013-05-27 13:46:13 +0000 |
3498 | +++ python-for-subunit2junitxml/subunit/tests/sample-script.py 1970-01-01 00:00:00 +0000 |
3499 | @@ -1,21 +0,0 @@ |
3500 | -#!/usr/bin/env python |
3501 | -import sys |
3502 | -if sys.platform == "win32": |
3503 | - import msvcrt, os |
3504 | - msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) |
3505 | -if len(sys.argv) == 2: |
3506 | - # subunit.tests.test_test_protocol.TestExecTestCase.test_sample_method_args |
3507 | - # uses this code path to be sure that the arguments were passed to |
3508 | - # sample-script.py |
3509 | - print "test fail" |
3510 | - print "error fail" |
3511 | - sys.exit(0) |
3512 | -print "test old mcdonald" |
3513 | -print "success old mcdonald" |
3514 | -print "test bing crosby" |
3515 | -print "failure bing crosby [" |
3516 | -print "foo.c:53:ERROR invalid state" |
3517 | -print "]" |
3518 | -print "test an error" |
3519 | -print "error an error" |
3520 | -sys.exit(0) |
3521 | |
3522 | === removed file 'python-for-subunit2junitxml/subunit/tests/sample-two-script.py' |
3523 | --- python-for-subunit2junitxml/subunit/tests/sample-two-script.py 2013-05-27 13:46:13 +0000 |
3524 | +++ python-for-subunit2junitxml/subunit/tests/sample-two-script.py 1970-01-01 00:00:00 +0000 |
3525 | @@ -1,7 +0,0 @@ |
3526 | -#!/usr/bin/env python |
3527 | -import sys |
3528 | -print "test old mcdonald" |
3529 | -print "success old mcdonald" |
3530 | -print "test bing crosby" |
3531 | -print "success bing crosby" |
3532 | -sys.exit(0) |
3533 | |
3534 | === removed file 'python-for-subunit2junitxml/subunit/tests/test_chunked.py' |
3535 | --- python-for-subunit2junitxml/subunit/tests/test_chunked.py 2013-05-27 13:46:13 +0000 |
3536 | +++ python-for-subunit2junitxml/subunit/tests/test_chunked.py 1970-01-01 00:00:00 +0000 |
3537 | @@ -1,152 +0,0 @@ |
3538 | -# |
3539 | -# subunit: extensions to python unittest to get test results from subprocesses. |
3540 | -# Copyright (C) 2005 Robert Collins <robertc@robertcollins.net> |
3541 | -# Copyright (C) 2011 Martin Pool <mbp@sourcefrog.net> |
3542 | -# |
3543 | -# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause |
3544 | -# license at the users choice. A copy of both licenses are available in the |
3545 | -# project source as Apache-2.0 and BSD. You may not use this file except in |
3546 | -# compliance with one of these two licences. |
3547 | -# |
3548 | -# Unless required by applicable law or agreed to in writing, software |
3549 | -# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT |
3550 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
3551 | -# license you chose for the specific language governing permissions and |
3552 | -# limitations under that license. |
3553 | -# |
3554 | - |
3555 | -import unittest |
3556 | - |
3557 | -from testtools.compat import _b, BytesIO |
3558 | - |
3559 | -import subunit.chunked |
3560 | - |
3561 | - |
3562 | -def test_suite(): |
3563 | - loader = subunit.tests.TestUtil.TestLoader() |
3564 | - result = loader.loadTestsFromName(__name__) |
3565 | - return result |
3566 | - |
3567 | - |
3568 | -class TestDecode(unittest.TestCase): |
3569 | - |
3570 | - def setUp(self): |
3571 | - unittest.TestCase.setUp(self) |
3572 | - self.output = BytesIO() |
3573 | - self.decoder = subunit.chunked.Decoder(self.output) |
3574 | - |
3575 | - def test_close_read_length_short_errors(self): |
3576 | - self.assertRaises(ValueError, self.decoder.close) |
3577 | - |
3578 | - def test_close_body_short_errors(self): |
3579 | - self.assertEqual(None, self.decoder.write(_b('2\r\na'))) |
3580 | - self.assertRaises(ValueError, self.decoder.close) |
3581 | - |
3582 | - def test_close_body_buffered_data_errors(self): |
3583 | - self.assertEqual(None, self.decoder.write(_b('2\r'))) |
3584 | - self.assertRaises(ValueError, self.decoder.close) |
3585 | - |
3586 | - def test_close_after_finished_stream_safe(self): |
3587 | - self.assertEqual(None, self.decoder.write(_b('2\r\nab'))) |
3588 | - self.assertEqual(_b(''), self.decoder.write(_b('0\r\n'))) |
3589 | - self.decoder.close() |
3590 | - |
3591 | - def test_decode_nothing(self): |
3592 | - self.assertEqual(_b(''), self.decoder.write(_b('0\r\n'))) |
3593 | - self.assertEqual(_b(''), self.output.getvalue()) |
3594 | - |
3595 | - def test_decode_serialised_form(self): |
3596 | - self.assertEqual(None, self.decoder.write(_b("F\r\n"))) |
3597 | - self.assertEqual(None, self.decoder.write(_b("serialised\n"))) |
3598 | - self.assertEqual(_b(''), self.decoder.write(_b("form0\r\n"))) |
3599 | - |
3600 | - def test_decode_short(self): |
3601 | - self.assertEqual(_b(''), self.decoder.write(_b('3\r\nabc0\r\n'))) |
3602 | - self.assertEqual(_b('abc'), self.output.getvalue()) |
3603 | - |
3604 | - def test_decode_combines_short(self): |
3605 | - self.assertEqual(_b(''), self.decoder.write(_b('6\r\nabcdef0\r\n'))) |
3606 | - self.assertEqual(_b('abcdef'), self.output.getvalue()) |
3607 | - |
3608 | - def test_decode_excess_bytes_from_write(self): |
3609 | - self.assertEqual(_b('1234'), self.decoder.write(_b('3\r\nabc0\r\n1234'))) |
3610 | - self.assertEqual(_b('abc'), self.output.getvalue()) |
3611 | - |
3612 | - def test_decode_write_after_finished_errors(self): |
3613 | - self.assertEqual(_b('1234'), self.decoder.write(_b('3\r\nabc0\r\n1234'))) |
3614 | - self.assertRaises(ValueError, self.decoder.write, _b('')) |
3615 | - |
3616 | - def test_decode_hex(self): |
3617 | - self.assertEqual(_b(''), self.decoder.write(_b('A\r\n12345678900\r\n'))) |
3618 | - self.assertEqual(_b('1234567890'), self.output.getvalue()) |
3619 | - |
3620 | - def test_decode_long_ranges(self): |
3621 | - self.assertEqual(None, self.decoder.write(_b('10000\r\n'))) |
3622 | - self.assertEqual(None, self.decoder.write(_b('1' * 65536))) |
3623 | - self.assertEqual(None, self.decoder.write(_b('10000\r\n'))) |
3624 | - self.assertEqual(None, self.decoder.write(_b('2' * 65536))) |
3625 | - self.assertEqual(_b(''), self.decoder.write(_b('0\r\n'))) |
3626 | - self.assertEqual(_b('1' * 65536 + '2' * 65536), self.output.getvalue()) |
3627 | - |
3628 | - def test_decode_newline_nonstrict(self): |
3629 | - """Tolerate chunk markers with no CR character.""" |
3630 | - # From <http://pad.lv/505078> |
3631 | - self.decoder = subunit.chunked.Decoder(self.output, strict=False) |
3632 | - self.assertEqual(None, self.decoder.write(_b('a\n'))) |
3633 | - self.assertEqual(None, self.decoder.write(_b('abcdeabcde'))) |
3634 | - self.assertEqual(_b(''), self.decoder.write(_b('0\n'))) |
3635 | - self.assertEqual(_b('abcdeabcde'), self.output.getvalue()) |
3636 | - |
3637 | - def test_decode_strict_newline_only(self): |
3638 | - """Reject chunk markers with no CR character in strict mode.""" |
3639 | - # From <http://pad.lv/505078> |
3640 | - self.assertRaises(ValueError, |
3641 | - self.decoder.write, _b('a\n')) |
3642 | - |
3643 | - def test_decode_strict_multiple_crs(self): |
3644 | - self.assertRaises(ValueError, |
3645 | - self.decoder.write, _b('a\r\r\n')) |
3646 | - |
3647 | - def test_decode_short_header(self): |
3648 | - self.assertRaises(ValueError, |
3649 | - self.decoder.write, _b('\n')) |
3650 | - |
3651 | - |
3652 | -class TestEncode(unittest.TestCase): |
3653 | - |
3654 | - def setUp(self): |
3655 | - unittest.TestCase.setUp(self) |
3656 | - self.output = BytesIO() |
3657 | - self.encoder = subunit.chunked.Encoder(self.output) |
3658 | - |
3659 | - def test_encode_nothing(self): |
3660 | - self.encoder.close() |
3661 | - self.assertEqual(_b('0\r\n'), self.output.getvalue()) |
3662 | - |
3663 | - def test_encode_empty(self): |
3664 | - self.encoder.write(_b('')) |
3665 | - self.encoder.close() |
3666 | - self.assertEqual(_b('0\r\n'), self.output.getvalue()) |
3667 | - |
3668 | - def test_encode_short(self): |
3669 | - self.encoder.write(_b('abc')) |
3670 | - self.encoder.close() |
3671 | - self.assertEqual(_b('3\r\nabc0\r\n'), self.output.getvalue()) |
3672 | - |
3673 | - def test_encode_combines_short(self): |
3674 | - self.encoder.write(_b('abc')) |
3675 | - self.encoder.write(_b('def')) |
3676 | - self.encoder.close() |
3677 | - self.assertEqual(_b('6\r\nabcdef0\r\n'), self.output.getvalue()) |
3678 | - |
3679 | - def test_encode_over_9_is_in_hex(self): |
3680 | - self.encoder.write(_b('1234567890')) |
3681 | - self.encoder.close() |
3682 | - self.assertEqual(_b('A\r\n12345678900\r\n'), self.output.getvalue()) |
3683 | - |
3684 | - def test_encode_long_ranges_not_combined(self): |
3685 | - self.encoder.write(_b('1' * 65536)) |
3686 | - self.encoder.write(_b('2' * 65536)) |
3687 | - self.encoder.close() |
3688 | - self.assertEqual(_b('10000\r\n' + '1' * 65536 + '10000\r\n' + |
3689 | - '2' * 65536 + '0\r\n'), self.output.getvalue()) |
3690 | |
3691 | === removed file 'python-for-subunit2junitxml/subunit/tests/test_details.py' |
3692 | --- python-for-subunit2junitxml/subunit/tests/test_details.py 2013-05-27 13:46:13 +0000 |
3693 | +++ python-for-subunit2junitxml/subunit/tests/test_details.py 1970-01-01 00:00:00 +0000 |
3694 | @@ -1,112 +0,0 @@ |
3695 | -# |
3696 | -# subunit: extensions to python unittest to get test results from subprocesses. |
3697 | -# Copyright (C) 2005 Robert Collins <robertc@robertcollins.net> |
3698 | -# |
3699 | -# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause |
3700 | -# license at the users choice. A copy of both licenses are available in the |
3701 | -# project source as Apache-2.0 and BSD. You may not use this file except in |
3702 | -# compliance with one of these two licences. |
3703 | -# |
3704 | -# Unless required by applicable law or agreed to in writing, software |
3705 | -# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT |
3706 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
3707 | -# license you chose for the specific language governing permissions and |
3708 | -# limitations under that license. |
3709 | -# |
3710 | - |
3711 | -import unittest |
3712 | - |
3713 | -from testtools.compat import _b, StringIO |
3714 | - |
3715 | -import subunit.tests |
3716 | -from subunit import content, content_type, details |
3717 | - |
3718 | - |
3719 | -def test_suite(): |
3720 | - loader = subunit.tests.TestUtil.TestLoader() |
3721 | - result = loader.loadTestsFromName(__name__) |
3722 | - return result |
3723 | - |
3724 | - |
3725 | -class TestSimpleDetails(unittest.TestCase): |
3726 | - |
3727 | - def test_lineReceived(self): |
3728 | - parser = details.SimpleDetailsParser(None) |
3729 | - parser.lineReceived(_b("foo\n")) |
3730 | - parser.lineReceived(_b("bar\n")) |
3731 | - self.assertEqual(_b("foo\nbar\n"), parser._message) |
3732 | - |
3733 | - def test_lineReceived_escaped_bracket(self): |
3734 | - parser = details.SimpleDetailsParser(None) |
3735 | - parser.lineReceived(_b("foo\n")) |
3736 | - parser.lineReceived(_b(" ]are\n")) |
3737 | - parser.lineReceived(_b("bar\n")) |
3738 | - self.assertEqual(_b("foo\n]are\nbar\n"), parser._message) |
3739 | - |
3740 | - def test_get_message(self): |
3741 | - parser = details.SimpleDetailsParser(None) |
3742 | - self.assertEqual(_b(""), parser.get_message()) |
3743 | - |
3744 | - def test_get_details(self): |
3745 | - parser = details.SimpleDetailsParser(None) |
3746 | - traceback = "" |
3747 | - expected = {} |
3748 | - expected['traceback'] = content.Content( |
3749 | - content_type.ContentType("text", "x-traceback", |
3750 | - {'charset': 'utf8'}), |
3751 | - lambda:[_b("")]) |
3752 | - found = parser.get_details() |
3753 | - self.assertEqual(expected.keys(), found.keys()) |
3754 | - self.assertEqual(expected['traceback'].content_type, |
3755 | - found['traceback'].content_type) |
3756 | - self.assertEqual(_b('').join(expected['traceback'].iter_bytes()), |
3757 | - _b('').join(found['traceback'].iter_bytes())) |
3758 | - |
3759 | - def test_get_details_skip(self): |
3760 | - parser = details.SimpleDetailsParser(None) |
3761 | - traceback = "" |
3762 | - expected = {} |
3763 | - expected['reason'] = content.Content( |
3764 | - content_type.ContentType("text", "plain"), |
3765 | - lambda:[_b("")]) |
3766 | - found = parser.get_details("skip") |
3767 | - self.assertEqual(expected, found) |
3768 | - |
3769 | - def test_get_details_success(self): |
3770 | - parser = details.SimpleDetailsParser(None) |
3771 | - traceback = "" |
3772 | - expected = {} |
3773 | - expected['message'] = content.Content( |
3774 | - content_type.ContentType("text", "plain"), |
3775 | - lambda:[_b("")]) |
3776 | - found = parser.get_details("success") |
3777 | - self.assertEqual(expected, found) |
3778 | - |
3779 | - |
3780 | -class TestMultipartDetails(unittest.TestCase): |
3781 | - |
3782 | - def test_get_message_is_None(self): |
3783 | - parser = details.MultipartDetailsParser(None) |
3784 | - self.assertEqual(None, parser.get_message()) |
3785 | - |
3786 | - def test_get_details(self): |
3787 | - parser = details.MultipartDetailsParser(None) |
3788 | - self.assertEqual({}, parser.get_details()) |
3789 | - |
3790 | - def test_parts(self): |
3791 | - parser = details.MultipartDetailsParser(None) |
3792 | - parser.lineReceived(_b("Content-Type: text/plain\n")) |
3793 | - parser.lineReceived(_b("something\n")) |
3794 | - parser.lineReceived(_b("F\r\n")) |
3795 | - parser.lineReceived(_b("serialised\n")) |
3796 | - parser.lineReceived(_b("form0\r\n")) |
3797 | - expected = {} |
3798 | - expected['something'] = content.Content( |
3799 | - content_type.ContentType("text", "plain"), |
3800 | - lambda:[_b("serialised\nform")]) |
3801 | - found = parser.get_details() |
3802 | - self.assertEqual(expected.keys(), found.keys()) |
3803 | - self.assertEqual(expected['something'].content_type, |
3804 | - found['something'].content_type) |
3805 | - self.assertEqual(_b('').join(expected['something'].iter_bytes()), |
3806 | - _b('').join(found['something'].iter_bytes())) |
3807 | |
3808 | === removed file 'python-for-subunit2junitxml/subunit/tests/test_progress_model.py' |
3809 | --- python-for-subunit2junitxml/subunit/tests/test_progress_model.py 2013-05-27 13:46:13 +0000 |
3810 | +++ python-for-subunit2junitxml/subunit/tests/test_progress_model.py 1970-01-01 00:00:00 +0000 |
3811 | @@ -1,118 +0,0 @@ |
3812 | -# |
3813 | -# subunit: extensions to Python unittest to get test results from subprocesses. |
3814 | -# Copyright (C) 2009 Robert Collins <robertc@robertcollins.net> |
3815 | -# |
3816 | -# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause |
3817 | -# license at the users choice. A copy of both licenses are available in the |
3818 | -# project source as Apache-2.0 and BSD. You may not use this file except in |
3819 | -# compliance with one of these two licences. |
3820 | -# |
3821 | -# Unless required by applicable law or agreed to in writing, software |
3822 | -# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT |
3823 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
3824 | -# license you chose for the specific language governing permissions and |
3825 | -# limitations under that license. |
3826 | -# |
3827 | - |
3828 | -import unittest |
3829 | - |
3830 | -import subunit |
3831 | -from subunit.progress_model import ProgressModel |
3832 | - |
3833 | - |
3834 | -class TestProgressModel(unittest.TestCase): |
3835 | - |
3836 | - def assertProgressSummary(self, pos, total, progress): |
3837 | - """Assert that a progress model has reached a particular point.""" |
3838 | - self.assertEqual(pos, progress.pos()) |
3839 | - self.assertEqual(total, progress.width()) |
3840 | - |
3841 | - def test_new_progress_0_0(self): |
3842 | - progress = ProgressModel() |
3843 | - self.assertProgressSummary(0, 0, progress) |
3844 | - |
3845 | - def test_advance_0_0(self): |
3846 | - progress = ProgressModel() |
3847 | - progress.advance() |
3848 | - self.assertProgressSummary(1, 0, progress) |
3849 | - |
3850 | - def test_advance_1_0(self): |
3851 | - progress = ProgressModel() |
3852 | - progress.advance() |
3853 | - self.assertProgressSummary(1, 0, progress) |
3854 | - |
3855 | - def test_set_width_absolute(self): |
3856 | - progress = ProgressModel() |
3857 | - progress.set_width(10) |
3858 | - self.assertProgressSummary(0, 10, progress) |
3859 | - |
3860 | - def test_set_width_absolute_preserves_pos(self): |
3861 | - progress = ProgressModel() |
3862 | - progress.advance() |
3863 | - progress.set_width(2) |
3864 | - self.assertProgressSummary(1, 2, progress) |
3865 | - |
3866 | - def test_adjust_width(self): |
3867 | - progress = ProgressModel() |
3868 | - progress.adjust_width(10) |
3869 | - self.assertProgressSummary(0, 10, progress) |
3870 | - progress.adjust_width(-10) |
3871 | - self.assertProgressSummary(0, 0, progress) |
3872 | - |
3873 | - def test_adjust_width_preserves_pos(self): |
3874 | - progress = ProgressModel() |
3875 | - progress.advance() |
3876 | - progress.adjust_width(10) |
3877 | - self.assertProgressSummary(1, 10, progress) |
3878 | - progress.adjust_width(-10) |
3879 | - self.assertProgressSummary(1, 0, progress) |
3880 | - |
3881 | - def test_push_preserves_progress(self): |
3882 | - progress = ProgressModel() |
3883 | - progress.adjust_width(3) |
3884 | - progress.advance() |
3885 | - progress.push() |
3886 | - self.assertProgressSummary(1, 3, progress) |
3887 | - |
3888 | - def test_advance_advances_substack(self): |
3889 | - progress = ProgressModel() |
3890 | - progress.adjust_width(3) |
3891 | - progress.advance() |
3892 | - progress.push() |
3893 | - progress.adjust_width(1) |
3894 | - progress.advance() |
3895 | - self.assertProgressSummary(2, 3, progress) |
3896 | - |
3897 | - def test_adjust_width_adjusts_substack(self): |
3898 | - progress = ProgressModel() |
3899 | - progress.adjust_width(3) |
3900 | - progress.advance() |
3901 | - progress.push() |
3902 | - progress.adjust_width(2) |
3903 | - progress.advance() |
3904 | - self.assertProgressSummary(3, 6, progress) |
3905 | - |
3906 | - def test_set_width_adjusts_substack(self): |
3907 | - progress = ProgressModel() |
3908 | - progress.adjust_width(3) |
3909 | - progress.advance() |
3910 | - progress.push() |
3911 | - progress.set_width(2) |
3912 | - progress.advance() |
3913 | - self.assertProgressSummary(3, 6, progress) |
3914 | - |
3915 | - def test_pop_restores_progress(self): |
3916 | - progress = ProgressModel() |
3917 | - progress.adjust_width(3) |
3918 | - progress.advance() |
3919 | - progress.push() |
3920 | - progress.adjust_width(1) |
3921 | - progress.advance() |
3922 | - progress.pop() |
3923 | - self.assertProgressSummary(1, 3, progress) |
3924 | - |
3925 | - |
3926 | -def test_suite(): |
3927 | - loader = subunit.tests.TestUtil.TestLoader() |
3928 | - result = loader.loadTestsFromName(__name__) |
3929 | - return result |
3930 | |
3931 | === removed file 'python-for-subunit2junitxml/subunit/tests/test_subunit_filter.py' |
3932 | --- python-for-subunit2junitxml/subunit/tests/test_subunit_filter.py 2013-05-27 13:46:13 +0000 |
3933 | +++ python-for-subunit2junitxml/subunit/tests/test_subunit_filter.py 1970-01-01 00:00:00 +0000 |
3934 | @@ -1,208 +0,0 @@ |
3935 | -# |
3936 | -# subunit: extensions to python unittest to get test results from subprocesses. |
3937 | -# Copyright (C) 2005 Robert Collins <robertc@robertcollins.net> |
3938 | -# |
3939 | -# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause |
3940 | -# license at the users choice. A copy of both licenses are available in the |
3941 | -# project source as Apache-2.0 and BSD. You may not use this file except in |
3942 | -# compliance with one of these two licences. |
3943 | -# |
3944 | -# Unless required by applicable law or agreed to in writing, software |
3945 | -# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT |
3946 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
3947 | -# license you chose for the specific language governing permissions and |
3948 | -# limitations under that license. |
3949 | -# |
3950 | - |
3951 | -"""Tests for subunit.TestResultFilter.""" |
3952 | - |
3953 | -from datetime import datetime |
3954 | -from subunit import iso8601 |
3955 | -import unittest |
3956 | - |
3957 | -from testtools import TestCase |
3958 | -from testtools.compat import _b, BytesIO, StringIO |
3959 | -from testtools.testresult.doubles import ExtendedTestResult |
3960 | - |
3961 | -import subunit |
3962 | -from subunit.test_results import TestResultFilter |
3963 | - |
3964 | - |
3965 | -class TestTestResultFilter(TestCase): |
3966 | - """Test for TestResultFilter, a TestResult object which filters tests.""" |
3967 | - |
3968 | - # While TestResultFilter works on python objects, using a subunit stream |
3969 | - # is an easy pithy way of getting a series of test objects to call into |
3970 | - # the TestResult, and as TestResultFilter is intended for use with subunit |
3971 | - # also has the benefit of detecting any interface skew issues. |
3972 | - example_subunit_stream = _b("""\ |
3973 | -tags: global |
3974 | -test passed |
3975 | -success passed |
3976 | -test failed |
3977 | -tags: local |
3978 | -failure failed |
3979 | -test error |
3980 | -error error [ |
3981 | -error details |
3982 | -] |
3983 | -test skipped |
3984 | -skip skipped |
3985 | -test todo |
3986 | -xfail todo |
3987 | -""") |
3988 | - |
3989 | - def run_tests(self, result_filter, input_stream=None): |
3990 | - """Run tests through the given filter. |
3991 | - |
3992 | - :param result_filter: A filtering TestResult object. |
3993 | - :param input_stream: Bytes of subunit stream data. If not provided, |
3994 | - uses TestTestResultFilter.example_subunit_stream. |
3995 | - """ |
3996 | - if input_stream is None: |
3997 | - input_stream = self.example_subunit_stream |
3998 | - test = subunit.ProtocolTestCase(BytesIO(input_stream)) |
3999 | - test.run(result_filter) |
4000 | - |
4001 | - def test_default(self): |
4002 | - """The default is to exclude success and include everything else.""" |
4003 | - filtered_result = unittest.TestResult() |
4004 | - result_filter = TestResultFilter(filtered_result) |
4005 | - self.run_tests(result_filter) |
4006 | - # skips are seen as success by default python TestResult. |
4007 | - self.assertEqual(['error'], |
4008 | - [error[0].id() for error in filtered_result.errors]) |
4009 | - self.assertEqual(['failed'], |
4010 | - [failure[0].id() for failure in |
4011 | - filtered_result.failures]) |
4012 | - self.assertEqual(4, filtered_result.testsRun) |
4013 | - |
4014 | - def test_exclude_errors(self): |
4015 | - filtered_result = unittest.TestResult() |
4016 | - result_filter = TestResultFilter(filtered_result, filter_error=True) |
4017 | - self.run_tests(result_filter) |
4018 | - # skips are seen as errors by default python TestResult. |
4019 | - self.assertEqual([], filtered_result.errors) |
4020 | - self.assertEqual(['failed'], |
4021 | - [failure[0].id() for failure in |
4022 | - filtered_result.failures]) |
4023 | - self.assertEqual(3, filtered_result.testsRun) |
4024 | - |
4025 | - def test_fixup_expected_failures(self): |
4026 | - filtered_result = unittest.TestResult() |
4027 | - result_filter = TestResultFilter(filtered_result, |
4028 | - fixup_expected_failures=set(["failed"])) |
4029 | - self.run_tests(result_filter) |
4030 | - self.assertEqual(['failed', 'todo'], |
4031 | - [failure[0].id() for failure in filtered_result.expectedFailures]) |
4032 | - self.assertEqual([], filtered_result.failures) |
4033 | - self.assertEqual(4, filtered_result.testsRun) |
4034 | - |
4035 | - def test_fixup_expected_errors(self): |
4036 | - filtered_result = unittest.TestResult() |
4037 | - result_filter = TestResultFilter(filtered_result, |
4038 | - fixup_expected_failures=set(["error"])) |
4039 | - self.run_tests(result_filter) |
4040 | - self.assertEqual(['error', 'todo'], |
4041 | - [failure[0].id() for failure in filtered_result.expectedFailures]) |
4042 | - self.assertEqual([], filtered_result.errors) |
4043 | - self.assertEqual(4, filtered_result.testsRun) |
4044 | - |
4045 | - def test_fixup_unexpected_success(self): |
4046 | - filtered_result = unittest.TestResult() |
4047 | - result_filter = TestResultFilter(filtered_result, filter_success=False, |
4048 | - fixup_expected_failures=set(["passed"])) |
4049 | - self.run_tests(result_filter) |
4050 | - self.assertEqual(['passed'], |
4051 | - [passed.id() for passed in filtered_result.unexpectedSuccesses]) |
4052 | - self.assertEqual(5, filtered_result.testsRun) |
4053 | - |
4054 | - def test_exclude_failure(self): |
4055 | - filtered_result = unittest.TestResult() |
4056 | - result_filter = TestResultFilter(filtered_result, filter_failure=True) |
4057 | - self.run_tests(result_filter) |
4058 | - self.assertEqual(['error'], |
4059 | - [error[0].id() for error in filtered_result.errors]) |
4060 | - self.assertEqual([], |
4061 | - [failure[0].id() for failure in |
4062 | - filtered_result.failures]) |
4063 | - self.assertEqual(3, filtered_result.testsRun) |
4064 | - |
4065 | - def test_exclude_skips(self): |
4066 | - filtered_result = subunit.TestResultStats(None) |
4067 | - result_filter = TestResultFilter(filtered_result, filter_skip=True) |
4068 | - self.run_tests(result_filter) |
4069 | - self.assertEqual(0, filtered_result.skipped_tests) |
4070 | - self.assertEqual(2, filtered_result.failed_tests) |
4071 | - self.assertEqual(3, filtered_result.testsRun) |
4072 | - |
4073 | - def test_include_success(self): |
4074 | - """Successes can be included if requested.""" |
4075 | - filtered_result = unittest.TestResult() |
4076 | - result_filter = TestResultFilter(filtered_result, |
4077 | - filter_success=False) |
4078 | - self.run_tests(result_filter) |
4079 | - self.assertEqual(['error'], |
4080 | - [error[0].id() for error in filtered_result.errors]) |
4081 | - self.assertEqual(['failed'], |
4082 | - [failure[0].id() for failure in |
4083 | - filtered_result.failures]) |
4084 | - self.assertEqual(5, filtered_result.testsRun) |
4085 | - |
4086 | - def test_filter_predicate(self): |
4087 | - """You can filter by predicate callbacks""" |
4088 | - filtered_result = unittest.TestResult() |
4089 | - def filter_cb(test, outcome, err, details): |
4090 | - return outcome == 'success' |
4091 | - result_filter = TestResultFilter(filtered_result, |
4092 | - filter_predicate=filter_cb, |
4093 | - filter_success=False) |
4094 | - self.run_tests(result_filter) |
4095 | - # Only success should pass |
4096 | - self.assertEqual(1, filtered_result.testsRun) |
4097 | - |
4098 | - def test_time_ordering_preserved(self): |
4099 | - # Passing a subunit stream through TestResultFilter preserves the |
4100 | - # relative ordering of 'time' directives and any other subunit |
4101 | - # directives that are still included. |
4102 | - date_a = datetime(year=2000, month=1, day=1, tzinfo=iso8601.UTC) |
4103 | - date_b = datetime(year=2000, month=1, day=2, tzinfo=iso8601.UTC) |
4104 | - date_c = datetime(year=2000, month=1, day=3, tzinfo=iso8601.UTC) |
4105 | - subunit_stream = _b('\n'.join([ |
4106 | - "time: %s", |
4107 | - "test: foo", |
4108 | - "time: %s", |
4109 | - "error: foo", |
4110 | - "time: %s", |
4111 | - ""]) % (date_a, date_b, date_c)) |
4112 | - result = ExtendedTestResult() |
4113 | - result_filter = TestResultFilter(result) |
4114 | - self.run_tests(result_filter, subunit_stream) |
4115 | - foo = subunit.RemotedTestCase('foo') |
4116 | - self.assertEquals( |
4117 | - [('time', date_a), |
4118 | - ('startTest', foo), |
4119 | - ('time', date_b), |
4120 | - ('addError', foo, {}), |
4121 | - ('stopTest', foo), |
4122 | - ('time', date_c)], result._events) |
4123 | - |
4124 | - def test_skip_preserved(self): |
4125 | - subunit_stream = _b('\n'.join([ |
4126 | - "test: foo", |
4127 | - "skip: foo", |
4128 | - ""])) |
4129 | - result = ExtendedTestResult() |
4130 | - result_filter = TestResultFilter(result) |
4131 | - self.run_tests(result_filter, subunit_stream) |
4132 | - foo = subunit.RemotedTestCase('foo') |
4133 | - self.assertEquals( |
4134 | - [('startTest', foo), |
4135 | - ('addSkip', foo, {}), |
4136 | - ('stopTest', foo), ], result._events) |
4137 | - |
4138 | - |
4139 | -def test_suite(): |
4140 | - loader = subunit.tests.TestUtil.TestLoader() |
4141 | - result = loader.loadTestsFromName(__name__) |
4142 | - return result |
4143 | |
4144 | === removed file 'python-for-subunit2junitxml/subunit/tests/test_subunit_stats.py' |
4145 | --- python-for-subunit2junitxml/subunit/tests/test_subunit_stats.py 2013-05-27 13:46:13 +0000 |
4146 | +++ python-for-subunit2junitxml/subunit/tests/test_subunit_stats.py 1970-01-01 00:00:00 +0000 |
4147 | @@ -1,84 +0,0 @@ |
4148 | -# |
4149 | -# subunit: extensions to python unittest to get test results from subprocesses. |
4150 | -# Copyright (C) 2005 Robert Collins <robertc@robertcollins.net> |
4151 | -# |
4152 | -# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause |
4153 | -# license at the users choice. A copy of both licenses are available in the |
4154 | -# project source as Apache-2.0 and BSD. You may not use this file except in |
4155 | -# compliance with one of these two licences. |
4156 | -# |
4157 | -# Unless required by applicable law or agreed to in writing, software |
4158 | -# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT |
4159 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
4160 | -# license you chose for the specific language governing permissions and |
4161 | -# limitations under that license. |
4162 | -# |
4163 | - |
4164 | -"""Tests for subunit.TestResultStats.""" |
4165 | - |
4166 | -import unittest |
4167 | - |
4168 | -from testtools.compat import _b, BytesIO, StringIO |
4169 | - |
4170 | -import subunit |
4171 | - |
4172 | - |
4173 | -class TestTestResultStats(unittest.TestCase): |
4174 | - """Test for TestResultStats, a TestResult object that generates stats.""" |
4175 | - |
4176 | - def setUp(self): |
4177 | - self.output = StringIO() |
4178 | - self.result = subunit.TestResultStats(self.output) |
4179 | - self.input_stream = BytesIO() |
4180 | - self.test = subunit.ProtocolTestCase(self.input_stream) |
4181 | - |
4182 | - def test_stats_empty(self): |
4183 | - self.test.run(self.result) |
4184 | - self.assertEqual(0, self.result.total_tests) |
4185 | - self.assertEqual(0, self.result.passed_tests) |
4186 | - self.assertEqual(0, self.result.failed_tests) |
4187 | - self.assertEqual(set(), self.result.seen_tags) |
4188 | - |
4189 | - def setUpUsedStream(self): |
4190 | - self.input_stream.write(_b("""tags: global |
4191 | -test passed |
4192 | -success passed |
4193 | -test failed |
4194 | -tags: local |
4195 | -failure failed |
4196 | -test error |
4197 | -error error |
4198 | -test skipped |
4199 | -skip skipped |
4200 | -test todo |
4201 | -xfail todo |
4202 | -""")) |
4203 | - self.input_stream.seek(0) |
4204 | - self.test.run(self.result) |
4205 | - |
4206 | - def test_stats_smoke_everything(self): |
4207 | - # Statistics are calculated usefully. |
4208 | - self.setUpUsedStream() |
4209 | - self.assertEqual(5, self.result.total_tests) |
4210 | - self.assertEqual(2, self.result.passed_tests) |
4211 | - self.assertEqual(2, self.result.failed_tests) |
4212 | - self.assertEqual(1, self.result.skipped_tests) |
4213 | - self.assertEqual(set(["global", "local"]), self.result.seen_tags) |
4214 | - |
4215 | - def test_stat_formatting(self): |
4216 | - expected = (""" |
4217 | -Total tests: 5 |
4218 | -Passed tests: 2 |
4219 | -Failed tests: 2 |
4220 | -Skipped tests: 1 |
4221 | -Seen tags: global, local |
4222 | -""")[1:] |
4223 | - self.setUpUsedStream() |
4224 | - self.result.formatStats() |
4225 | - self.assertEqual(expected, self.output.getvalue()) |
4226 | - |
4227 | - |
4228 | -def test_suite(): |
4229 | - loader = subunit.tests.TestUtil.TestLoader() |
4230 | - result = loader.loadTestsFromName(__name__) |
4231 | - return result |
4232 | |
4233 | === removed file 'python-for-subunit2junitxml/subunit/tests/test_subunit_tags.py' |
4234 | --- python-for-subunit2junitxml/subunit/tests/test_subunit_tags.py 2013-05-27 13:46:13 +0000 |
4235 | +++ python-for-subunit2junitxml/subunit/tests/test_subunit_tags.py 1970-01-01 00:00:00 +0000 |
4236 | @@ -1,69 +0,0 @@ |
4237 | -# |
4238 | -# subunit: extensions to python unittest to get test results from subprocesses. |
4239 | -# Copyright (C) 2005 Robert Collins <robertc@robertcollins.net> |
4240 | -# |
4241 | -# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause |
4242 | -# license at the users choice. A copy of both licenses are available in the |
4243 | -# project source as Apache-2.0 and BSD. You may not use this file except in |
4244 | -# compliance with one of these two licences. |
4245 | -# |
4246 | -# Unless required by applicable law or agreed to in writing, software |
4247 | -# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT |
4248 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
4249 | -# license you chose for the specific language governing permissions and |
4250 | -# limitations under that license. |
4251 | -# |
4252 | - |
4253 | -"""Tests for subunit.tag_stream.""" |
4254 | - |
4255 | -import unittest |
4256 | - |
4257 | -from testtools.compat import StringIO |
4258 | - |
4259 | -import subunit |
4260 | -import subunit.test_results |
4261 | - |
4262 | - |
4263 | -class TestSubUnitTags(unittest.TestCase): |
4264 | - |
4265 | - def setUp(self): |
4266 | - self.original = StringIO() |
4267 | - self.filtered = StringIO() |
4268 | - |
4269 | - def test_add_tag(self): |
4270 | - self.original.write("tags: foo\n") |
4271 | - self.original.write("test: test\n") |
4272 | - self.original.write("tags: bar -quux\n") |
4273 | - self.original.write("success: test\n") |
4274 | - self.original.seek(0) |
4275 | - result = subunit.tag_stream(self.original, self.filtered, ["quux"]) |
4276 | - self.assertEqual([ |
4277 | - "tags: quux", |
4278 | - "tags: foo", |
4279 | - "test: test", |
4280 | - "tags: bar", |
4281 | - "success: test", |
4282 | - ], |
4283 | - self.filtered.getvalue().splitlines()) |
4284 | - |
4285 | - def test_remove_tag(self): |
4286 | - self.original.write("tags: foo\n") |
4287 | - self.original.write("test: test\n") |
4288 | - self.original.write("tags: bar -quux\n") |
4289 | - self.original.write("success: test\n") |
4290 | - self.original.seek(0) |
4291 | - result = subunit.tag_stream(self.original, self.filtered, ["-bar"]) |
4292 | - self.assertEqual([ |
4293 | - "tags: -bar", |
4294 | - "tags: foo", |
4295 | - "test: test", |
4296 | - "tags: -quux", |
4297 | - "success: test", |
4298 | - ], |
4299 | - self.filtered.getvalue().splitlines()) |
4300 | - |
4301 | - |
4302 | -def test_suite(): |
4303 | - loader = subunit.tests.TestUtil.TestLoader() |
4304 | - result = loader.loadTestsFromName(__name__) |
4305 | - return result |
4306 | |
4307 | === removed file 'python-for-subunit2junitxml/subunit/tests/test_tap2subunit.py' |
4308 | --- python-for-subunit2junitxml/subunit/tests/test_tap2subunit.py 2013-05-27 13:46:13 +0000 |
4309 | +++ python-for-subunit2junitxml/subunit/tests/test_tap2subunit.py 1970-01-01 00:00:00 +0000 |
4310 | @@ -1,445 +0,0 @@ |
4311 | -# |
4312 | -# subunit: extensions to python unittest to get test results from subprocesses. |
4313 | -# Copyright (C) 2005 Robert Collins <robertc@robertcollins.net> |
4314 | -# |
4315 | -# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause |
4316 | -# license at the users choice. A copy of both licenses are available in the |
4317 | -# project source as Apache-2.0 and BSD. You may not use this file except in |
4318 | -# compliance with one of these two licences. |
4319 | -# |
4320 | -# Unless required by applicable law or agreed to in writing, software |
4321 | -# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT |
4322 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
4323 | -# license you chose for the specific language governing permissions and |
4324 | -# limitations under that license. |
4325 | -# |
4326 | - |
4327 | -"""Tests for TAP2SubUnit.""" |
4328 | - |
4329 | -import unittest |
4330 | - |
4331 | -from testtools.compat import StringIO |
4332 | - |
4333 | -import subunit |
4334 | - |
4335 | - |
4336 | -class TestTAP2SubUnit(unittest.TestCase): |
4337 | - """Tests for TAP2SubUnit. |
4338 | - |
4339 | - These tests test TAP string data in, and subunit string data out. |
4340 | - This is ok because the subunit protocol is intended to be stable, |
4341 | - but it might be easier/pithier to write tests against TAP string in, |
4342 | - parsed subunit objects out (by hooking the subunit stream to a subunit |
4343 | - protocol server. |
4344 | - """ |
4345 | - |
4346 | - def setUp(self): |
4347 | - self.tap = StringIO() |
4348 | - self.subunit = StringIO() |
4349 | - |
4350 | - def test_skip_entire_file(self): |
4351 | - # A file |
4352 | - # 1..- # Skipped: comment |
4353 | - # results in a single skipped test. |
4354 | - self.tap.write("1..0 # Skipped: entire file skipped\n") |
4355 | - self.tap.seek(0) |
4356 | - result = subunit.TAP2SubUnit(self.tap, self.subunit) |
4357 | - self.assertEqual(0, result) |
4358 | - self.assertEqual([ |
4359 | - "test file skip", |
4360 | - "skip file skip [", |
4361 | - "Skipped: entire file skipped", |
4362 | - "]", |
4363 | - ], |
4364 | - self.subunit.getvalue().splitlines()) |
4365 | - |
4366 | - def test_ok_test_pass(self): |
4367 | - # A file |
4368 | - # ok |
4369 | - # results in a passed test with name 'test 1' (a synthetic name as tap |
4370 | - # does not require named fixtures - it is the first test in the tap |
4371 | - # stream). |
4372 | - self.tap.write("ok\n") |
4373 | - self.tap.seek(0) |
4374 | - result = subunit.TAP2SubUnit(self.tap, self.subunit) |
4375 | - self.assertEqual(0, result) |
4376 | - self.assertEqual([ |
4377 | - "test test 1", |
4378 | - "success test 1", |
4379 | - ], |
4380 | - self.subunit.getvalue().splitlines()) |
4381 | - |
4382 | - def test_ok_test_number_pass(self): |
4383 | - # A file |
4384 | - # ok 1 |
4385 | - # results in a passed test with name 'test 1' |
4386 | - self.tap.write("ok 1\n") |
4387 | - self.tap.seek(0) |
4388 | - result = subunit.TAP2SubUnit(self.tap, self.subunit) |
4389 | - self.assertEqual(0, result) |
4390 | - self.assertEqual([ |
4391 | - "test test 1", |
4392 | - "success test 1", |
4393 | - ], |
4394 | - self.subunit.getvalue().splitlines()) |
4395 | - |
4396 | - def test_ok_test_number_description_pass(self): |
4397 | - # A file |
4398 | - # ok 1 - There is a description |
4399 | - # results in a passed test with name 'test 1 - There is a description' |
4400 | - self.tap.write("ok 1 - There is a description\n") |
4401 | - self.tap.seek(0) |
4402 | - result = subunit.TAP2SubUnit(self.tap, self.subunit) |
4403 | - self.assertEqual(0, result) |
4404 | - self.assertEqual([ |
4405 | - "test test 1 - There is a description", |
4406 | - "success test 1 - There is a description", |
4407 | - ], |
4408 | - self.subunit.getvalue().splitlines()) |
4409 | - |
4410 | - def test_ok_test_description_pass(self): |
4411 | - # A file |
4412 | - # ok There is a description |
4413 | - # results in a passed test with name 'test 1 There is a description' |
4414 | - self.tap.write("ok There is a description\n") |
4415 | - self.tap.seek(0) |
4416 | - result = subunit.TAP2SubUnit(self.tap, self.subunit) |
4417 | - self.assertEqual(0, result) |
4418 | - self.assertEqual([ |
4419 | - "test test 1 There is a description", |
4420 | - "success test 1 There is a description", |
4421 | - ], |
4422 | - self.subunit.getvalue().splitlines()) |
4423 | - |
4424 | - def test_ok_SKIP_skip(self): |
4425 | - # A file |
4426 | - # ok # SKIP |
4427 | - # results in a skkip test with name 'test 1' |
4428 | - self.tap.write("ok # SKIP\n") |
4429 | - self.tap.seek(0) |
4430 | - result = subunit.TAP2SubUnit(self.tap, self.subunit) |
4431 | - self.assertEqual(0, result) |
4432 | - self.assertEqual([ |
4433 | - "test test 1", |
4434 | - "skip test 1", |
4435 | - ], |
4436 | - self.subunit.getvalue().splitlines()) |
4437 | - |
4438 | - def test_ok_skip_number_comment_lowercase(self): |
4439 | - self.tap.write("ok 1 # skip no samba environment available, skipping compilation\n") |
4440 | - self.tap.seek(0) |
4441 | - result = subunit.TAP2SubUnit(self.tap, self.subunit) |
4442 | - self.assertEqual(0, result) |
4443 | - self.assertEqual([ |
4444 | - "test test 1", |
4445 | - "skip test 1 [", |
4446 | - "no samba environment available, skipping compilation", |
4447 | - "]" |
4448 | - ], |
4449 | - self.subunit.getvalue().splitlines()) |
4450 | - |
4451 | - def test_ok_number_description_SKIP_skip_comment(self): |
4452 | - # A file |
4453 | - # ok 1 foo # SKIP Not done yet |
4454 | - # results in a skip test with name 'test 1 foo' and a log of |
4455 | - # Not done yet |
4456 | - self.tap.write("ok 1 foo # SKIP Not done yet\n") |
4457 | - self.tap.seek(0) |
4458 | - result = subunit.TAP2SubUnit(self.tap, self.subunit) |
4459 | - self.assertEqual(0, result) |
4460 | - self.assertEqual([ |
4461 | - "test test 1 foo", |
4462 | - "skip test 1 foo [", |
4463 | - "Not done yet", |
4464 | - "]", |
4465 | - ], |
4466 | - self.subunit.getvalue().splitlines()) |
4467 | - |
4468 | - def test_ok_SKIP_skip_comment(self): |
4469 | - # A file |
4470 | - # ok # SKIP Not done yet |
4471 | - # results in a skip test with name 'test 1' and a log of Not done yet |
4472 | - self.tap.write("ok # SKIP Not done yet\n") |
4473 | - self.tap.seek(0) |
4474 | - result = subunit.TAP2SubUnit(self.tap, self.subunit) |
4475 | - self.assertEqual(0, result) |
4476 | - self.assertEqual([ |
4477 | - "test test 1", |
4478 | - "skip test 1 [", |
4479 | - "Not done yet", |
4480 | - "]", |
4481 | - ], |
4482 | - self.subunit.getvalue().splitlines()) |
4483 | - |
4484 | - def test_ok_TODO_xfail(self): |
4485 | - # A file |
4486 | - # ok # TODO |
4487 | - # results in a xfail test with name 'test 1' |
4488 | - self.tap.write("ok # TODO\n") |
4489 | - self.tap.seek(0) |
4490 | - result = subunit.TAP2SubUnit(self.tap, self.subunit) |
4491 | - self.assertEqual(0, result) |
4492 | - self.assertEqual([ |
4493 | - "test test 1", |
4494 | - "xfail test 1", |
4495 | - ], |
4496 | - self.subunit.getvalue().splitlines()) |
4497 | - |
4498 | - def test_ok_TODO_xfail_comment(self): |
4499 | - # A file |
4500 | - # ok # TODO Not done yet |
4501 | - # results in a xfail test with name 'test 1' and a log of Not done yet |
4502 | - self.tap.write("ok # TODO Not done yet\n") |
4503 | - self.tap.seek(0) |
4504 | - result = subunit.TAP2SubUnit(self.tap, self.subunit) |
4505 | - self.assertEqual(0, result) |
4506 | - self.assertEqual([ |
4507 | - "test test 1", |
4508 | - "xfail test 1 [", |
4509 | - "Not done yet", |
4510 | - "]", |
4511 | - ], |
4512 | - self.subunit.getvalue().splitlines()) |
4513 | - |
4514 | - def test_bail_out_errors(self): |
4515 | - # A file with line in it |
4516 | - # Bail out! COMMENT |
4517 | - # is treated as an error |
4518 | - self.tap.write("ok 1 foo\n") |
4519 | - self.tap.write("Bail out! Lifejacket engaged\n") |
4520 | - self.tap.seek(0) |
4521 | - result = subunit.TAP2SubUnit(self.tap, self.subunit) |
4522 | - self.assertEqual(0, result) |
4523 | - self.assertEqual([ |
4524 | - "test test 1 foo", |
4525 | - "success test 1 foo", |
4526 | - "test Bail out! Lifejacket engaged", |
4527 | - "error Bail out! Lifejacket engaged", |
4528 | - ], |
4529 | - self.subunit.getvalue().splitlines()) |
4530 | - |
4531 | - def test_missing_test_at_end_with_plan_adds_error(self): |
4532 | - # A file |
4533 | - # 1..3 |
4534 | - # ok first test |
4535 | - # not ok third test |
4536 | - # results in three tests, with the third being created |
4537 | - self.tap.write('1..3\n') |
4538 | - self.tap.write('ok first test\n') |
4539 | - self.tap.write('not ok second test\n') |
4540 | - self.tap.seek(0) |
4541 | - result = subunit.TAP2SubUnit(self.tap, self.subunit) |
4542 | - self.assertEqual(0, result) |
4543 | - self.assertEqual([ |
4544 | - 'test test 1 first test', |
4545 | - 'success test 1 first test', |
4546 | - 'test test 2 second test', |
4547 | - 'failure test 2 second test', |
4548 | - 'test test 3', |
4549 | - 'error test 3 [', |
4550 | - 'test missing from TAP output', |
4551 | - ']', |
4552 | - ], |
4553 | - self.subunit.getvalue().splitlines()) |
4554 | - |
4555 | - def test_missing_test_with_plan_adds_error(self): |
4556 | - # A file |
4557 | - # 1..3 |
4558 | - # ok first test |
4559 | - # not ok 3 third test |
4560 | - # results in three tests, with the second being created |
4561 | - self.tap.write('1..3\n') |
4562 | - self.tap.write('ok first test\n') |
4563 | - self.tap.write('not ok 3 third test\n') |
4564 | - self.tap.seek(0) |
4565 | - result = subunit.TAP2SubUnit(self.tap, self.subunit) |
4566 | - self.assertEqual(0, result) |
4567 | - self.assertEqual([ |
4568 | - 'test test 1 first test', |
4569 | - 'success test 1 first test', |
4570 | - 'test test 2', |
4571 | - 'error test 2 [', |
4572 | - 'test missing from TAP output', |
4573 | - ']', |
4574 | - 'test test 3 third test', |
4575 | - 'failure test 3 third test', |
4576 | - ], |
4577 | - self.subunit.getvalue().splitlines()) |
4578 | - |
4579 | - def test_missing_test_no_plan_adds_error(self): |
4580 | - # A file |
4581 | - # ok first test |
4582 | - # not ok 3 third test |
4583 | - # results in three tests, with the second being created |
4584 | - self.tap.write('ok first test\n') |
4585 | - self.tap.write('not ok 3 third test\n') |
4586 | - self.tap.seek(0) |
4587 | - result = subunit.TAP2SubUnit(self.tap, self.subunit) |
4588 | - self.assertEqual(0, result) |
4589 | - self.assertEqual([ |
4590 | - 'test test 1 first test', |
4591 | - 'success test 1 first test', |
4592 | - 'test test 2', |
4593 | - 'error test 2 [', |
4594 | - 'test missing from TAP output', |
4595 | - ']', |
4596 | - 'test test 3 third test', |
4597 | - 'failure test 3 third test', |
4598 | - ], |
4599 | - self.subunit.getvalue().splitlines()) |
4600 | - |
4601 | - def test_four_tests_in_a_row_trailing_plan(self): |
4602 | - # A file |
4603 | - # ok 1 - first test in a script with no plan at all |
4604 | - # not ok 2 - second |
4605 | - # ok 3 - third |
4606 | - # not ok 4 - fourth |
4607 | - # 1..4 |
4608 | - # results in four tests numbered and named |
4609 | - self.tap.write('ok 1 - first test in a script with trailing plan\n') |
4610 | - self.tap.write('not ok 2 - second\n') |
4611 | - self.tap.write('ok 3 - third\n') |
4612 | - self.tap.write('not ok 4 - fourth\n') |
4613 | - self.tap.write('1..4\n') |
4614 | - self.tap.seek(0) |
4615 | - result = subunit.TAP2SubUnit(self.tap, self.subunit) |
4616 | - self.assertEqual(0, result) |
4617 | - self.assertEqual([ |
4618 | - 'test test 1 - first test in a script with trailing plan', |
4619 | - 'success test 1 - first test in a script with trailing plan', |
4620 | - 'test test 2 - second', |
4621 | - 'failure test 2 - second', |
4622 | - 'test test 3 - third', |
4623 | - 'success test 3 - third', |
4624 | - 'test test 4 - fourth', |
4625 | - 'failure test 4 - fourth' |
4626 | - ], |
4627 | - self.subunit.getvalue().splitlines()) |
4628 | - |
4629 | - def test_four_tests_in_a_row_with_plan(self): |
4630 | - # A file |
4631 | - # 1..4 |
4632 | - # ok 1 - first test in a script with no plan at all |
4633 | - # not ok 2 - second |
4634 | - # ok 3 - third |
4635 | - # not ok 4 - fourth |
4636 | - # results in four tests numbered and named |
4637 | - self.tap.write('1..4\n') |
4638 | - self.tap.write('ok 1 - first test in a script with a plan\n') |
4639 | - self.tap.write('not ok 2 - second\n') |
4640 | - self.tap.write('ok 3 - third\n') |
4641 | - self.tap.write('not ok 4 - fourth\n') |
4642 | - self.tap.seek(0) |
4643 | - result = subunit.TAP2SubUnit(self.tap, self.subunit) |
4644 | - self.assertEqual(0, result) |
4645 | - self.assertEqual([ |
4646 | - 'test test 1 - first test in a script with a plan', |
4647 | - 'success test 1 - first test in a script with a plan', |
4648 | - 'test test 2 - second', |
4649 | - 'failure test 2 - second', |
4650 | - 'test test 3 - third', |
4651 | - 'success test 3 - third', |
4652 | - 'test test 4 - fourth', |
4653 | - 'failure test 4 - fourth' |
4654 | - ], |
4655 | - self.subunit.getvalue().splitlines()) |
4656 | - |
4657 | - def test_four_tests_in_a_row_no_plan(self): |
4658 | - # A file |
4659 | - # ok 1 - first test in a script with no plan at all |
4660 | - # not ok 2 - second |
4661 | - # ok 3 - third |
4662 | - # not ok 4 - fourth |
4663 | - # results in four tests numbered and named |
4664 | - self.tap.write('ok 1 - first test in a script with no plan at all\n') |
4665 | - self.tap.write('not ok 2 - second\n') |
4666 | - self.tap.write('ok 3 - third\n') |
4667 | - self.tap.write('not ok 4 - fourth\n') |
4668 | - self.tap.seek(0) |
4669 | - result = subunit.TAP2SubUnit(self.tap, self.subunit) |
4670 | - self.assertEqual(0, result) |
4671 | - self.assertEqual([ |
4672 | - 'test test 1 - first test in a script with no plan at all', |
4673 | - 'success test 1 - first test in a script with no plan at all', |
4674 | - 'test test 2 - second', |
4675 | - 'failure test 2 - second', |
4676 | - 'test test 3 - third', |
4677 | - 'success test 3 - third', |
4678 | - 'test test 4 - fourth', |
4679 | - 'failure test 4 - fourth' |
4680 | - ], |
4681 | - self.subunit.getvalue().splitlines()) |
4682 | - |
4683 | - def test_todo_and_skip(self): |
4684 | - # A file |
4685 | - # not ok 1 - a fail but # TODO but is TODO |
4686 | - # not ok 2 - another fail # SKIP instead |
4687 | - # results in two tests, numbered and commented. |
4688 | - self.tap.write("not ok 1 - a fail but # TODO but is TODO\n") |
4689 | - self.tap.write("not ok 2 - another fail # SKIP instead\n") |
4690 | - self.tap.seek(0) |
4691 | - result = subunit.TAP2SubUnit(self.tap, self.subunit) |
4692 | - self.assertEqual(0, result) |
4693 | - self.assertEqual([ |
4694 | - 'test test 1 - a fail but', |
4695 | - 'xfail test 1 - a fail but [', |
4696 | - 'but is TODO', |
4697 | - ']', |
4698 | - 'test test 2 - another fail', |
4699 | - 'skip test 2 - another fail [', |
4700 | - 'instead', |
4701 | - ']', |
4702 | - ], |
4703 | - self.subunit.getvalue().splitlines()) |
4704 | - |
4705 | - def test_leading_comments_add_to_next_test_log(self): |
4706 | - # A file |
4707 | - # # comment |
4708 | - # ok |
4709 | - # ok |
4710 | - # results in a single test with the comment included |
4711 | - # in the first test and not the second. |
4712 | - self.tap.write("# comment\n") |
4713 | - self.tap.write("ok\n") |
4714 | - self.tap.write("ok\n") |
4715 | - self.tap.seek(0) |
4716 | - result = subunit.TAP2SubUnit(self.tap, self.subunit) |
4717 | - self.assertEqual(0, result) |
4718 | - self.assertEqual([ |
4719 | - 'test test 1', |
4720 | - 'success test 1 [', |
4721 | - '# comment', |
4722 | - ']', |
4723 | - 'test test 2', |
4724 | - 'success test 2', |
4725 | - ], |
4726 | - self.subunit.getvalue().splitlines()) |
4727 | - |
4728 | - def test_trailing_comments_are_included_in_last_test_log(self): |
4729 | - # A file |
4730 | - # ok foo |
4731 | - # ok foo |
4732 | - # # comment |
4733 | - # results in a two tests, with the second having the comment |
4734 | - # attached to its log. |
4735 | - self.tap.write("ok\n") |
4736 | - self.tap.write("ok\n") |
4737 | - self.tap.write("# comment\n") |
4738 | - self.tap.seek(0) |
4739 | - result = subunit.TAP2SubUnit(self.tap, self.subunit) |
4740 | - self.assertEqual(0, result) |
4741 | - self.assertEqual([ |
4742 | - 'test test 1', |
4743 | - 'success test 1', |
4744 | - 'test test 2', |
4745 | - 'success test 2 [', |
4746 | - '# comment', |
4747 | - ']', |
4748 | - ], |
4749 | - self.subunit.getvalue().splitlines()) |
4750 | - |
4751 | - |
4752 | -def test_suite(): |
4753 | - loader = subunit.tests.TestUtil.TestLoader() |
4754 | - result = loader.loadTestsFromName(__name__) |
4755 | - return result |
4756 | |
4757 | === removed file 'python-for-subunit2junitxml/subunit/tests/test_test_protocol.py' |
4758 | --- python-for-subunit2junitxml/subunit/tests/test_test_protocol.py 2013-05-27 13:46:13 +0000 |
4759 | +++ python-for-subunit2junitxml/subunit/tests/test_test_protocol.py 1970-01-01 00:00:00 +0000 |
4760 | @@ -1,1299 +0,0 @@ |
4761 | -# |
4762 | -# subunit: extensions to Python unittest to get test results from subprocesses. |
4763 | -# Copyright (C) 2005 Robert Collins <robertc@robertcollins.net> |
4764 | -# |
4765 | -# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause |
4766 | -# license at the users choice. A copy of both licenses are available in the |
4767 | -# project source as Apache-2.0 and BSD. You may not use this file except in |
4768 | -# compliance with one of these two licences. |
4769 | -# |
4770 | -# Unless required by applicable law or agreed to in writing, software |
4771 | -# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT |
4772 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
4773 | -# license you chose for the specific language governing permissions and |
4774 | -# limitations under that license. |
4775 | -# |
4776 | - |
4777 | -import datetime |
4778 | -import unittest |
4779 | -import os |
4780 | - |
4781 | -from testtools import skipIf, TestCase |
4782 | -from testtools.compat import _b, _u, BytesIO, StringIO |
4783 | -from testtools.content import Content, TracebackContent |
4784 | -from testtools.content_type import ContentType |
4785 | -from testtools.tests.helpers import ( |
4786 | - Python26TestResult, |
4787 | - Python27TestResult, |
4788 | - ExtendedTestResult, |
4789 | - ) |
4790 | - |
4791 | -import subunit |
4792 | -from subunit import _remote_exception_str, _remote_exception_str_chunked |
4793 | -import subunit.iso8601 as iso8601 |
4794 | - |
4795 | - |
4796 | -class TestTestImports(unittest.TestCase): |
4797 | - |
4798 | - def test_imports(self): |
4799 | - from subunit import DiscardStream |
4800 | - from subunit import TestProtocolServer |
4801 | - from subunit import RemotedTestCase |
4802 | - from subunit import RemoteError |
4803 | - from subunit import ExecTestCase |
4804 | - from subunit import IsolatedTestCase |
4805 | - from subunit import TestProtocolClient |
4806 | - from subunit import ProtocolTestCase |
4807 | - |
4808 | - |
4809 | -class TestDiscardStream(unittest.TestCase): |
4810 | - |
4811 | - def test_write(self): |
4812 | - subunit.DiscardStream().write("content") |
4813 | - |
4814 | - |
4815 | -class TestProtocolServerForward(unittest.TestCase): |
4816 | - |
4817 | - def test_story(self): |
4818 | - client = unittest.TestResult() |
4819 | - out = BytesIO() |
4820 | - protocol = subunit.TestProtocolServer(client, forward_stream=out) |
4821 | - pipe = BytesIO(_b("test old mcdonald\n" |
4822 | - "success old mcdonald\n")) |
4823 | - protocol.readFrom(pipe) |
4824 | - self.assertEqual(client.testsRun, 1) |
4825 | - self.assertEqual(pipe.getvalue(), out.getvalue()) |
4826 | - |
4827 | - def test_not_command(self): |
4828 | - client = unittest.TestResult() |
4829 | - out = BytesIO() |
4830 | - protocol = subunit.TestProtocolServer(client, |
4831 | - stream=subunit.DiscardStream(), forward_stream=out) |
4832 | - pipe = BytesIO(_b("success old mcdonald\n")) |
4833 | - protocol.readFrom(pipe) |
4834 | - self.assertEqual(client.testsRun, 0) |
4835 | - self.assertEqual(_b(""), out.getvalue()) |
4836 | - |
4837 | - |
4838 | -class TestTestProtocolServerPipe(unittest.TestCase): |
4839 | - |
4840 | - def test_story(self): |
4841 | - client = unittest.TestResult() |
4842 | - protocol = subunit.TestProtocolServer(client) |
4843 | - pipe = BytesIO(_b("test old mcdonald\n" |
4844 | - "success old mcdonald\n" |
4845 | - "test bing crosby\n" |
4846 | - "failure bing crosby [\n" |
4847 | - "foo.c:53:ERROR invalid state\n" |
4848 | - "]\n" |
4849 | - "test an error\n" |
4850 | - "error an error\n")) |
4851 | - protocol.readFrom(pipe) |
4852 | - bing = subunit.RemotedTestCase("bing crosby") |
4853 | - an_error = subunit.RemotedTestCase("an error") |
4854 | - self.assertEqual(client.errors, |
4855 | - [(an_error, _remote_exception_str + '\n')]) |
4856 | - self.assertEqual( |
4857 | - client.failures, |
4858 | - [(bing, _remote_exception_str + ": Text attachment: traceback\n" |
4859 | - "------------\nfoo.c:53:ERROR invalid state\n" |
4860 | - "------------\n\n")]) |
4861 | - self.assertEqual(client.testsRun, 3) |
4862 | - |
4863 | - def test_non_test_characters_forwarded_immediately(self): |
4864 | - pass |
4865 | - |
4866 | - |
4867 | -class TestTestProtocolServerStartTest(unittest.TestCase): |
4868 | - |
4869 | - def setUp(self): |
4870 | - self.client = Python26TestResult() |
4871 | - self.stream = BytesIO() |
4872 | - self.protocol = subunit.TestProtocolServer(self.client, self.stream) |
4873 | - |
4874 | - def test_start_test(self): |
4875 | - self.protocol.lineReceived(_b("test old mcdonald\n")) |
4876 | - self.assertEqual(self.client._events, |
4877 | - [('startTest', subunit.RemotedTestCase("old mcdonald"))]) |
4878 | - |
4879 | - def test_start_testing(self): |
4880 | - self.protocol.lineReceived(_b("testing old mcdonald\n")) |
4881 | - self.assertEqual(self.client._events, |
4882 | - [('startTest', subunit.RemotedTestCase("old mcdonald"))]) |
4883 | - |
4884 | - def test_start_test_colon(self): |
4885 | - self.protocol.lineReceived(_b("test: old mcdonald\n")) |
4886 | - self.assertEqual(self.client._events, |
4887 | - [('startTest', subunit.RemotedTestCase("old mcdonald"))]) |
4888 | - |
4889 | - def test_indented_test_colon_ignored(self): |
4890 | - ignored_line = _b(" test: old mcdonald\n") |
4891 | - self.protocol.lineReceived(ignored_line) |
4892 | - self.assertEqual([], self.client._events) |
4893 | - self.assertEqual(self.stream.getvalue(), ignored_line) |
4894 | - |
4895 | - def test_start_testing_colon(self): |
4896 | - self.protocol.lineReceived(_b("testing: old mcdonald\n")) |
4897 | - self.assertEqual(self.client._events, |
4898 | - [('startTest', subunit.RemotedTestCase("old mcdonald"))]) |
4899 | - |
4900 | - |
4901 | -class TestTestProtocolServerPassThrough(unittest.TestCase): |
4902 | - |
4903 | - def setUp(self): |
4904 | - self.stdout = BytesIO() |
4905 | - self.test = subunit.RemotedTestCase("old mcdonald") |
4906 | - self.client = ExtendedTestResult() |
4907 | - self.protocol = subunit.TestProtocolServer(self.client, self.stdout) |
4908 | - |
4909 | - def keywords_before_test(self): |
4910 | - self.protocol.lineReceived(_b("failure a\n")) |
4911 | - self.protocol.lineReceived(_b("failure: a\n")) |
4912 | - self.protocol.lineReceived(_b("error a\n")) |
4913 | - self.protocol.lineReceived(_b("error: a\n")) |
4914 | - self.protocol.lineReceived(_b("success a\n")) |
4915 | - self.protocol.lineReceived(_b("success: a\n")) |
4916 | - self.protocol.lineReceived(_b("successful a\n")) |
4917 | - self.protocol.lineReceived(_b("successful: a\n")) |
4918 | - self.protocol.lineReceived(_b("]\n")) |
4919 | - self.assertEqual(self.stdout.getvalue(), _b("failure a\n" |
4920 | - "failure: a\n" |
4921 | - "error a\n" |
4922 | - "error: a\n" |
4923 | - "success a\n" |
4924 | - "success: a\n" |
4925 | - "successful a\n" |
4926 | - "successful: a\n" |
4927 | - "]\n")) |
4928 | - |
4929 | - def test_keywords_before_test(self): |
4930 | - self.keywords_before_test() |
4931 | - self.assertEqual(self.client._events, []) |
4932 | - |
4933 | - def test_keywords_after_error(self): |
4934 | - self.protocol.lineReceived(_b("test old mcdonald\n")) |
4935 | - self.protocol.lineReceived(_b("error old mcdonald\n")) |
4936 | - self.keywords_before_test() |
4937 | - self.assertEqual([ |
4938 | - ('startTest', self.test), |
4939 | - ('addError', self.test, {}), |
4940 | - ('stopTest', self.test), |
4941 | - ], self.client._events) |
4942 | - |
4943 | - def test_keywords_after_failure(self): |
4944 | - self.protocol.lineReceived(_b("test old mcdonald\n")) |
4945 | - self.protocol.lineReceived(_b("failure old mcdonald\n")) |
4946 | - self.keywords_before_test() |
4947 | - self.assertEqual(self.client._events, [ |
4948 | - ('startTest', self.test), |
4949 | - ('addFailure', self.test, {}), |
4950 | - ('stopTest', self.test), |
4951 | - ]) |
4952 | - |
4953 | - def test_keywords_after_success(self): |
4954 | - self.protocol.lineReceived(_b("test old mcdonald\n")) |
4955 | - self.protocol.lineReceived(_b("success old mcdonald\n")) |
4956 | - self.keywords_before_test() |
4957 | - self.assertEqual([ |
4958 | - ('startTest', self.test), |
4959 | - ('addSuccess', self.test), |
4960 | - ('stopTest', self.test), |
4961 | - ], self.client._events) |
4962 | - |
4963 | - def test_keywords_after_test(self): |
4964 | - self.protocol.lineReceived(_b("test old mcdonald\n")) |
4965 | - self.protocol.lineReceived(_b("test old mcdonald\n")) |
4966 | - self.protocol.lineReceived(_b("failure a\n")) |
4967 | - self.protocol.lineReceived(_b("failure: a\n")) |
4968 | - self.protocol.lineReceived(_b("error a\n")) |
4969 | - self.protocol.lineReceived(_b("error: a\n")) |
4970 | - self.protocol.lineReceived(_b("success a\n")) |
4971 | - self.protocol.lineReceived(_b("success: a\n")) |
4972 | - self.protocol.lineReceived(_b("successful a\n")) |
4973 | - self.protocol.lineReceived(_b("successful: a\n")) |
4974 | - self.protocol.lineReceived(_b("]\n")) |
4975 | - self.protocol.lineReceived(_b("failure old mcdonald\n")) |
4976 | - self.assertEqual(self.stdout.getvalue(), _b("test old mcdonald\n" |
4977 | - "failure a\n" |
4978 | - "failure: a\n" |
4979 | - "error a\n" |
4980 | - "error: a\n" |
4981 | - "success a\n" |
4982 | - "success: a\n" |
4983 | - "successful a\n" |
4984 | - "successful: a\n" |
4985 | - "]\n")) |
4986 | - self.assertEqual(self.client._events, [ |
4987 | - ('startTest', self.test), |
4988 | - ('addFailure', self.test, {}), |
4989 | - ('stopTest', self.test), |
4990 | - ]) |
4991 | - |
4992 | - def test_keywords_during_failure(self): |
4993 | - # A smoke test to make sure that the details parsers have control |
4994 | - # appropriately. |
4995 | - self.protocol.lineReceived(_b("test old mcdonald\n")) |
4996 | - self.protocol.lineReceived(_b("failure: old mcdonald [\n")) |
4997 | - self.protocol.lineReceived(_b("test old mcdonald\n")) |
4998 | - self.protocol.lineReceived(_b("failure a\n")) |
4999 | - self.protocol.lineReceived(_b("failure: a\n")) |
5000 | - self.protocol.lineReceived(_b("error a\n")) |
The diff has been truncated for viewing.