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
24 from subunit.content import Content, TracebackContent
25 from subunit.content_type import ContentType
26 import subunit.iso8601 as iso8601
29 class MockTestProtocolServerClient(object):
30 """A mock protocol server client to test callbacks.
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.
40 self.failure_calls = []
43 self.success_calls = []
44 self.progress_calls = []
46 super(MockTestProtocolServerClient, self).__init__()
48 def addError(self, test, error):
49 self.error_calls.append((test, error))
51 def addFailure(self, test, error):
52 self.failure_calls.append((test, error))
54 def addSkip(self, test, reason):
55 self.skip_calls.append((test, reason))
57 def addSuccess(self, test):
58 self.success_calls.append(test)
60 def stopTest(self, test):
61 self.end_calls.append(test)
63 def startTest(self, test):
64 self.start_calls.append(test)
66 def progress(self, offset, whence):
67 self.progress_calls.append((offset, whence))
73 class MockExtendedTestProtocolServerClient(MockTestProtocolServerClient):
74 """An extended TestResult for testing which implements tags() etc."""
77 MockTestProtocolServerClient.__init__(self)
79 self.gone_tags = set()
81 def tags(self, new_tags, gone_tags):
82 self.new_tags = new_tags
83 self.gone_tags = gone_tags
86 class TestMockTestProtocolServer(unittest.TestCase):
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, [])
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, [])
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, [])
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")])
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, [])
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)])
148 class TestTestImports(unittest.TestCase):
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
160 class TestDiscardStream(unittest.TestCase):
162 def test_write(self):
163 subunit.DiscardStream().write("content")
166 class TestTestProtocolServerPipe(unittest.TestCase):
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"
174 "failure bing crosby [\n"
175 "foo.c:53:ERROR invalid state\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')])
187 [(bing, "RemoteException: foo.c:53:ERROR invalid state\n\n")])
188 self.assertEqual(client.testsRun, 3)
191 class TestTestProtocolServerStartTest(unittest.TestCase):
194 self.client = MockTestProtocolServerClient()
195 self.protocol = subunit.TestProtocolServer(self.client)
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")])
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")])
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")])
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")])
218 class TestTestProtocolServerPassThrough(unittest.TestCase):
221 self.stdout = StringIO()
222 self.test = subunit.RemotedTestCase("old mcdonald")
223 self.client = MockTestProtocolServerClient()
224 self.protocol = subunit.TestProtocolServer(self.client, self.stdout)
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"
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, [])
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, [])
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, [])
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])
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"
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, [])
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"
342 self.assertEqual(self.client.end_calls, [self.test])
343 self.assertEqual(self.client.error_calls, [])
344 self.assertEqual(self.client.success_calls, [])
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.
350 bytes = "randombytes\n"
351 self.protocol.lineReceived(bytes)
352 self.assertEqual(self.stdout.getvalue(), bytes)
355 class TestTestProtocolServerLostConnection(unittest.TestCase):
358 self.client = MockTestProtocolServerClient()
359 self.protocol = subunit.TestProtocolServer(self.client)
360 self.test = subunit.RemotedTestCase("old mcdonald")
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, [])
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, [])
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, [])
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, [])
403 def test_lost_connection_during_error(self):
404 self.do_connection_lost("error", "[\n")
406 def test_lost_connection_during_error_details(self):
407 self.do_connection_lost("error", "[ multipart\n")
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, [])
421 def test_lost_connection_during_failure(self):
422 self.do_connection_lost("failure", "[\n")
424 def test_lost_connection_during_failure_details(self):
425 self.do_connection_lost("failure", "[ multipart\n")
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])
437 def test_lost_connection_during_success(self):
438 self.do_connection_lost("success", "[\n")
440 def test_lost_connection_during_success_details(self):
441 self.do_connection_lost("success", "[ multipart\n")
443 def test_lost_connection_during_skip(self):
444 self.do_connection_lost("skip", "[\n")
446 def test_lost_connection_during_skip_details(self):
447 self.do_connection_lost("skip", "[ multipart\n")
449 def test_lost_connection_during_xfail(self):
450 self.do_connection_lost("xfail", "[\n")
452 def test_lost_connection_during_xfail_details(self):
453 self.do_connection_lost("xfail", "[ multipart\n")
456 class TestInTestMultipart(unittest.TestCase):
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")
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))
474 class TestTestProtocolServerAddError(unittest.TestCase):
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")
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, [])
490 def test_simple_error(self):
491 self.simple_error_keyword("error")
493 def test_simple_error_colon(self):
494 self.simple_error_keyword("error:")
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, [])
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, [])
515 def test_error_quoted_bracket(self):
516 self.error_quoted_bracket("error")
518 def test_error_colon_quoted_bracket(self):
519 self.error_quoted_bracket("error:")
522 class TestTestProtocolServerAddFailure(unittest.TestCase):
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")
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())])
538 def test_simple_failure(self):
539 self.simple_failure_keyword("failure")
541 def test_simple_failure_colon(self):
542 self.simple_failure_keyword("failure:")
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())])
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"))])
563 def test_failure_quoted_bracket(self):
564 self.failure_quoted_bracket("failure")
566 def test_failure_colon_quoted_bracket(self):
567 self.failure_quoted_bracket("failure:")
570 class TestTestProtocolServerAddxFail(unittest.TestCase):
571 """Tests for the xfail keyword.
573 In Python this can thunk through to Success due to stdlib limitations (see
577 def capture_expected_failure(self, test, err):
578 self._calls.append((test, err))
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()
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
590 self.setup_protocol()
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]
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)
606 def check_success_or_xfail(self, as_success):
608 self.assertEqual(self.client.success_calls, [self.test])
610 self.assertEqual(1, len(self._calls))
611 self.assertEqual(self.test, self._calls[0][0])
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)
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)
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)
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)
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)
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)
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)
665 class TestTestProtocolServerAddSkip(unittest.TestCase):
666 """Tests for the skip keyword.
668 In Python this meets the testtools extended TestResult contract.
669 (See https://launchpad.net/testtools).
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]
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')])
689 def test_simple_skip(self):
690 self.simple_skip_keyword("skip")
692 def test_simple_skip_colon(self):
693 self.simple_skip_keyword("skip:")
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")])
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")])
720 def test_skip_quoted_bracket(self):
721 self.skip_quoted_bracket("skip")
723 def test_skip_colon_quoted_bracket(self):
724 self.skip_quoted_bracket("skip:")
727 class TestTestProtocolServerAddSuccess(unittest.TestCase):
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")
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])
742 def test_simple_success(self):
743 self.simple_success_keyword("failure")
745 def test_simple_success_colon(self):
746 self.simple_success_keyword("failure:")
748 def test_simple_success(self):
749 self.simple_success_keyword("successful")
751 def test_simple_success_colon(self):
752 self.simple_success_keyword("successful:")
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])
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])
775 def test_success_quoted_bracket(self):
776 self.success_quoted_bracket("success")
778 def test_success_colon_quoted_bracket(self):
779 self.success_quoted_bracket("success:")
782 class TestTestProtocolServerProgress(unittest.TestCase):
783 """Test receipt of progress: directives."""
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,
791 self.protocol.lineReceived("progress: 23")
792 self.protocol.lineReceived("progress: -2")
793 self.protocol.lineReceived("progress: +4")
794 self.assertEqual("", self.stream.getvalue())
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,
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())
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)
815 class TestTestProtocolServerStreamTags(unittest.TestCase):
816 """Test managing tags on the protocol level."""
819 self.client = MockExtendedTestProtocolServerClient()
820 self.protocol = subunit.TestProtocolServer(self.client)
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)
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)
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))
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))
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))
856 class TestTestProtocolServerStreamTime(unittest.TestCase):
857 """Test managing time information at the protocol level."""
859 def test_time_accepted_stdlib(self):
860 self.result = unittest.TestResult()
861 self.stream = StringIO()
862 self.protocol = subunit.TestProtocolServer(self.result,
864 self.protocol.lineReceived("time: 2001-12-12 12:59:59Z\n")
865 self.assertEqual("", self.stream.getvalue())
867 def test_time_accepted_extended(self):
868 self.result = MockTestProtocolServerClient()
869 self.stream = StringIO()
870 self.protocol = subunit.TestProtocolServer(self.result,
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)
878 class TestRemotedTestCase(unittest.TestCase):
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",
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()
893 self.assertEqual([(test, "RemoteException: "
894 "Cannot run RemotedTestCases.\n\n")],
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)
904 class TestRemoteError(unittest.TestCase):
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)
914 def test_empty_constructor(self):
915 self.assertEqual(subunit.RemoteError(), subunit.RemoteError(""))
918 class TestExecTestCase(unittest.TestCase):
920 class SampleExecTestCase(subunit.ExecTestCase):
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
927 def test_sample_method_args(self):
928 """sample-script.py foo"""
929 # sample that will run just one test.
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'))
937 result = unittest.TestResult()
938 test = self.SampleExecTestCase("test_sample_method_args")
940 self.assertEqual(1, result.testsRun)
943 runner = MockTestProtocolServerClient()
944 test = self.SampleExecTestCase("test_sample_method")
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,
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])
958 def test_debug(self):
959 test = self.SampleExecTestCase("test_sample_method")
962 def test_count_test_cases(self):
963 """TODO run the child process and count responses to determine the count."""
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)
971 class DoExecTestCase(subunit.ExecTestCase):
973 def test_working_script(self):
974 """sample-two-script.py"""
977 class TestIsolatedTestCase(unittest.TestCase):
979 class SampleIsolatedTestCase(subunit.IsolatedTestCase):
986 TestIsolatedTestCase.SampleIsolatedTestCase.SETUP = True
989 TestIsolatedTestCase.SampleIsolatedTestCase.TEARDOWN = True
991 def test_sets_global_state(self):
992 TestIsolatedTestCase.SampleIsolatedTestCase.TEST = True
995 def test_construct(self):
996 test = self.SampleIsolatedTestCase("test_sets_global_state")
999 result = unittest.TestResult()
1000 test = self.SampleIsolatedTestCase("test_sets_global_state")
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)
1007 def test_debug(self):
1009 #test = self.SampleExecTestCase("test_sample_method")
1013 class TestIsolatedTestSuite(unittest.TestCase):
1015 class SampleTestToIsolate(unittest.TestCase):
1022 TestIsolatedTestSuite.SampleTestToIsolate.SETUP = True
1025 TestIsolatedTestSuite.SampleTestToIsolate.TEARDOWN = True
1027 def test_sets_global_state(self):
1028 TestIsolatedTestSuite.SampleTestToIsolate.TEST = True
1031 def test_construct(self):
1032 suite = subunit.IsolatedTestSuite()
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"))
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)
1049 class TestTestProtocolClient(unittest.TestCase):
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"))
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())
1066 def test_stop_test(self):
1067 # stopTest doesn't output anything.
1068 self.protocol.stopTest(self.test)
1069 self.assertEqual(self.io.getvalue(), "")
1071 def test_add_success(self):
1072 """Test addSuccess on a TestProtocolClient."""
1073 self.protocol.addSuccess(self.test)
1075 self.io.getvalue(), "successful: %s\n" % self.test.id())
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)
1081 self.io.getvalue(), "successful: %s [ multipart\n"
1082 "Content-Type: text/plain\n"
1084 "F\r\nserialised\nform0\r\n]\n" % self.test.id())
1086 def test_add_failure(self):
1087 """Test addFailure on a TestProtocolClient."""
1088 self.protocol.addFailure(
1089 self.test, subunit.RemoteError("boo qux"))
1092 'failure: %s [\nRemoteException: boo qux\n]\n' % self.test.id())
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)
1100 "failure: %s [ multipart\n"
1101 "Content-Type: text/plain\n"
1103 "F\r\nserialised\nform0\r\n"
1104 "Content-Type: text/x-traceback;language=python\n"
1106 "19\r\nRemoteException: boo qux\n0\r\n"
1107 "]\n" % self.test.id())
1109 def test_add_error(self):
1110 """Test stopTest on a TestProtocolClient."""
1111 self.protocol.addError(
1112 self.test, subunit.RemoteError("phwoar crikey"))
1116 "RemoteException: phwoar crikey\n"
1117 "]\n" % self.test.id())
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)
1125 "error: %s [ multipart\n"
1126 "Content-Type: text/plain\n"
1128 "F\r\nserialised\nform0\r\n"
1129 "Content-Type: text/x-traceback;language=python\n"
1131 "19\r\nRemoteException: boo qux\n0\r\n"
1132 "]\n" % self.test.id())
1134 def test_add_expected_failure(self):
1135 """Test addExpectedFailure on a TestProtocolClient."""
1136 self.protocol.addExpectedFailure(
1137 self.test, subunit.RemoteError("phwoar crikey"))
1141 "RemoteException: phwoar crikey\n"
1142 "]\n" % self.test.id())
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)
1150 "xfail: %s [ multipart\n"
1151 "Content-Type: text/plain\n"
1153 "F\r\nserialised\nform0\r\n"
1154 "Content-Type: text/x-traceback;language=python\n"
1156 "19\r\nRemoteException: boo qux\n0\r\n"
1157 "]\n" % self.test.id())
1159 def test_add_skip(self):
1160 """Test addSkip on a TestProtocolClient."""
1161 self.protocol.addSkip(
1162 self.test, "Has it really?")
1165 'skip: %s [\nHas it really?\n]\n' % self.test.id())
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)
1175 "skip: %s [ multipart\n"
1176 "Content-Type: text/plain\n"
1178 "E\r\nHas it really?0\r\n"
1179 "]\n" % self.test.id())
1181 def test_progress_set(self):
1182 self.protocol.progress(23, subunit.PROGRESS_SET)
1183 self.assertEqual(self.io.getvalue(), 'progress: 23\n')
1185 def test_progress_neg_cur(self):
1186 self.protocol.progress(-23, subunit.PROGRESS_CUR)
1187 self.assertEqual(self.io.getvalue(), 'progress: -23\n')
1189 def test_progress_pos_cur(self):
1190 self.protocol.progress(23, subunit.PROGRESS_CUR)
1191 self.assertEqual(self.io.getvalue(), 'progress: +23\n')
1193 def test_progress_pop(self):
1194 self.protocol.progress(1234, subunit.PROGRESS_POP)
1195 self.assertEqual(self.io.getvalue(), 'progress: pop\n')
1197 def test_progress_push(self):
1198 self.protocol.progress(1234, subunit.PROGRESS_PUSH)
1199 self.assertEqual(self.io.getvalue(), 'progress: push\n')
1201 def test_time(self):
1202 # Calling time() outputs a time signal immediately.
1204 datetime.datetime(2009,10,11,12,13,14,15, iso8601.Utc()))
1206 "time: 2009-10-11 12:13:14.000015Z\n",
1209 def test_add_unexpected_success(self):
1210 """Test addUnexpectedSuccess on a TestProtocolClient."""
1211 self.protocol.addUnexpectedSuccess(self.test)
1213 self.io.getvalue(), "successful: %s\n" % self.test.id())
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)
1219 self.io.getvalue(), "successful: %s [ multipart\n"
1220 "Content-Type: text/plain\n"
1222 "F\r\nserialised\nform0\r\n]\n" % self.test.id())
1226 loader = subunit.tests.TestUtil.TestLoader()
1227 result = loader.loadTestsFromName(__name__)