Move details parsing into a separate class.
[third_party/subunit] / python / subunit / tests / test_test_protocol.py
1 #
2 #  subunit: extensions to Python unittest to get test results from subprocesses.
3 #  Copyright (C) 2005  Robert Collins <robertc@robertcollins.net>
4 #
5 #  Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
6 #  license at the users choice. A copy of both licenses are available in the
7 #  project source as Apache-2.0 and BSD. You may not use this file except in
8 #  compliance with one of these two licences.
9 #  
10 #  Unless required by applicable law or agreed to in writing, software
11 #  distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
12 #  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
13 #  license you chose for the specific language governing permissions and
14 #  limitations under that license.
15 #
16
17 import datetime
18 import unittest
19 from StringIO import StringIO
20 import os
21 import sys
22
23 import subunit
24 from subunit.content import Content, TracebackContent
25 from subunit.content_type import ContentType
26 import subunit.iso8601 as iso8601
27
28
29 class MockTestProtocolServerClient(object):
30     """A mock protocol server client to test callbacks.
31     
32     Note that this is deliberately not Python 2.7 complete, to allow
33     testing compatibility - we need a TestResult that will not have new methods
34     like addExpectedFailure.
35     """
36
37     def __init__(self):
38         self.end_calls = []
39         self.error_calls = []
40         self.failure_calls = []
41         self.skip_calls = []
42         self.start_calls = []
43         self.success_calls = []
44         self.progress_calls = []
45         self._time = None
46         super(MockTestProtocolServerClient, self).__init__()
47
48     def addError(self, test, error):
49         self.error_calls.append((test, error))
50
51     def addFailure(self, test, error):
52         self.failure_calls.append((test, error))
53
54     def addSkip(self, test, reason):
55         self.skip_calls.append((test, reason))
56
57     def addSuccess(self, test):
58         self.success_calls.append(test)
59
60     def stopTest(self, test):
61         self.end_calls.append(test)
62
63     def startTest(self, test):
64         self.start_calls.append(test)
65
66     def progress(self, offset, whence):
67         self.progress_calls.append((offset, whence))
68
69     def time(self, time):
70         self._time = time
71
72
73 class MockExtendedTestProtocolServerClient(MockTestProtocolServerClient):
74     """An extended TestResult for testing which implements tags() etc."""
75
76     def __init__(self):
77         MockTestProtocolServerClient.__init__(self)
78         self.new_tags = set()
79         self.gone_tags = set()
80
81     def tags(self, new_tags, gone_tags):
82         self.new_tags = new_tags
83         self.gone_tags = gone_tags
84
85
86 class TestMockTestProtocolServer(unittest.TestCase):
87
88     def test_start_test(self):
89         protocol = MockTestProtocolServerClient()
90         protocol.startTest(subunit.RemotedTestCase("test old mcdonald"))
91         self.assertEqual(protocol.start_calls,
92                          [subunit.RemotedTestCase("test old mcdonald")])
93         self.assertEqual(protocol.end_calls, [])
94         self.assertEqual(protocol.error_calls, [])
95         self.assertEqual(protocol.failure_calls, [])
96         self.assertEqual(protocol.success_calls, [])
97
98     def test_add_error(self):
99         protocol = MockTestProtocolServerClient()
100         protocol.addError(subunit.RemotedTestCase("old mcdonald"),
101                           subunit.RemoteError("omg it works"))
102         self.assertEqual(protocol.start_calls, [])
103         self.assertEqual(protocol.end_calls, [])
104         self.assertEqual(protocol.error_calls, [(
105                             subunit.RemotedTestCase("old mcdonald"),
106                             subunit.RemoteError("omg it works"))])
107         self.assertEqual(protocol.failure_calls, [])
108         self.assertEqual(protocol.success_calls, [])
109
110     def test_add_failure(self):
111         protocol = MockTestProtocolServerClient()
112         protocol.addFailure(subunit.RemotedTestCase("old mcdonald"),
113                             subunit.RemoteError("omg it works"))
114         self.assertEqual(protocol.start_calls, [])
115         self.assertEqual(protocol.end_calls, [])
116         self.assertEqual(protocol.error_calls, [])
117         self.assertEqual(protocol.failure_calls, [
118                             (subunit.RemotedTestCase("old mcdonald"),
119                              subunit.RemoteError("omg it works"))])
120         self.assertEqual(protocol.success_calls, [])
121
122     def test_add_success(self):
123         protocol = MockTestProtocolServerClient()
124         protocol.addSuccess(subunit.RemotedTestCase("test old mcdonald"))
125         self.assertEqual(protocol.start_calls, [])
126         self.assertEqual(protocol.end_calls, [])
127         self.assertEqual(protocol.error_calls, [])
128         self.assertEqual(protocol.failure_calls, [])
129         self.assertEqual(protocol.success_calls,
130                          [subunit.RemotedTestCase("test old mcdonald")])
131
132     def test_end_test(self):
133         protocol = MockTestProtocolServerClient()
134         protocol.stopTest(subunit.RemotedTestCase("test old mcdonald"))
135         self.assertEqual(protocol.end_calls,
136                          [subunit.RemotedTestCase("test old mcdonald")])
137         self.assertEqual(protocol.error_calls, [])
138         self.assertEqual(protocol.failure_calls, [])
139         self.assertEqual(protocol.success_calls, [])
140         self.assertEqual(protocol.start_calls, [])
141
142     def test_progress(self):
143         protocol = MockTestProtocolServerClient()
144         protocol.progress(-1, subunit.PROGRESS_CUR)
145         self.assertEqual(protocol.progress_calls, [(-1, subunit.PROGRESS_CUR)])
146
147
148 class TestTestImports(unittest.TestCase):
149
150     def test_imports(self):
151         from subunit import DiscardStream
152         from subunit import TestProtocolServer
153         from subunit import RemotedTestCase
154         from subunit import RemoteError
155         from subunit import ExecTestCase
156         from subunit import IsolatedTestCase
157         from subunit import TestProtocolClient
158
159
160 class TestDiscardStream(unittest.TestCase):
161
162     def test_write(self):
163         subunit.DiscardStream().write("content")
164
165
166 class TestTestProtocolServerPipe(unittest.TestCase):
167
168     def test_story(self):
169         client = unittest.TestResult()
170         protocol = subunit.TestProtocolServer(client)
171         pipe = StringIO("test old mcdonald\n"
172                         "success old mcdonald\n"
173                         "test bing crosby\n"
174                         "failure bing crosby [\n"
175                         "foo.c:53:ERROR invalid state\n"
176                         "]\n"
177                         "test an error\n"
178                         "error an error\n")
179         protocol.readFrom(pipe)
180         mcdonald = subunit.RemotedTestCase("old mcdonald")
181         bing = subunit.RemotedTestCase("bing crosby")
182         an_error = subunit.RemotedTestCase("an error")
183         self.assertEqual(client.errors,
184                          [(an_error, 'RemoteException: \n\n')])
185         self.assertEqual(
186             client.failures,
187             [(bing, "RemoteException: foo.c:53:ERROR invalid state\n\n")])
188         self.assertEqual(client.testsRun, 3)
189
190
191 class TestTestProtocolServerStartTest(unittest.TestCase):
192
193     def setUp(self):
194         self.client = MockTestProtocolServerClient()
195         self.protocol = subunit.TestProtocolServer(self.client)
196
197     def test_start_test(self):
198         self.protocol.lineReceived("test old mcdonald\n")
199         self.assertEqual(self.client.start_calls,
200                          [subunit.RemotedTestCase("old mcdonald")])
201
202     def test_start_testing(self):
203         self.protocol.lineReceived("testing old mcdonald\n")
204         self.assertEqual(self.client.start_calls,
205                          [subunit.RemotedTestCase("old mcdonald")])
206
207     def test_start_test_colon(self):
208         self.protocol.lineReceived("test: old mcdonald\n")
209         self.assertEqual(self.client.start_calls,
210                          [subunit.RemotedTestCase("old mcdonald")])
211
212     def test_start_testing_colon(self):
213         self.protocol.lineReceived("testing: old mcdonald\n")
214         self.assertEqual(self.client.start_calls,
215                          [subunit.RemotedTestCase("old mcdonald")])
216
217
218 class TestTestProtocolServerPassThrough(unittest.TestCase):
219
220     def setUp(self):
221         self.stdout = StringIO()
222         self.test = subunit.RemotedTestCase("old mcdonald")
223         self.client = MockTestProtocolServerClient()
224         self.protocol = subunit.TestProtocolServer(self.client, self.stdout)
225
226     def keywords_before_test(self):
227         self.protocol.lineReceived("failure a\n")
228         self.protocol.lineReceived("failure: a\n")
229         self.protocol.lineReceived("error a\n")
230         self.protocol.lineReceived("error: a\n")
231         self.protocol.lineReceived("success a\n")
232         self.protocol.lineReceived("success: a\n")
233         self.protocol.lineReceived("successful a\n")
234         self.protocol.lineReceived("successful: a\n")
235         self.protocol.lineReceived("]\n")
236         self.assertEqual(self.stdout.getvalue(), "failure a\n"
237                                                  "failure: a\n"
238                                                  "error a\n"
239                                                  "error: a\n"
240                                                  "success a\n"
241                                                  "success: a\n"
242                                                  "successful a\n"
243                                                  "successful: a\n"
244                                                  "]\n")
245
246     def test_keywords_before_test(self):
247         self.keywords_before_test()
248         self.assertEqual(self.client.start_calls, [])
249         self.assertEqual(self.client.error_calls, [])
250         self.assertEqual(self.client.failure_calls, [])
251         self.assertEqual(self.client.success_calls, [])
252
253     def test_keywords_after_error(self):
254         self.protocol.lineReceived("test old mcdonald\n")
255         self.protocol.lineReceived("error old mcdonald\n")
256         self.keywords_before_test()
257         self.assertEqual(self.client.start_calls, [self.test])
258         self.assertEqual(self.client.end_calls, [self.test])
259         self.assertEqual(self.client.error_calls,
260                          [(self.test, subunit.RemoteError(""))])
261         self.assertEqual(self.client.failure_calls, [])
262         self.assertEqual(self.client.success_calls, [])
263
264     def test_keywords_after_failure(self):
265         self.protocol.lineReceived("test old mcdonald\n")
266         self.protocol.lineReceived("failure old mcdonald\n")
267         self.keywords_before_test()
268         self.assertEqual(self.client.start_calls, [self.test])
269         self.assertEqual(self.client.end_calls, [self.test])
270         self.assertEqual(self.client.error_calls, [])
271         self.assertEqual(self.client.failure_calls,
272                          [(self.test, subunit.RemoteError())])
273         self.assertEqual(self.client.success_calls, [])
274
275     def test_keywords_after_success(self):
276         self.protocol.lineReceived("test old mcdonald\n")
277         self.protocol.lineReceived("success old mcdonald\n")
278         self.keywords_before_test()
279         self.assertEqual(self.client.start_calls, [self.test])
280         self.assertEqual(self.client.end_calls, [self.test])
281         self.assertEqual(self.client.error_calls, [])
282         self.assertEqual(self.client.failure_calls, [])
283         self.assertEqual(self.client.success_calls, [self.test])
284
285     def test_keywords_after_test(self):
286         self.protocol.lineReceived("test old mcdonald\n")
287         self.protocol.lineReceived("test old mcdonald\n")
288         self.protocol.lineReceived("failure a\n")
289         self.protocol.lineReceived("failure: a\n")
290         self.protocol.lineReceived("error a\n")
291         self.protocol.lineReceived("error: a\n")
292         self.protocol.lineReceived("success a\n")
293         self.protocol.lineReceived("success: a\n")
294         self.protocol.lineReceived("successful a\n")
295         self.protocol.lineReceived("successful: a\n")
296         self.protocol.lineReceived("]\n")
297         self.protocol.lineReceived("failure old mcdonald\n")
298         self.assertEqual(self.stdout.getvalue(), "test old mcdonald\n"
299                                                  "failure a\n"
300                                                  "failure: a\n"
301                                                  "error a\n"
302                                                  "error: a\n"
303                                                  "success a\n"
304                                                  "success: a\n"
305                                                  "successful a\n"
306                                                  "successful: a\n"
307                                                  "]\n")
308         self.assertEqual(self.client.start_calls, [self.test])
309         self.assertEqual(self.client.end_calls, [self.test])
310         self.assertEqual(self.client.failure_calls,
311                          [(self.test, subunit.RemoteError())])
312         self.assertEqual(self.client.error_calls, [])
313         self.assertEqual(self.client.success_calls, [])
314
315     def test_keywords_during_failure(self):
316         self.protocol.lineReceived("test old mcdonald\n")
317         self.protocol.lineReceived("failure: old mcdonald [\n")
318         self.protocol.lineReceived("test old mcdonald\n")
319         self.protocol.lineReceived("failure a\n")
320         self.protocol.lineReceived("failure: a\n")
321         self.protocol.lineReceived("error a\n")
322         self.protocol.lineReceived("error: a\n")
323         self.protocol.lineReceived("success a\n")
324         self.protocol.lineReceived("success: a\n")
325         self.protocol.lineReceived("successful a\n")
326         self.protocol.lineReceived("successful: a\n")
327         self.protocol.lineReceived(" ]\n")
328         self.protocol.lineReceived("]\n")
329         self.assertEqual(self.stdout.getvalue(), "")
330         self.assertEqual(self.client.start_calls, [self.test])
331         self.assertEqual(self.client.failure_calls,
332                          [(self.test, subunit.RemoteError("test old mcdonald\n"
333                                                   "failure a\n"
334                                                   "failure: a\n"
335                                                   "error a\n"
336                                                   "error: a\n"
337                                                   "success a\n"
338                                                   "success: a\n"
339                                                   "successful a\n"
340                                                   "successful: a\n"
341                                                   "]\n"))])
342         self.assertEqual(self.client.end_calls, [self.test])
343         self.assertEqual(self.client.error_calls, [])
344         self.assertEqual(self.client.success_calls, [])
345
346     def test_stdout_passthrough(self):
347         """Lines received which cannot be interpreted as any protocol action
348         should be passed through to sys.stdout.
349         """
350         bytes = "randombytes\n"
351         self.protocol.lineReceived(bytes)
352         self.assertEqual(self.stdout.getvalue(), bytes)
353
354
355 class TestTestProtocolServerLostConnection(unittest.TestCase):
356
357     def setUp(self):
358         self.client = MockTestProtocolServerClient()
359         self.protocol = subunit.TestProtocolServer(self.client)
360         self.test = subunit.RemotedTestCase("old mcdonald")
361
362     def test_lost_connection_no_input(self):
363         self.protocol.lostConnection()
364         self.assertEqual(self.client.start_calls, [])
365         self.assertEqual(self.client.error_calls, [])
366         self.assertEqual(self.client.failure_calls, [])
367         self.assertEqual(self.client.success_calls, [])
368
369     def test_lost_connection_after_start(self):
370         self.protocol.lineReceived("test old mcdonald\n")
371         self.protocol.lostConnection()
372         self.assertEqual(self.client.start_calls, [self.test])
373         self.assertEqual(self.client.end_calls, [self.test])
374         self.assertEqual(self.client.error_calls, [
375             (self.test, subunit.RemoteError("lost connection during "
376                                             "test 'old mcdonald'"))])
377         self.assertEqual(self.client.failure_calls, [])
378         self.assertEqual(self.client.success_calls, [])
379
380     def test_lost_connected_after_error(self):
381         self.protocol.lineReceived("test old mcdonald\n")
382         self.protocol.lineReceived("error old mcdonald\n")
383         self.protocol.lostConnection()
384         self.assertEqual(self.client.start_calls, [self.test])
385         self.assertEqual(self.client.failure_calls, [])
386         self.assertEqual(self.client.end_calls, [self.test])
387         self.assertEqual(self.client.error_calls, [
388             (self.test, subunit.RemoteError(""))])
389         self.assertEqual(self.client.success_calls, [])
390
391     def do_connection_lost(self, outcome, opening):
392         self.protocol.lineReceived("test old mcdonald\n")
393         self.protocol.lineReceived("%s old mcdonald %s" % (outcome, opening))
394         self.protocol.lostConnection()
395         self.assertEqual(self.client.start_calls, [self.test])
396         self.assertEqual(self.client.end_calls, [self.test])
397         self.assertEqual(self.client.error_calls, [
398             (self.test, subunit.RemoteError("lost connection during %s "
399                 "report of test 'old mcdonald'" % outcome))])
400         self.assertEqual(self.client.failure_calls, [])
401         self.assertEqual(self.client.success_calls, [])
402
403     def test_lost_connection_during_error(self):
404         self.do_connection_lost("error", "[\n")
405
406     def test_lost_connection_during_error_details(self):
407         self.do_connection_lost("error", "[ multipart\n")
408
409     def test_lost_connected_after_failure(self):
410         self.protocol.lineReceived("test old mcdonald\n")
411         self.protocol.lineReceived("failure old mcdonald\n")
412         self.protocol.lostConnection()
413         test = subunit.RemotedTestCase("old mcdonald")
414         self.assertEqual(self.client.start_calls, [self.test])
415         self.assertEqual(self.client.end_calls, [self.test])
416         self.assertEqual(self.client.error_calls, [])
417         self.assertEqual(self.client.failure_calls,
418                          [(self.test, subunit.RemoteError())])
419         self.assertEqual(self.client.success_calls, [])
420
421     def test_lost_connection_during_failure(self):
422         self.do_connection_lost("failure", "[\n")
423
424     def test_lost_connection_during_failure_details(self):
425         self.do_connection_lost("failure", "[ multipart\n")
426
427     def test_lost_connection_after_success(self):
428         self.protocol.lineReceived("test old mcdonald\n")
429         self.protocol.lineReceived("success old mcdonald\n")
430         self.protocol.lostConnection()
431         self.assertEqual(self.client.start_calls, [self.test])
432         self.assertEqual(self.client.end_calls, [self.test])
433         self.assertEqual(self.client.error_calls, [])
434         self.assertEqual(self.client.failure_calls, [])
435         self.assertEqual(self.client.success_calls, [self.test])
436
437     def test_lost_connection_during_success(self):
438         self.do_connection_lost("success", "[\n")
439
440     def test_lost_connection_during_success_details(self):
441         self.do_connection_lost("success", "[ multipart\n")
442
443     def test_lost_connection_during_skip(self):
444         self.do_connection_lost("skip", "[\n")
445
446     def test_lost_connection_during_skip_details(self):
447         self.do_connection_lost("skip", "[ multipart\n")
448
449     def test_lost_connection_during_xfail(self):
450         self.do_connection_lost("xfail", "[\n")
451
452     def test_lost_connection_during_xfail_details(self):
453         self.do_connection_lost("xfail", "[ multipart\n")
454
455
456 class TestInTestMultipart(unittest.TestCase):
457
458     def setUp(self):
459         self.client = MockTestProtocolServerClient()
460         self.protocol = subunit.TestProtocolServer(self.client)
461         self.protocol.lineReceived("test mcdonalds farm\n")
462         self.test = subunit.RemotedTestCase("mcdonalds farm")
463
464     def test__outcome_sets_details_parser(self):
465         self.protocol._reading_success_details.details_parser = None
466         self.protocol._state._outcome(0, "mcdonalds farm [ multipart\n",
467             None, self.protocol._reading_success_details)
468         parser = self.protocol._reading_success_details.details_parser
469         self.assertNotEqual(None, parser)
470         self.assertTrue(isinstance(parser,
471             subunit.details.MultipartDetailsParser))
472
473
474 class TestTestProtocolServerAddError(unittest.TestCase):
475
476     def setUp(self):
477         self.client = MockTestProtocolServerClient()
478         self.protocol = subunit.TestProtocolServer(self.client)
479         self.protocol.lineReceived("test mcdonalds farm\n")
480         self.test = subunit.RemotedTestCase("mcdonalds farm")
481
482     def simple_error_keyword(self, keyword):
483         self.protocol.lineReceived("%s mcdonalds farm\n" % keyword)
484         self.assertEqual(self.client.start_calls, [self.test])
485         self.assertEqual(self.client.end_calls, [self.test])
486         self.assertEqual(self.client.error_calls, [
487             (self.test, subunit.RemoteError(""))])
488         self.assertEqual(self.client.failure_calls, [])
489
490     def test_simple_error(self):
491         self.simple_error_keyword("error")
492
493     def test_simple_error_colon(self):
494         self.simple_error_keyword("error:")
495
496     def test_error_empty_message(self):
497         self.protocol.lineReceived("error mcdonalds farm [\n")
498         self.protocol.lineReceived("]\n")
499         self.assertEqual(self.client.start_calls, [self.test])
500         self.assertEqual(self.client.end_calls, [self.test])
501         self.assertEqual(self.client.error_calls, [
502             (self.test, subunit.RemoteError(""))])
503         self.assertEqual(self.client.failure_calls, [])
504
505     def error_quoted_bracket(self, keyword):
506         self.protocol.lineReceived("%s mcdonalds farm [\n" % keyword)
507         self.protocol.lineReceived(" ]\n")
508         self.protocol.lineReceived("]\n")
509         self.assertEqual(self.client.start_calls, [self.test])
510         self.assertEqual(self.client.end_calls, [self.test])
511         self.assertEqual(self.client.error_calls, [
512             (self.test, subunit.RemoteError("]\n"))])
513         self.assertEqual(self.client.failure_calls, [])
514
515     def test_error_quoted_bracket(self):
516         self.error_quoted_bracket("error")
517
518     def test_error_colon_quoted_bracket(self):
519         self.error_quoted_bracket("error:")
520
521
522 class TestTestProtocolServerAddFailure(unittest.TestCase):
523
524     def setUp(self):
525         self.client = MockTestProtocolServerClient()
526         self.protocol = subunit.TestProtocolServer(self.client)
527         self.protocol.lineReceived("test mcdonalds farm\n")
528         self.test = subunit.RemotedTestCase("mcdonalds farm")
529
530     def simple_failure_keyword(self, keyword):
531         self.protocol.lineReceived("%s mcdonalds farm\n" % keyword)
532         self.assertEqual(self.client.start_calls, [self.test])
533         self.assertEqual(self.client.end_calls, [self.test])
534         self.assertEqual(self.client.error_calls, [])
535         self.assertEqual(self.client.failure_calls,
536                          [(self.test, subunit.RemoteError())])
537
538     def test_simple_failure(self):
539         self.simple_failure_keyword("failure")
540
541     def test_simple_failure_colon(self):
542         self.simple_failure_keyword("failure:")
543
544     def test_failure_empty_message(self):
545         self.protocol.lineReceived("failure mcdonalds farm [\n")
546         self.protocol.lineReceived("]\n")
547         self.assertEqual(self.client.start_calls, [self.test])
548         self.assertEqual(self.client.end_calls, [self.test])
549         self.assertEqual(self.client.error_calls, [])
550         self.assertEqual(self.client.failure_calls,
551                          [(self.test, subunit.RemoteError())])
552
553     def failure_quoted_bracket(self, keyword):
554         self.protocol.lineReceived("%s mcdonalds farm [\n" % keyword)
555         self.protocol.lineReceived(" ]\n")
556         self.protocol.lineReceived("]\n")
557         self.assertEqual(self.client.start_calls, [self.test])
558         self.assertEqual(self.client.end_calls, [self.test])
559         self.assertEqual(self.client.error_calls, [])
560         self.assertEqual(self.client.failure_calls,
561                          [(self.test, subunit.RemoteError("]\n"))])
562
563     def test_failure_quoted_bracket(self):
564         self.failure_quoted_bracket("failure")
565
566     def test_failure_colon_quoted_bracket(self):
567         self.failure_quoted_bracket("failure:")
568
569
570 class TestTestProtocolServerAddxFail(unittest.TestCase):
571     """Tests for the xfail keyword.
572
573     In Python this can thunk through to Success due to stdlib limitations (see
574     README).
575     """
576
577     def capture_expected_failure(self, test, err):
578         self._calls.append((test, err))
579
580     def setup_python26(self):
581         """Setup a test object ready to be xfailed and thunk to success."""
582         self.client = MockTestProtocolServerClient()
583         self.setup_protocol()
584
585     def setup_python27(self):
586         """Setup a test object ready to be xfailed and thunk to success."""
587         self.client = MockTestProtocolServerClient()
588         self.client.addExpectedFailure = self.capture_expected_failure
589         self._calls = []
590         self.setup_protocol()
591
592     def setup_protocol(self):
593         """Setup the protocol based on self.client."""
594         self.protocol = subunit.TestProtocolServer(self.client)
595         self.protocol.lineReceived("test mcdonalds farm\n")
596         self.test = self.client.start_calls[-1]
597
598     def simple_xfail_keyword(self, keyword, as_success):
599         self.protocol.lineReceived("%s mcdonalds farm\n" % keyword)
600         self.assertEqual(self.client.start_calls, [self.test])
601         self.assertEqual(self.client.end_calls, [self.test])
602         self.assertEqual(self.client.error_calls, [])
603         self.assertEqual(self.client.failure_calls, [])
604         self.check_success_or_xfail(as_success)
605
606     def check_success_or_xfail(self, as_success):
607         if as_success:
608             self.assertEqual(self.client.success_calls, [self.test])
609         else:
610             self.assertEqual(1, len(self._calls))
611             self.assertEqual(self.test, self._calls[0][0])
612
613     def test_simple_xfail(self):
614         self.setup_python26()
615         self.simple_xfail_keyword("xfail", True)
616         self.setup_python27()
617         self.simple_xfail_keyword("xfail",  False)
618
619     def test_simple_xfail_colon(self):
620         self.setup_python26()
621         self.simple_xfail_keyword("xfail:", True)
622         self.setup_python27()
623         self.simple_xfail_keyword("xfail:", False)
624
625     def test_xfail_empty_message(self):
626         self.setup_python26()
627         self.empty_message(True)
628         self.setup_python27()
629         self.empty_message(False)
630
631     def empty_message(self, as_success):
632         self.protocol.lineReceived("xfail mcdonalds farm [\n")
633         self.protocol.lineReceived("]\n")
634         self.assertEqual(self.client.start_calls, [self.test])
635         self.assertEqual(self.client.end_calls, [self.test])
636         self.assertEqual(self.client.error_calls, [])
637         self.assertEqual(self.client.failure_calls, [])
638         self.check_success_or_xfail(as_success)
639
640     def xfail_quoted_bracket(self, keyword, as_success):
641         # This tests it is accepted, but cannot test it is used today, because
642         # of not having a way to expose it in Python so far.
643         self.protocol.lineReceived("%s mcdonalds farm [\n" % keyword)
644         self.protocol.lineReceived(" ]\n")
645         self.protocol.lineReceived("]\n")
646         self.assertEqual(self.client.start_calls, [self.test])
647         self.assertEqual(self.client.end_calls, [self.test])
648         self.assertEqual(self.client.error_calls, [])
649         self.assertEqual(self.client.failure_calls, [])
650         self.check_success_or_xfail(as_success)
651
652     def test_xfail_quoted_bracket(self):
653         self.setup_python26()
654         self.xfail_quoted_bracket("xfail", True)
655         self.setup_python27()
656         self.xfail_quoted_bracket("xfail", False)
657
658     def test_xfail_colon_quoted_bracket(self):
659         self.setup_python26()
660         self.xfail_quoted_bracket("xfail:", True)
661         self.setup_python27()
662         self.xfail_quoted_bracket("xfail:", False)
663
664
665 class TestTestProtocolServerAddSkip(unittest.TestCase):
666     """Tests for the skip keyword.
667
668     In Python this meets the testtools extended TestResult contract.
669     (See https://launchpad.net/testtools).
670     """
671
672     def setUp(self):
673         """Setup a test object ready to be skipped."""
674         self.client = MockTestProtocolServerClient()
675         self.protocol = subunit.TestProtocolServer(self.client)
676         self.protocol.lineReceived("test mcdonalds farm\n")
677         self.test = self.client.start_calls[-1]
678
679     def simple_skip_keyword(self, keyword):
680         self.protocol.lineReceived("%s mcdonalds farm\n" % keyword)
681         self.assertEqual(self.client.start_calls, [self.test])
682         self.assertEqual(self.client.end_calls, [self.test])
683         self.assertEqual(self.client.error_calls, [])
684         self.assertEqual(self.client.failure_calls, [])
685         self.assertEqual(self.client.success_calls, [])
686         self.assertEqual(self.client.skip_calls,
687             [(self.test, 'No reason given')])
688
689     def test_simple_skip(self):
690         self.simple_skip_keyword("skip")
691
692     def test_simple_skip_colon(self):
693         self.simple_skip_keyword("skip:")
694
695     def test_skip_empty_message(self):
696         self.protocol.lineReceived("skip mcdonalds farm [\n")
697         self.protocol.lineReceived("]\n")
698         self.assertEqual(self.client.start_calls, [self.test])
699         self.assertEqual(self.client.end_calls, [self.test])
700         self.assertEqual(self.client.error_calls, [])
701         self.assertEqual(self.client.failure_calls, [])
702         self.assertEqual(self.client.success_calls, [])
703         self.assertEqual(self.client.skip_calls,
704             [(self.test, "No reason given")])
705
706     def skip_quoted_bracket(self, keyword):
707         # This tests it is accepted, but cannot test it is used today, because
708         # of not having a way to expose it in Python so far.
709         self.protocol.lineReceived("%s mcdonalds farm [\n" % keyword)
710         self.protocol.lineReceived(" ]\n")
711         self.protocol.lineReceived("]\n")
712         self.assertEqual(self.client.start_calls, [self.test])
713         self.assertEqual(self.client.end_calls, [self.test])
714         self.assertEqual(self.client.error_calls, [])
715         self.assertEqual(self.client.failure_calls, [])
716         self.assertEqual(self.client.success_calls, [])
717         self.assertEqual(self.client.skip_calls,
718             [(self.test, "]\n")])
719
720     def test_skip_quoted_bracket(self):
721         self.skip_quoted_bracket("skip")
722
723     def test_skip_colon_quoted_bracket(self):
724         self.skip_quoted_bracket("skip:")
725
726
727 class TestTestProtocolServerAddSuccess(unittest.TestCase):
728
729     def setUp(self):
730         self.client = MockTestProtocolServerClient()
731         self.protocol = subunit.TestProtocolServer(self.client)
732         self.protocol.lineReceived("test mcdonalds farm\n")
733         self.test = subunit.RemotedTestCase("mcdonalds farm")
734
735     def simple_success_keyword(self, keyword):
736         self.protocol.lineReceived("%s mcdonalds farm\n" % keyword)
737         self.assertEqual(self.client.start_calls, [self.test])
738         self.assertEqual(self.client.end_calls, [self.test])
739         self.assertEqual(self.client.error_calls, [])
740         self.assertEqual(self.client.success_calls, [self.test])
741
742     def test_simple_success(self):
743         self.simple_success_keyword("failure")
744
745     def test_simple_success_colon(self):
746         self.simple_success_keyword("failure:")
747
748     def test_simple_success(self):
749         self.simple_success_keyword("successful")
750
751     def test_simple_success_colon(self):
752         self.simple_success_keyword("successful:")
753
754     def test_success_empty_message(self):
755         self.protocol.lineReceived("success mcdonalds farm [\n")
756         self.protocol.lineReceived("]\n")
757         self.assertEqual(self.client.start_calls, [self.test])
758         self.assertEqual(self.client.end_calls, [self.test])
759         self.assertEqual(self.client.error_calls, [])
760         self.assertEqual(self.client.failure_calls, [])
761         self.assertEqual(self.client.success_calls, [self.test])
762
763     def success_quoted_bracket(self, keyword):
764         # This tests it is accepted, but cannot test it is used today, because
765         # of not having a way to expose it in Python so far.
766         self.protocol.lineReceived("%s mcdonalds farm [\n" % keyword)
767         self.protocol.lineReceived(" ]\n")
768         self.protocol.lineReceived("]\n")
769         self.assertEqual(self.client.start_calls, [self.test])
770         self.assertEqual(self.client.end_calls, [self.test])
771         self.assertEqual(self.client.error_calls, [])
772         self.assertEqual(self.client.failure_calls, [])
773         self.assertEqual(self.client.success_calls, [self.test])
774
775     def test_success_quoted_bracket(self):
776         self.success_quoted_bracket("success")
777
778     def test_success_colon_quoted_bracket(self):
779         self.success_quoted_bracket("success:")
780
781
782 class TestTestProtocolServerProgress(unittest.TestCase):
783     """Test receipt of progress: directives."""
784
785     def test_progress_accepted_stdlib(self):
786         # With a stdlib TestResult, progress events are swallowed.
787         self.result = unittest.TestResult()
788         self.stream = StringIO()
789         self.protocol = subunit.TestProtocolServer(self.result,
790             stream=self.stream)
791         self.protocol.lineReceived("progress: 23")
792         self.protocol.lineReceived("progress: -2")
793         self.protocol.lineReceived("progress: +4")
794         self.assertEqual("", self.stream.getvalue())
795
796     def test_progress_accepted_extended(self):
797         # With a progress capable TestResult, progress events are emitted.
798         self.result = MockTestProtocolServerClient()
799         self.stream = StringIO()
800         self.protocol = subunit.TestProtocolServer(self.result,
801             stream=self.stream)
802         self.protocol.lineReceived("progress: 23")
803         self.protocol.lineReceived("progress: push")
804         self.protocol.lineReceived("progress: -2")
805         self.protocol.lineReceived("progress: pop")
806         self.protocol.lineReceived("progress: +4")
807         self.assertEqual("", self.stream.getvalue())
808         self.assertEqual(
809             [(23, subunit.PROGRESS_SET), (None, subunit.PROGRESS_PUSH),
810              (-2, subunit.PROGRESS_CUR), (None, subunit.PROGRESS_POP),
811              (4, subunit.PROGRESS_CUR)],
812             self.result.progress_calls)
813
814
815 class TestTestProtocolServerStreamTags(unittest.TestCase):
816     """Test managing tags on the protocol level."""
817
818     def setUp(self):
819         self.client = MockExtendedTestProtocolServerClient()
820         self.protocol = subunit.TestProtocolServer(self.client)
821
822     def test_initial_tags(self):
823         self.protocol.lineReceived("tags: foo bar:baz  quux\n")
824         self.assertEqual(set(["foo", "bar:baz", "quux"]),
825             self.client.new_tags)
826         self.assertEqual(set(), self.client.gone_tags)
827
828     def test_minus_removes_tags(self):
829         self.protocol.lineReceived("tags: foo bar\n")
830         self.assertEqual(set(["foo", "bar"]),
831             self.client.new_tags)
832         self.assertEqual(set(), self.client.gone_tags)
833         self.protocol.lineReceived("tags: -bar quux\n")
834         self.assertEqual(set(["quux"]), self.client.new_tags)
835         self.assertEqual(set(["bar"]), self.client.gone_tags)
836
837     def test_tags_do_not_get_set_on_test(self):
838         self.protocol.lineReceived("test mcdonalds farm\n")
839         test = self.client.start_calls[-1]
840         self.assertEqual(None, getattr(test, 'tags', None))
841
842     def test_tags_do_not_get_set_on_global_tags(self):
843         self.protocol.lineReceived("tags: foo bar\n")
844         self.protocol.lineReceived("test mcdonalds farm\n")
845         test = self.client.start_calls[-1]
846         self.assertEqual(None, getattr(test, 'tags', None))
847
848     def test_tags_get_set_on_test_tags(self):
849         self.protocol.lineReceived("test mcdonalds farm\n")
850         test = self.client.start_calls[-1]
851         self.protocol.lineReceived("tags: foo bar\n")
852         self.protocol.lineReceived("success mcdonalds farm\n")
853         self.assertEqual(None, getattr(test, 'tags', None))
854
855
856 class TestTestProtocolServerStreamTime(unittest.TestCase):
857     """Test managing time information at the protocol level."""
858
859     def test_time_accepted_stdlib(self):
860         self.result = unittest.TestResult()
861         self.stream = StringIO()
862         self.protocol = subunit.TestProtocolServer(self.result,
863             stream=self.stream)
864         self.protocol.lineReceived("time: 2001-12-12 12:59:59Z\n")
865         self.assertEqual("", self.stream.getvalue())
866
867     def test_time_accepted_extended(self):
868         self.result = MockTestProtocolServerClient()
869         self.stream = StringIO()
870         self.protocol = subunit.TestProtocolServer(self.result,
871             stream=self.stream)
872         self.protocol.lineReceived("time: 2001-12-12 12:59:59Z\n")
873         self.assertEqual("", self.stream.getvalue())
874         self.assertEqual(datetime.datetime(2001, 12, 12, 12, 59, 59, 0,
875             iso8601.Utc()), self.result._time)
876
877
878 class TestRemotedTestCase(unittest.TestCase):
879
880     def test_simple(self):
881         test = subunit.RemotedTestCase("A test description")
882         self.assertRaises(NotImplementedError, test.setUp)
883         self.assertRaises(NotImplementedError, test.tearDown)
884         self.assertEqual("A test description",
885                          test.shortDescription())
886         self.assertEqual("A test description",
887                          test.id())
888         self.assertEqual("A test description (subunit.RemotedTestCase)", "%s" % test)
889         self.assertEqual("<subunit.RemotedTestCase description="
890                          "'A test description'>", "%r" % test)
891         result = unittest.TestResult()
892         test.run(result)
893         self.assertEqual([(test, "RemoteException: "
894                                  "Cannot run RemotedTestCases.\n\n")],
895                          result.errors)
896         self.assertEqual(1, result.testsRun)
897         another_test = subunit.RemotedTestCase("A test description")
898         self.assertEqual(test, another_test)
899         different_test = subunit.RemotedTestCase("ofo")
900         self.assertNotEqual(test, different_test)
901         self.assertNotEqual(another_test, different_test)
902
903
904 class TestRemoteError(unittest.TestCase):
905
906     def test_eq(self):
907         error = subunit.RemoteError("Something went wrong")
908         another_error = subunit.RemoteError("Something went wrong")
909         different_error = subunit.RemoteError("boo!")
910         self.assertEqual(error, another_error)
911         self.assertNotEqual(error, different_error)
912         self.assertNotEqual(different_error, another_error)
913
914     def test_empty_constructor(self):
915         self.assertEqual(subunit.RemoteError(), subunit.RemoteError(""))
916
917
918 class TestExecTestCase(unittest.TestCase):
919
920     class SampleExecTestCase(subunit.ExecTestCase):
921
922         def test_sample_method(self):
923             """sample-script.py"""
924             # the sample script runs three tests, one each
925             # that fails, errors and succeeds
926
927         def test_sample_method_args(self):
928             """sample-script.py foo"""
929             # sample that will run just one test.
930
931     def test_construct(self):
932         test = self.SampleExecTestCase("test_sample_method")
933         self.assertEqual(test.script,
934                          subunit.join_dir(__file__, 'sample-script.py'))
935
936     def test_args(self):
937         result = unittest.TestResult()
938         test = self.SampleExecTestCase("test_sample_method_args")
939         test.run(result)
940         self.assertEqual(1, result.testsRun)
941
942     def test_run(self):
943         runner = MockTestProtocolServerClient()
944         test = self.SampleExecTestCase("test_sample_method")
945         test.run(runner)
946         mcdonald = subunit.RemotedTestCase("old mcdonald")
947         bing = subunit.RemotedTestCase("bing crosby")
948         an_error = subunit.RemotedTestCase("an error")
949         self.assertEqual(runner.error_calls,
950                          [(an_error, subunit.RemoteError())])
951         self.assertEqual(runner.failure_calls,
952                          [(bing,
953                            subunit.RemoteError(
954                             "foo.c:53:ERROR invalid state\n"))])
955         self.assertEqual(runner.start_calls, [mcdonald, bing, an_error])
956         self.assertEqual(runner.end_calls, [mcdonald, bing, an_error])
957
958     def test_debug(self):
959         test = self.SampleExecTestCase("test_sample_method")
960         test.debug()
961
962     def test_count_test_cases(self):
963         """TODO run the child process and count responses to determine the count."""
964
965     def test_join_dir(self):
966         sibling = subunit.join_dir(__file__, 'foo')
967         expected = '%s/foo' % (os.path.split(__file__)[0],)
968         self.assertEqual(sibling, expected)
969
970
971 class DoExecTestCase(subunit.ExecTestCase):
972
973     def test_working_script(self):
974         """sample-two-script.py"""
975
976
977 class TestIsolatedTestCase(unittest.TestCase):
978
979     class SampleIsolatedTestCase(subunit.IsolatedTestCase):
980
981         SETUP = False
982         TEARDOWN = False
983         TEST = False
984
985         def setUp(self):
986             TestIsolatedTestCase.SampleIsolatedTestCase.SETUP = True
987
988         def tearDown(self):
989             TestIsolatedTestCase.SampleIsolatedTestCase.TEARDOWN = True
990
991         def test_sets_global_state(self):
992             TestIsolatedTestCase.SampleIsolatedTestCase.TEST = True
993
994
995     def test_construct(self):
996         test = self.SampleIsolatedTestCase("test_sets_global_state")
997
998     def test_run(self):
999         result = unittest.TestResult()
1000         test = self.SampleIsolatedTestCase("test_sets_global_state")
1001         test.run(result)
1002         self.assertEqual(result.testsRun, 1)
1003         self.assertEqual(self.SampleIsolatedTestCase.SETUP, False)
1004         self.assertEqual(self.SampleIsolatedTestCase.TEARDOWN, False)
1005         self.assertEqual(self.SampleIsolatedTestCase.TEST, False)
1006
1007     def test_debug(self):
1008         pass
1009         #test = self.SampleExecTestCase("test_sample_method")
1010         #test.debug()
1011
1012
1013 class TestIsolatedTestSuite(unittest.TestCase):
1014
1015     class SampleTestToIsolate(unittest.TestCase):
1016
1017         SETUP = False
1018         TEARDOWN = False
1019         TEST = False
1020
1021         def setUp(self):
1022             TestIsolatedTestSuite.SampleTestToIsolate.SETUP = True
1023
1024         def tearDown(self):
1025             TestIsolatedTestSuite.SampleTestToIsolate.TEARDOWN = True
1026
1027         def test_sets_global_state(self):
1028             TestIsolatedTestSuite.SampleTestToIsolate.TEST = True
1029
1030
1031     def test_construct(self):
1032         suite = subunit.IsolatedTestSuite()
1033
1034     def test_run(self):
1035         result = unittest.TestResult()
1036         suite = subunit.IsolatedTestSuite()
1037         sub_suite = unittest.TestSuite()
1038         sub_suite.addTest(self.SampleTestToIsolate("test_sets_global_state"))
1039         sub_suite.addTest(self.SampleTestToIsolate("test_sets_global_state"))
1040         suite.addTest(sub_suite)
1041         suite.addTest(self.SampleTestToIsolate("test_sets_global_state"))
1042         suite.run(result)
1043         self.assertEqual(result.testsRun, 3)
1044         self.assertEqual(self.SampleTestToIsolate.SETUP, False)
1045         self.assertEqual(self.SampleTestToIsolate.TEARDOWN, False)
1046         self.assertEqual(self.SampleTestToIsolate.TEST, False)
1047
1048
1049 class TestTestProtocolClient(unittest.TestCase):
1050
1051     def setUp(self):
1052         self.io = StringIO()
1053         self.protocol = subunit.TestProtocolClient(self.io)
1054         self.test = TestTestProtocolClient("test_start_test")
1055         self.sample_details = {'something':Content(
1056             ContentType('text', 'plain'), lambda:['serialised\nform'])}
1057         self.sample_tb_details = dict(self.sample_details)
1058         self.sample_tb_details['traceback'] = TracebackContent(
1059             subunit.RemoteError("boo qux"))
1060
1061     def test_start_test(self):
1062         """Test startTest on a TestProtocolClient."""
1063         self.protocol.startTest(self.test)
1064         self.assertEqual(self.io.getvalue(), "test: %s\n" % self.test.id())
1065
1066     def test_stop_test(self):
1067         # stopTest doesn't output anything.
1068         self.protocol.stopTest(self.test)
1069         self.assertEqual(self.io.getvalue(), "")
1070
1071     def test_add_success(self):
1072         """Test addSuccess on a TestProtocolClient."""
1073         self.protocol.addSuccess(self.test)
1074         self.assertEqual(
1075             self.io.getvalue(), "successful: %s\n" % self.test.id())
1076
1077     def test_add_success_details(self):
1078         """Test addSuccess on a TestProtocolClient with details."""
1079         self.protocol.addSuccess(self.test, details=self.sample_details)
1080         self.assertEqual(
1081             self.io.getvalue(), "successful: %s [ multipart\n"
1082                 "Content-Type: text/plain\n"
1083                 "something\n"
1084                 "F\r\nserialised\nform0\r\n]\n" % self.test.id())
1085
1086     def test_add_failure(self):
1087         """Test addFailure on a TestProtocolClient."""
1088         self.protocol.addFailure(
1089             self.test, subunit.RemoteError("boo qux"))
1090         self.assertEqual(
1091             self.io.getvalue(),
1092             'failure: %s [\nRemoteException: boo qux\n]\n' % self.test.id())
1093
1094     def test_add_failure_details(self):
1095         """Test addFailure on a TestProtocolClient with details."""
1096         self.protocol.addFailure(
1097             self.test, details=self.sample_tb_details)
1098         self.assertEqual(
1099             self.io.getvalue(),
1100             "failure: %s [ multipart\n"
1101             "Content-Type: text/plain\n"
1102             "something\n"
1103             "F\r\nserialised\nform0\r\n"
1104             "Content-Type: text/x-traceback;language=python\n"
1105             "traceback\n"
1106             "19\r\nRemoteException: boo qux\n0\r\n"
1107             "]\n" % self.test.id())
1108
1109     def test_add_error(self):
1110         """Test stopTest on a TestProtocolClient."""
1111         self.protocol.addError(
1112             self.test, subunit.RemoteError("phwoar crikey"))
1113         self.assertEqual(
1114             self.io.getvalue(),
1115             'error: %s [\n'
1116             "RemoteException: phwoar crikey\n"
1117             "]\n" % self.test.id())
1118
1119     def test_add_error_details(self):
1120         """Test stopTest on a TestProtocolClient with details."""
1121         self.protocol.addError(
1122             self.test, details=self.sample_tb_details)
1123         self.assertEqual(
1124             self.io.getvalue(),
1125             "error: %s [ multipart\n"
1126             "Content-Type: text/plain\n"
1127             "something\n"
1128             "F\r\nserialised\nform0\r\n"
1129             "Content-Type: text/x-traceback;language=python\n"
1130             "traceback\n"
1131             "19\r\nRemoteException: boo qux\n0\r\n"
1132             "]\n" % self.test.id())
1133
1134     def test_add_expected_failure(self):
1135         """Test addExpectedFailure on a TestProtocolClient."""
1136         self.protocol.addExpectedFailure(
1137             self.test, subunit.RemoteError("phwoar crikey"))
1138         self.assertEqual(
1139             self.io.getvalue(),
1140             'xfail: %s [\n'
1141             "RemoteException: phwoar crikey\n"
1142             "]\n" % self.test.id())
1143
1144     def test_add_expected_failure_details(self):
1145         """Test addExpectedFailure on a TestProtocolClient with details."""
1146         self.protocol.addExpectedFailure(
1147             self.test, details=self.sample_tb_details)
1148         self.assertEqual(
1149             self.io.getvalue(),
1150             "xfail: %s [ multipart\n"
1151             "Content-Type: text/plain\n"
1152             "something\n"
1153             "F\r\nserialised\nform0\r\n"
1154             "Content-Type: text/x-traceback;language=python\n"
1155             "traceback\n"
1156             "19\r\nRemoteException: boo qux\n0\r\n"
1157             "]\n" % self.test.id())
1158
1159     def test_add_skip(self):
1160         """Test addSkip on a TestProtocolClient."""
1161         self.protocol.addSkip(
1162             self.test, "Has it really?")
1163         self.assertEqual(
1164             self.io.getvalue(),
1165             'skip: %s [\nHas it really?\n]\n' % self.test.id())
1166     
1167     def test_add_skip_details(self):
1168         """Test addSkip on a TestProtocolClient with details."""
1169         details = {'reason':Content(
1170             ContentType('text', 'plain'), lambda:['Has it really?'])}
1171         self.protocol.addSkip(
1172             self.test, details=details)
1173         self.assertEqual(
1174             self.io.getvalue(),
1175             "skip: %s [ multipart\n"
1176             "Content-Type: text/plain\n"
1177             "reason\n"
1178             "E\r\nHas it really?0\r\n"
1179             "]\n" % self.test.id())
1180
1181     def test_progress_set(self):
1182         self.protocol.progress(23, subunit.PROGRESS_SET)
1183         self.assertEqual(self.io.getvalue(), 'progress: 23\n')
1184
1185     def test_progress_neg_cur(self):
1186         self.protocol.progress(-23, subunit.PROGRESS_CUR)
1187         self.assertEqual(self.io.getvalue(), 'progress: -23\n')
1188
1189     def test_progress_pos_cur(self):
1190         self.protocol.progress(23, subunit.PROGRESS_CUR)
1191         self.assertEqual(self.io.getvalue(), 'progress: +23\n')
1192
1193     def test_progress_pop(self):
1194         self.protocol.progress(1234, subunit.PROGRESS_POP)
1195         self.assertEqual(self.io.getvalue(), 'progress: pop\n')
1196
1197     def test_progress_push(self):
1198         self.protocol.progress(1234, subunit.PROGRESS_PUSH)
1199         self.assertEqual(self.io.getvalue(), 'progress: push\n')
1200
1201     def test_time(self):
1202         # Calling time() outputs a time signal immediately.
1203         self.protocol.time(
1204             datetime.datetime(2009,10,11,12,13,14,15, iso8601.Utc()))
1205         self.assertEqual(
1206             "time: 2009-10-11 12:13:14.000015Z\n",
1207             self.io.getvalue())
1208
1209     def test_add_unexpected_success(self):
1210         """Test addUnexpectedSuccess on a TestProtocolClient."""
1211         self.protocol.addUnexpectedSuccess(self.test)
1212         self.assertEqual(
1213             self.io.getvalue(), "successful: %s\n" % self.test.id())
1214
1215     def test_add_unexpected_success_details(self):
1216         """Test addUnexpectedSuccess on a TestProtocolClient with details."""
1217         self.protocol.addUnexpectedSuccess(self.test, details=self.sample_details)
1218         self.assertEqual(
1219             self.io.getvalue(), "successful: %s [ multipart\n"
1220                 "Content-Type: text/plain\n"
1221                 "something\n"
1222                 "F\r\nserialised\nform0\r\n]\n" % self.test.id())
1223
1224
1225 def test_suite():
1226     loader = subunit.tests.TestUtil.TestLoader()
1227     result = loader.loadTestsFromName(__name__)
1228     return result