2 # subunit: extensions to Python unittest to get test results from subprocesses.
3 # Copyright (C) 2005 Robert Collins <robertc@robertcollins.net>
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.
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.
19 from StringIO import StringIO
23 from testtools.content import Content, TracebackContent
24 from testtools.content_type import ContentType
25 from testtools.tests.helpers import (
32 from subunit import _remote_exception_str
33 import subunit.iso8601 as iso8601
36 class TestTestImports(unittest.TestCase):
38 def test_imports(self):
39 from subunit import DiscardStream
40 from subunit import TestProtocolServer
41 from subunit import RemotedTestCase
42 from subunit import RemoteError
43 from subunit import ExecTestCase
44 from subunit import IsolatedTestCase
45 from subunit import TestProtocolClient
46 from subunit import ProtocolTestCase
49 class TestDiscardStream(unittest.TestCase):
52 subunit.DiscardStream().write("content")
55 class TestProtocolServerForward(unittest.TestCase):
58 client = unittest.TestResult()
60 protocol = subunit.TestProtocolServer(client, forward_stream=out)
61 pipe = StringIO("test old mcdonald\n"
62 "success old mcdonald\n")
63 protocol.readFrom(pipe)
64 mcdonald = subunit.RemotedTestCase("old mcdonald")
65 self.assertEqual(client.testsRun, 1)
66 self.assertEqual(pipe.getvalue(), out.getvalue())
68 def test_not_command(self):
69 client = unittest.TestResult()
71 protocol = subunit.TestProtocolServer(client,
72 stream=subunit.DiscardStream(), forward_stream=out)
73 pipe = StringIO("success old mcdonald\n")
74 protocol.readFrom(pipe)
75 self.assertEqual(client.testsRun, 0)
76 self.assertEqual("", out.getvalue())
79 class TestTestProtocolServerPipe(unittest.TestCase):
82 client = unittest.TestResult()
83 protocol = subunit.TestProtocolServer(client)
84 pipe = StringIO("test old mcdonald\n"
85 "success old mcdonald\n"
87 "failure bing crosby [\n"
88 "foo.c:53:ERROR invalid state\n"
92 protocol.readFrom(pipe)
93 mcdonald = subunit.RemotedTestCase("old mcdonald")
94 bing = subunit.RemotedTestCase("bing crosby")
95 an_error = subunit.RemotedTestCase("an error")
96 self.assertEqual(client.errors,
97 [(an_error, _remote_exception_str + '\n')])
100 [(bing, _remote_exception_str + ": Text attachment: traceback\n"
101 "------------\nfoo.c:53:ERROR invalid state\n"
102 "------------\n\n")])
103 self.assertEqual(client.testsRun, 3)
105 def test_non_test_characters_forwarded_immediately(self):
109 class TestTestProtocolServerStartTest(unittest.TestCase):
112 self.client = Python26TestResult()
113 self.protocol = subunit.TestProtocolServer(self.client)
115 def test_start_test(self):
116 self.protocol.lineReceived("test old mcdonald\n")
117 self.assertEqual(self.client._events,
118 [('startTest', subunit.RemotedTestCase("old mcdonald"))])
120 def test_start_testing(self):
121 self.protocol.lineReceived("testing old mcdonald\n")
122 self.assertEqual(self.client._events,
123 [('startTest', subunit.RemotedTestCase("old mcdonald"))])
125 def test_start_test_colon(self):
126 self.protocol.lineReceived("test: old mcdonald\n")
127 self.assertEqual(self.client._events,
128 [('startTest', subunit.RemotedTestCase("old mcdonald"))])
130 def test_indented_test_colon_ignored(self):
131 self.protocol.lineReceived(" test: old mcdonald\n")
132 self.assertEqual([], self.client._events)
134 def test_start_testing_colon(self):
135 self.protocol.lineReceived("testing: old mcdonald\n")
136 self.assertEqual(self.client._events,
137 [('startTest', subunit.RemotedTestCase("old mcdonald"))])
140 class TestTestProtocolServerPassThrough(unittest.TestCase):
143 self.stdout = StringIO()
144 self.test = subunit.RemotedTestCase("old mcdonald")
145 self.client = ExtendedTestResult()
146 self.protocol = subunit.TestProtocolServer(self.client, self.stdout)
148 def keywords_before_test(self):
149 self.protocol.lineReceived("failure a\n")
150 self.protocol.lineReceived("failure: a\n")
151 self.protocol.lineReceived("error a\n")
152 self.protocol.lineReceived("error: a\n")
153 self.protocol.lineReceived("success a\n")
154 self.protocol.lineReceived("success: a\n")
155 self.protocol.lineReceived("successful a\n")
156 self.protocol.lineReceived("successful: a\n")
157 self.protocol.lineReceived("]\n")
158 self.assertEqual(self.stdout.getvalue(), "failure a\n"
168 def test_keywords_before_test(self):
169 self.keywords_before_test()
170 self.assertEqual(self.client._events, [])
172 def test_keywords_after_error(self):
173 self.protocol.lineReceived("test old mcdonald\n")
174 self.protocol.lineReceived("error old mcdonald\n")
175 self.keywords_before_test()
177 ('startTest', self.test),
178 ('addError', self.test, {}),
179 ('stopTest', self.test),
180 ], self.client._events)
182 def test_keywords_after_failure(self):
183 self.protocol.lineReceived("test old mcdonald\n")
184 self.protocol.lineReceived("failure old mcdonald\n")
185 self.keywords_before_test()
186 self.assertEqual(self.client._events, [
187 ('startTest', self.test),
188 ('addFailure', self.test, {}),
189 ('stopTest', self.test),
192 def test_keywords_after_success(self):
193 self.protocol.lineReceived("test old mcdonald\n")
194 self.protocol.lineReceived("success old mcdonald\n")
195 self.keywords_before_test()
197 ('startTest', self.test),
198 ('addSuccess', self.test),
199 ('stopTest', self.test),
200 ], self.client._events)
202 def test_keywords_after_test(self):
203 self.protocol.lineReceived("test old mcdonald\n")
204 self.protocol.lineReceived("test old mcdonald\n")
205 self.protocol.lineReceived("failure a\n")
206 self.protocol.lineReceived("failure: a\n")
207 self.protocol.lineReceived("error a\n")
208 self.protocol.lineReceived("error: a\n")
209 self.protocol.lineReceived("success a\n")
210 self.protocol.lineReceived("success: a\n")
211 self.protocol.lineReceived("successful a\n")
212 self.protocol.lineReceived("successful: a\n")
213 self.protocol.lineReceived("]\n")
214 self.protocol.lineReceived("failure old mcdonald\n")
215 self.assertEqual(self.stdout.getvalue(), "test old mcdonald\n"
225 self.assertEqual(self.client._events, [
226 ('startTest', self.test),
227 ('addFailure', self.test, {}),
228 ('stopTest', self.test),
231 def test_keywords_during_failure(self):
232 # A smoke test to make sure that the details parsers have control
234 self.protocol.lineReceived("test old mcdonald\n")
235 self.protocol.lineReceived("failure: old mcdonald [\n")
236 self.protocol.lineReceived("test old mcdonald\n")
237 self.protocol.lineReceived("failure a\n")
238 self.protocol.lineReceived("failure: a\n")
239 self.protocol.lineReceived("error a\n")
240 self.protocol.lineReceived("error: a\n")
241 self.protocol.lineReceived("success a\n")
242 self.protocol.lineReceived("success: a\n")
243 self.protocol.lineReceived("successful a\n")
244 self.protocol.lineReceived("successful: a\n")
245 self.protocol.lineReceived(" ]\n")
246 self.protocol.lineReceived("]\n")
247 self.assertEqual(self.stdout.getvalue(), "")
249 details['traceback'] = Content(ContentType("text", "x-traceback",
250 {'charset': 'utf8'}),
252 "test old mcdonald\n"
262 self.assertEqual(self.client._events, [
263 ('startTest', self.test),
264 ('addFailure', self.test, details),
265 ('stopTest', self.test),
268 def test_stdout_passthrough(self):
269 """Lines received which cannot be interpreted as any protocol action
270 should be passed through to sys.stdout.
272 bytes = "randombytes\n"
273 self.protocol.lineReceived(bytes)
274 self.assertEqual(self.stdout.getvalue(), bytes)
277 class TestTestProtocolServerLostConnection(unittest.TestCase):
280 self.client = Python26TestResult()
281 self.protocol = subunit.TestProtocolServer(self.client)
282 self.test = subunit.RemotedTestCase("old mcdonald")
284 def test_lost_connection_no_input(self):
285 self.protocol.lostConnection()
286 self.assertEqual([], self.client._events)
288 def test_lost_connection_after_start(self):
289 self.protocol.lineReceived("test old mcdonald\n")
290 self.protocol.lostConnection()
291 failure = subunit.RemoteError(
292 u"lost connection during test 'old mcdonald'")
294 ('startTest', self.test),
295 ('addError', self.test, failure),
296 ('stopTest', self.test),
297 ], self.client._events)
299 def test_lost_connected_after_error(self):
300 self.protocol.lineReceived("test old mcdonald\n")
301 self.protocol.lineReceived("error old mcdonald\n")
302 self.protocol.lostConnection()
304 ('startTest', self.test),
305 ('addError', self.test, subunit.RemoteError(u"")),
306 ('stopTest', self.test),
307 ], self.client._events)
309 def do_connection_lost(self, outcome, opening):
310 self.protocol.lineReceived("test old mcdonald\n")
311 self.protocol.lineReceived("%s old mcdonald %s" % (outcome, opening))
312 self.protocol.lostConnection()
313 failure = subunit.RemoteError(
314 u"lost connection during %s report of test 'old mcdonald'" %
317 ('startTest', self.test),
318 ('addError', self.test, failure),
319 ('stopTest', self.test),
320 ], self.client._events)
322 def test_lost_connection_during_error(self):
323 self.do_connection_lost("error", "[\n")
325 def test_lost_connection_during_error_details(self):
326 self.do_connection_lost("error", "[ multipart\n")
328 def test_lost_connected_after_failure(self):
329 self.protocol.lineReceived("test old mcdonald\n")
330 self.protocol.lineReceived("failure old mcdonald\n")
331 self.protocol.lostConnection()
333 ('startTest', self.test),
334 ('addFailure', self.test, subunit.RemoteError(u"")),
335 ('stopTest', self.test),
336 ], self.client._events)
338 def test_lost_connection_during_failure(self):
339 self.do_connection_lost("failure", "[\n")
341 def test_lost_connection_during_failure_details(self):
342 self.do_connection_lost("failure", "[ multipart\n")
344 def test_lost_connection_after_success(self):
345 self.protocol.lineReceived("test old mcdonald\n")
346 self.protocol.lineReceived("success old mcdonald\n")
347 self.protocol.lostConnection()
349 ('startTest', self.test),
350 ('addSuccess', self.test),
351 ('stopTest', self.test),
352 ], self.client._events)
354 def test_lost_connection_during_success(self):
355 self.do_connection_lost("success", "[\n")
357 def test_lost_connection_during_success_details(self):
358 self.do_connection_lost("success", "[ multipart\n")
360 def test_lost_connection_during_skip(self):
361 self.do_connection_lost("skip", "[\n")
363 def test_lost_connection_during_skip_details(self):
364 self.do_connection_lost("skip", "[ multipart\n")
366 def test_lost_connection_during_xfail(self):
367 self.do_connection_lost("xfail", "[\n")
369 def test_lost_connection_during_xfail_details(self):
370 self.do_connection_lost("xfail", "[ multipart\n")
373 class TestInTestMultipart(unittest.TestCase):
376 self.client = ExtendedTestResult()
377 self.protocol = subunit.TestProtocolServer(self.client)
378 self.protocol.lineReceived("test mcdonalds farm\n")
379 self.test = subunit.RemotedTestCase("mcdonalds farm")
381 def test__outcome_sets_details_parser(self):
382 self.protocol._reading_success_details.details_parser = None
383 self.protocol._state._outcome(0, "mcdonalds farm [ multipart\n",
384 None, self.protocol._reading_success_details)
385 parser = self.protocol._reading_success_details.details_parser
386 self.assertNotEqual(None, parser)
387 self.assertTrue(isinstance(parser,
388 subunit.details.MultipartDetailsParser))
391 class TestTestProtocolServerAddError(unittest.TestCase):
394 self.client = ExtendedTestResult()
395 self.protocol = subunit.TestProtocolServer(self.client)
396 self.protocol.lineReceived("test mcdonalds farm\n")
397 self.test = subunit.RemotedTestCase("mcdonalds farm")
399 def simple_error_keyword(self, keyword):
400 self.protocol.lineReceived("%s mcdonalds farm\n" % keyword)
403 ('startTest', self.test),
404 ('addError', self.test, details),
405 ('stopTest', self.test),
406 ], self.client._events)
408 def test_simple_error(self):
409 self.simple_error_keyword("error")
411 def test_simple_error_colon(self):
412 self.simple_error_keyword("error:")
414 def test_error_empty_message(self):
415 self.protocol.lineReceived("error mcdonalds farm [\n")
416 self.protocol.lineReceived("]\n")
418 details['traceback'] = Content(ContentType("text", "x-traceback",
419 {'charset': 'utf8'}), lambda:[""])
421 ('startTest', self.test),
422 ('addError', self.test, details),
423 ('stopTest', self.test),
424 ], self.client._events)
426 def error_quoted_bracket(self, keyword):
427 self.protocol.lineReceived("%s mcdonalds farm [\n" % keyword)
428 self.protocol.lineReceived(" ]\n")
429 self.protocol.lineReceived("]\n")
431 details['traceback'] = Content(ContentType("text", "x-traceback",
432 {'charset': 'utf8'}), lambda:["]\n"])
434 ('startTest', self.test),
435 ('addError', self.test, details),
436 ('stopTest', self.test),
437 ], self.client._events)
439 def test_error_quoted_bracket(self):
440 self.error_quoted_bracket("error")
442 def test_error_colon_quoted_bracket(self):
443 self.error_quoted_bracket("error:")
446 class TestTestProtocolServerAddFailure(unittest.TestCase):
449 self.client = ExtendedTestResult()
450 self.protocol = subunit.TestProtocolServer(self.client)
451 self.protocol.lineReceived("test mcdonalds farm\n")
452 self.test = subunit.RemotedTestCase("mcdonalds farm")
454 def assertFailure(self, details):
456 ('startTest', self.test),
457 ('addFailure', self.test, details),
458 ('stopTest', self.test),
459 ], self.client._events)
461 def simple_failure_keyword(self, keyword):
462 self.protocol.lineReceived("%s mcdonalds farm\n" % keyword)
464 self.assertFailure(details)
466 def test_simple_failure(self):
467 self.simple_failure_keyword("failure")
469 def test_simple_failure_colon(self):
470 self.simple_failure_keyword("failure:")
472 def test_failure_empty_message(self):
473 self.protocol.lineReceived("failure mcdonalds farm [\n")
474 self.protocol.lineReceived("]\n")
476 details['traceback'] = Content(ContentType("text", "x-traceback",
477 {'charset': 'utf8'}), lambda:[""])
478 self.assertFailure(details)
480 def failure_quoted_bracket(self, keyword):
481 self.protocol.lineReceived("%s mcdonalds farm [\n" % keyword)
482 self.protocol.lineReceived(" ]\n")
483 self.protocol.lineReceived("]\n")
485 details['traceback'] = Content(ContentType("text", "x-traceback",
486 {'charset': 'utf8'}), lambda:["]\n"])
487 self.assertFailure(details)
489 def test_failure_quoted_bracket(self):
490 self.failure_quoted_bracket("failure")
492 def test_failure_colon_quoted_bracket(self):
493 self.failure_quoted_bracket("failure:")
496 class TestTestProtocolServerAddxFail(unittest.TestCase):
497 """Tests for the xfail keyword.
499 In Python this can thunk through to Success due to stdlib limitations (see
503 def capture_expected_failure(self, test, err):
504 self._events.append((test, err))
506 def setup_python26(self):
507 """Setup a test object ready to be xfailed and thunk to success."""
508 self.client = Python26TestResult()
509 self.setup_protocol()
511 def setup_python27(self):
512 """Setup a test object ready to be xfailed."""
513 self.client = Python27TestResult()
514 self.setup_protocol()
516 def setup_python_ex(self):
517 """Setup a test object ready to be xfailed with details."""
518 self.client = ExtendedTestResult()
519 self.setup_protocol()
521 def setup_protocol(self):
522 """Setup the protocol based on self.client."""
523 self.protocol = subunit.TestProtocolServer(self.client)
524 self.protocol.lineReceived("test mcdonalds farm\n")
525 self.test = self.client._events[-1][-1]
527 def simple_xfail_keyword(self, keyword, as_success):
528 self.protocol.lineReceived("%s mcdonalds farm\n" % keyword)
529 self.check_success_or_xfail(as_success)
531 def check_success_or_xfail(self, as_success, error_message=None):
534 ('startTest', self.test),
535 ('addSuccess', self.test),
536 ('stopTest', self.test),
537 ], self.client._events)
540 if error_message is not None:
541 details['traceback'] = Content(
542 ContentType("text", "x-traceback", {'charset': 'utf8'}),
543 lambda:[error_message])
544 if isinstance(self.client, ExtendedTestResult):
547 if error_message is not None:
548 value = subunit.RemoteError(u'Text attachment: traceback\n'
549 '------------\n' + error_message + '------------\n')
551 value = subunit.RemoteError()
553 ('startTest', self.test),
554 ('addExpectedFailure', self.test, value),
555 ('stopTest', self.test),
556 ], self.client._events)
558 def test_simple_xfail(self):
559 self.setup_python26()
560 self.simple_xfail_keyword("xfail", True)
561 self.setup_python27()
562 self.simple_xfail_keyword("xfail", False)
563 self.setup_python_ex()
564 self.simple_xfail_keyword("xfail", False)
566 def test_simple_xfail_colon(self):
567 self.setup_python26()
568 self.simple_xfail_keyword("xfail:", True)
569 self.setup_python27()
570 self.simple_xfail_keyword("xfail:", False)
571 self.setup_python_ex()
572 self.simple_xfail_keyword("xfail:", False)
574 def test_xfail_empty_message(self):
575 self.setup_python26()
576 self.empty_message(True)
577 self.setup_python27()
578 self.empty_message(False)
579 self.setup_python_ex()
580 self.empty_message(False, error_message="")
582 def empty_message(self, as_success, error_message="\n"):
583 self.protocol.lineReceived("xfail mcdonalds farm [\n")
584 self.protocol.lineReceived("]\n")
585 self.check_success_or_xfail(as_success, error_message)
587 def xfail_quoted_bracket(self, keyword, as_success):
588 # This tests it is accepted, but cannot test it is used today, because
589 # of not having a way to expose it in Python so far.
590 self.protocol.lineReceived("%s mcdonalds farm [\n" % keyword)
591 self.protocol.lineReceived(" ]\n")
592 self.protocol.lineReceived("]\n")
593 self.check_success_or_xfail(as_success, "]\n")
595 def test_xfail_quoted_bracket(self):
596 self.setup_python26()
597 self.xfail_quoted_bracket("xfail", True)
598 self.setup_python27()
599 self.xfail_quoted_bracket("xfail", False)
600 self.setup_python_ex()
601 self.xfail_quoted_bracket("xfail", False)
603 def test_xfail_colon_quoted_bracket(self):
604 self.setup_python26()
605 self.xfail_quoted_bracket("xfail:", True)
606 self.setup_python27()
607 self.xfail_quoted_bracket("xfail:", False)
608 self.setup_python_ex()
609 self.xfail_quoted_bracket("xfail:", False)
612 class TestTestProtocolServerAddSkip(unittest.TestCase):
613 """Tests for the skip keyword.
615 In Python this meets the testtools extended TestResult contract.
616 (See https://launchpad.net/testtools).
620 """Setup a test object ready to be skipped."""
621 self.client = ExtendedTestResult()
622 self.protocol = subunit.TestProtocolServer(self.client)
623 self.protocol.lineReceived("test mcdonalds farm\n")
624 self.test = self.client._events[-1][-1]
626 def assertSkip(self, reason):
628 if reason is not None:
629 details['reason'] = Content(
630 ContentType("text", "plain"), lambda:[reason])
632 ('startTest', self.test),
633 ('addSkip', self.test, details),
634 ('stopTest', self.test),
635 ], self.client._events)
637 def simple_skip_keyword(self, keyword):
638 self.protocol.lineReceived("%s mcdonalds farm\n" % keyword)
639 self.assertSkip(None)
641 def test_simple_skip(self):
642 self.simple_skip_keyword("skip")
644 def test_simple_skip_colon(self):
645 self.simple_skip_keyword("skip:")
647 def test_skip_empty_message(self):
648 self.protocol.lineReceived("skip mcdonalds farm [\n")
649 self.protocol.lineReceived("]\n")
652 def skip_quoted_bracket(self, keyword):
653 # This tests it is accepted, but cannot test it is used today, because
654 # of not having a way to expose it in Python so far.
655 self.protocol.lineReceived("%s mcdonalds farm [\n" % keyword)
656 self.protocol.lineReceived(" ]\n")
657 self.protocol.lineReceived("]\n")
658 self.assertSkip("]\n")
660 def test_skip_quoted_bracket(self):
661 self.skip_quoted_bracket("skip")
663 def test_skip_colon_quoted_bracket(self):
664 self.skip_quoted_bracket("skip:")
667 class TestTestProtocolServerAddSuccess(unittest.TestCase):
670 self.client = ExtendedTestResult()
671 self.protocol = subunit.TestProtocolServer(self.client)
672 self.protocol.lineReceived("test mcdonalds farm\n")
673 self.test = subunit.RemotedTestCase("mcdonalds farm")
675 def simple_success_keyword(self, keyword):
676 self.protocol.lineReceived("%s mcdonalds farm\n" % keyword)
678 ('startTest', self.test),
679 ('addSuccess', self.test),
680 ('stopTest', self.test),
681 ], self.client._events)
683 def test_simple_success(self):
684 self.simple_success_keyword("failure")
686 def test_simple_success_colon(self):
687 self.simple_success_keyword("failure:")
689 def test_simple_success(self):
690 self.simple_success_keyword("successful")
692 def test_simple_success_colon(self):
693 self.simple_success_keyword("successful:")
695 def assertSuccess(self, details):
697 ('startTest', self.test),
698 ('addSuccess', self.test, details),
699 ('stopTest', self.test),
700 ], self.client._events)
702 def test_success_empty_message(self):
703 self.protocol.lineReceived("success mcdonalds farm [\n")
704 self.protocol.lineReceived("]\n")
706 details['message'] = Content(ContentType("text", "plain"),
708 self.assertSuccess(details)
710 def success_quoted_bracket(self, keyword):
711 # This tests it is accepted, but cannot test it is used today, because
712 # of not having a way to expose it in Python so far.
713 self.protocol.lineReceived("%s mcdonalds farm [\n" % keyword)
714 self.protocol.lineReceived(" ]\n")
715 self.protocol.lineReceived("]\n")
717 details['message'] = Content(ContentType("text", "plain"),
719 self.assertSuccess(details)
721 def test_success_quoted_bracket(self):
722 self.success_quoted_bracket("success")
724 def test_success_colon_quoted_bracket(self):
725 self.success_quoted_bracket("success:")
728 class TestTestProtocolServerProgress(unittest.TestCase):
729 """Test receipt of progress: directives."""
731 def test_progress_accepted_stdlib(self):
732 self.result = Python26TestResult()
733 self.stream = StringIO()
734 self.protocol = subunit.TestProtocolServer(self.result,
736 self.protocol.lineReceived("progress: 23")
737 self.protocol.lineReceived("progress: -2")
738 self.protocol.lineReceived("progress: +4")
739 self.assertEqual("", self.stream.getvalue())
741 def test_progress_accepted_extended(self):
742 # With a progress capable TestResult, progress events are emitted.
743 self.result = ExtendedTestResult()
744 self.stream = StringIO()
745 self.protocol = subunit.TestProtocolServer(self.result,
747 self.protocol.lineReceived("progress: 23")
748 self.protocol.lineReceived("progress: push")
749 self.protocol.lineReceived("progress: -2")
750 self.protocol.lineReceived("progress: pop")
751 self.protocol.lineReceived("progress: +4")
752 self.assertEqual("", self.stream.getvalue())
754 ('progress', 23, subunit.PROGRESS_SET),
755 ('progress', None, subunit.PROGRESS_PUSH),
756 ('progress', -2, subunit.PROGRESS_CUR),
757 ('progress', None, subunit.PROGRESS_POP),
758 ('progress', 4, subunit.PROGRESS_CUR),
759 ], self.result._events)
762 class TestTestProtocolServerStreamTags(unittest.TestCase):
763 """Test managing tags on the protocol level."""
766 self.client = ExtendedTestResult()
767 self.protocol = subunit.TestProtocolServer(self.client)
769 def test_initial_tags(self):
770 self.protocol.lineReceived("tags: foo bar:baz quux\n")
772 ('tags', set(["foo", "bar:baz", "quux"]), set()),
773 ], self.client._events)
775 def test_minus_removes_tags(self):
776 self.protocol.lineReceived("tags: -bar quux\n")
778 ('tags', set(["quux"]), set(["bar"])),
779 ], self.client._events)
781 def test_tags_do_not_get_set_on_test(self):
782 self.protocol.lineReceived("test mcdonalds farm\n")
783 test = self.client._events[0][-1]
784 self.assertEqual(None, getattr(test, 'tags', None))
786 def test_tags_do_not_get_set_on_global_tags(self):
787 self.protocol.lineReceived("tags: foo bar\n")
788 self.protocol.lineReceived("test mcdonalds farm\n")
789 test = self.client._events[-1][-1]
790 self.assertEqual(None, getattr(test, 'tags', None))
792 def test_tags_get_set_on_test_tags(self):
793 self.protocol.lineReceived("test mcdonalds farm\n")
794 test = self.client._events[-1][-1]
795 self.protocol.lineReceived("tags: foo bar\n")
796 self.protocol.lineReceived("success mcdonalds farm\n")
797 self.assertEqual(None, getattr(test, 'tags', None))
800 class TestTestProtocolServerStreamTime(unittest.TestCase):
801 """Test managing time information at the protocol level."""
803 def test_time_accepted_stdlib(self):
804 self.result = Python26TestResult()
805 self.stream = StringIO()
806 self.protocol = subunit.TestProtocolServer(self.result,
808 self.protocol.lineReceived("time: 2001-12-12 12:59:59Z\n")
809 self.assertEqual("", self.stream.getvalue())
811 def test_time_accepted_extended(self):
812 self.result = ExtendedTestResult()
813 self.stream = StringIO()
814 self.protocol = subunit.TestProtocolServer(self.result,
816 self.protocol.lineReceived("time: 2001-12-12 12:59:59Z\n")
817 self.assertEqual("", self.stream.getvalue())
819 ('time', datetime.datetime(2001, 12, 12, 12, 59, 59, 0,
821 ], self.result._events)
824 class TestRemotedTestCase(unittest.TestCase):
826 def test_simple(self):
827 test = subunit.RemotedTestCase("A test description")
828 self.assertRaises(NotImplementedError, test.setUp)
829 self.assertRaises(NotImplementedError, test.tearDown)
830 self.assertEqual("A test description",
831 test.shortDescription())
832 self.assertEqual("A test description",
834 self.assertEqual("A test description (subunit.RemotedTestCase)", "%s" % test)
835 self.assertEqual("<subunit.RemotedTestCase description="
836 "'A test description'>", "%r" % test)
837 result = unittest.TestResult()
839 self.assertEqual([(test, _remote_exception_str + ": "
840 "Cannot run RemotedTestCases.\n\n")],
842 self.assertEqual(1, result.testsRun)
843 another_test = subunit.RemotedTestCase("A test description")
844 self.assertEqual(test, another_test)
845 different_test = subunit.RemotedTestCase("ofo")
846 self.assertNotEqual(test, different_test)
847 self.assertNotEqual(another_test, different_test)
850 class TestRemoteError(unittest.TestCase):
853 error = subunit.RemoteError(u"Something went wrong")
854 another_error = subunit.RemoteError(u"Something went wrong")
855 different_error = subunit.RemoteError(u"boo!")
856 self.assertEqual(error, another_error)
857 self.assertNotEqual(error, different_error)
858 self.assertNotEqual(different_error, another_error)
860 def test_empty_constructor(self):
861 self.assertEqual(subunit.RemoteError(), subunit.RemoteError(u""))
864 class TestExecTestCase(unittest.TestCase):
866 class SampleExecTestCase(subunit.ExecTestCase):
868 def test_sample_method(self):
869 """sample-script.py"""
870 # the sample script runs three tests, one each
871 # that fails, errors and succeeds
873 def test_sample_method_args(self):
874 """sample-script.py foo"""
875 # sample that will run just one test.
877 def test_construct(self):
878 test = self.SampleExecTestCase("test_sample_method")
879 self.assertEqual(test.script,
880 subunit.join_dir(__file__, 'sample-script.py'))
883 result = unittest.TestResult()
884 test = self.SampleExecTestCase("test_sample_method_args")
886 self.assertEqual(1, result.testsRun)
889 result = ExtendedTestResult()
890 test = self.SampleExecTestCase("test_sample_method")
892 mcdonald = subunit.RemotedTestCase("old mcdonald")
893 bing = subunit.RemotedTestCase("bing crosby")
895 bing_details['traceback'] = Content(ContentType("text", "x-traceback",
896 {'charset': 'utf8'}), lambda:["foo.c:53:ERROR invalid state\n"])
897 an_error = subunit.RemotedTestCase("an error")
900 ('startTest', mcdonald),
901 ('addSuccess', mcdonald),
902 ('stopTest', mcdonald),
904 ('addFailure', bing, bing_details),
906 ('startTest', an_error),
907 ('addError', an_error, error_details),
908 ('stopTest', an_error),
911 def test_debug(self):
912 test = self.SampleExecTestCase("test_sample_method")
915 def test_count_test_cases(self):
916 """TODO run the child process and count responses to determine the count."""
918 def test_join_dir(self):
919 sibling = subunit.join_dir(__file__, 'foo')
920 expected = '%s/foo' % (os.path.split(__file__)[0],)
921 self.assertEqual(sibling, expected)
924 class DoExecTestCase(subunit.ExecTestCase):
926 def test_working_script(self):
927 """sample-two-script.py"""
930 class TestIsolatedTestCase(unittest.TestCase):
932 class SampleIsolatedTestCase(subunit.IsolatedTestCase):
939 TestIsolatedTestCase.SampleIsolatedTestCase.SETUP = True
942 TestIsolatedTestCase.SampleIsolatedTestCase.TEARDOWN = True
944 def test_sets_global_state(self):
945 TestIsolatedTestCase.SampleIsolatedTestCase.TEST = True
948 def test_construct(self):
949 test = self.SampleIsolatedTestCase("test_sets_global_state")
952 result = unittest.TestResult()
953 test = self.SampleIsolatedTestCase("test_sets_global_state")
955 self.assertEqual(result.testsRun, 1)
956 self.assertEqual(self.SampleIsolatedTestCase.SETUP, False)
957 self.assertEqual(self.SampleIsolatedTestCase.TEARDOWN, False)
958 self.assertEqual(self.SampleIsolatedTestCase.TEST, False)
960 def test_debug(self):
962 #test = self.SampleExecTestCase("test_sample_method")
966 class TestIsolatedTestSuite(unittest.TestCase):
968 class SampleTestToIsolate(unittest.TestCase):
975 TestIsolatedTestSuite.SampleTestToIsolate.SETUP = True
978 TestIsolatedTestSuite.SampleTestToIsolate.TEARDOWN = True
980 def test_sets_global_state(self):
981 TestIsolatedTestSuite.SampleTestToIsolate.TEST = True
984 def test_construct(self):
985 suite = subunit.IsolatedTestSuite()
988 result = unittest.TestResult()
989 suite = subunit.IsolatedTestSuite()
990 sub_suite = unittest.TestSuite()
991 sub_suite.addTest(self.SampleTestToIsolate("test_sets_global_state"))
992 sub_suite.addTest(self.SampleTestToIsolate("test_sets_global_state"))
993 suite.addTest(sub_suite)
994 suite.addTest(self.SampleTestToIsolate("test_sets_global_state"))
996 self.assertEqual(result.testsRun, 3)
997 self.assertEqual(self.SampleTestToIsolate.SETUP, False)
998 self.assertEqual(self.SampleTestToIsolate.TEARDOWN, False)
999 self.assertEqual(self.SampleTestToIsolate.TEST, False)
1002 class TestTestProtocolClient(unittest.TestCase):
1005 self.io = StringIO()
1006 self.protocol = subunit.TestProtocolClient(self.io)
1007 self.test = TestTestProtocolClient("test_start_test")
1008 self.sample_details = {'something':Content(
1009 ContentType('text', 'plain'), lambda:['serialised\nform'])}
1010 self.sample_tb_details = dict(self.sample_details)
1011 self.sample_tb_details['traceback'] = TracebackContent(
1012 subunit.RemoteError(u"boo qux"), self.test)
1014 def test_start_test(self):
1015 """Test startTest on a TestProtocolClient."""
1016 self.protocol.startTest(self.test)
1017 self.assertEqual(self.io.getvalue(), "test: %s\n" % self.test.id())
1019 def test_stop_test(self):
1020 # stopTest doesn't output anything.
1021 self.protocol.stopTest(self.test)
1022 self.assertEqual(self.io.getvalue(), "")
1024 def test_add_success(self):
1025 """Test addSuccess on a TestProtocolClient."""
1026 self.protocol.addSuccess(self.test)
1028 self.io.getvalue(), "successful: %s\n" % self.test.id())
1030 def test_add_success_details(self):
1031 """Test addSuccess on a TestProtocolClient with details."""
1032 self.protocol.addSuccess(self.test, details=self.sample_details)
1034 self.io.getvalue(), "successful: %s [ multipart\n"
1035 "Content-Type: text/plain\n"
1037 "F\r\nserialised\nform0\r\n]\n" % self.test.id())
1039 def test_add_failure(self):
1040 """Test addFailure on a TestProtocolClient."""
1041 self.protocol.addFailure(
1042 self.test, subunit.RemoteError(u"boo qux"))
1045 ('failure: %s [\n' + _remote_exception_str + ': boo qux\n]\n')
1048 def test_add_failure_details(self):
1049 """Test addFailure on a TestProtocolClient with details."""
1050 self.protocol.addFailure(
1051 self.test, details=self.sample_tb_details)
1054 ("failure: %s [ multipart\n"
1055 "Content-Type: text/plain\n"
1057 "F\r\nserialised\nform0\r\n"
1058 "Content-Type: text/x-traceback;charset=utf8,language=python\n"
1060 "1A\r\n" + _remote_exception_str + ": boo qux\n0\r\n"
1061 "]\n") % self.test.id())
1063 def test_add_error(self):
1064 """Test stopTest on a TestProtocolClient."""
1065 self.protocol.addError(
1066 self.test, subunit.RemoteError(u"phwoar crikey"))
1070 _remote_exception_str + ": phwoar crikey\n"
1071 "]\n") % self.test.id())
1073 def test_add_error_details(self):
1074 """Test stopTest on a TestProtocolClient with details."""
1075 self.protocol.addError(
1076 self.test, details=self.sample_tb_details)
1079 ("error: %s [ multipart\n"
1080 "Content-Type: text/plain\n"
1082 "F\r\nserialised\nform0\r\n"
1083 "Content-Type: text/x-traceback;charset=utf8,language=python\n"
1085 "1A\r\n" + _remote_exception_str + ": boo qux\n0\r\n"
1086 "]\n") % self.test.id())
1088 def test_add_expected_failure(self):
1089 """Test addExpectedFailure on a TestProtocolClient."""
1090 self.protocol.addExpectedFailure(
1091 self.test, subunit.RemoteError(u"phwoar crikey"))
1095 _remote_exception_str + ": phwoar crikey\n"
1096 "]\n") % self.test.id())
1098 def test_add_expected_failure_details(self):
1099 """Test addExpectedFailure on a TestProtocolClient with details."""
1100 self.protocol.addExpectedFailure(
1101 self.test, details=self.sample_tb_details)
1104 ("xfail: %s [ multipart\n"
1105 "Content-Type: text/plain\n"
1107 "F\r\nserialised\nform0\r\n"
1108 "Content-Type: text/x-traceback;charset=utf8,language=python\n"
1110 "1A\r\n"+ _remote_exception_str + ": boo qux\n0\r\n"
1111 "]\n") % self.test.id())
1113 def test_add_skip(self):
1114 """Test addSkip on a TestProtocolClient."""
1115 self.protocol.addSkip(
1116 self.test, "Has it really?")
1119 'skip: %s [\nHas it really?\n]\n' % self.test.id())
1121 def test_add_skip_details(self):
1122 """Test addSkip on a TestProtocolClient with details."""
1123 details = {'reason':Content(
1124 ContentType('text', 'plain'), lambda:['Has it really?'])}
1125 self.protocol.addSkip(
1126 self.test, details=details)
1129 "skip: %s [ multipart\n"
1130 "Content-Type: text/plain\n"
1132 "E\r\nHas it really?0\r\n"
1133 "]\n" % self.test.id())
1135 def test_progress_set(self):
1136 self.protocol.progress(23, subunit.PROGRESS_SET)
1137 self.assertEqual(self.io.getvalue(), 'progress: 23\n')
1139 def test_progress_neg_cur(self):
1140 self.protocol.progress(-23, subunit.PROGRESS_CUR)
1141 self.assertEqual(self.io.getvalue(), 'progress: -23\n')
1143 def test_progress_pos_cur(self):
1144 self.protocol.progress(23, subunit.PROGRESS_CUR)
1145 self.assertEqual(self.io.getvalue(), 'progress: +23\n')
1147 def test_progress_pop(self):
1148 self.protocol.progress(1234, subunit.PROGRESS_POP)
1149 self.assertEqual(self.io.getvalue(), 'progress: pop\n')
1151 def test_progress_push(self):
1152 self.protocol.progress(1234, subunit.PROGRESS_PUSH)
1153 self.assertEqual(self.io.getvalue(), 'progress: push\n')
1155 def test_time(self):
1156 # Calling time() outputs a time signal immediately.
1158 datetime.datetime(2009,10,11,12,13,14,15, iso8601.Utc()))
1160 "time: 2009-10-11 12:13:14.000015Z\n",
1163 def test_add_unexpected_success(self):
1164 """Test addUnexpectedSuccess on a TestProtocolClient."""
1165 self.protocol.addUnexpectedSuccess(self.test)
1167 self.io.getvalue(), "successful: %s\n" % self.test.id())
1169 def test_add_unexpected_success_details(self):
1170 """Test addUnexpectedSuccess on a TestProtocolClient with details."""
1171 self.protocol.addUnexpectedSuccess(self.test, details=self.sample_details)
1173 self.io.getvalue(), "successful: %s [ multipart\n"
1174 "Content-Type: text/plain\n"
1176 "F\r\nserialised\nform0\r\n]\n" % self.test.id())
1180 loader = subunit.tests.TestUtil.TestLoader()
1181 result = loader.loadTestsFromName(__name__)