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)
106 class TestTestProtocolServerStartTest(unittest
.TestCase
):
109 self
.client
= Python26TestResult()
110 self
.protocol
= subunit
.TestProtocolServer(self
.client
)
112 def test_start_test(self
):
113 self
.protocol
.lineReceived("test old mcdonald\n")
114 self
.assertEqual(self
.client
._events
,
115 [('startTest', subunit
.RemotedTestCase("old mcdonald"))])
117 def test_start_testing(self
):
118 self
.protocol
.lineReceived("testing old mcdonald\n")
119 self
.assertEqual(self
.client
._events
,
120 [('startTest', subunit
.RemotedTestCase("old mcdonald"))])
122 def test_start_test_colon(self
):
123 self
.protocol
.lineReceived("test: old mcdonald\n")
124 self
.assertEqual(self
.client
._events
,
125 [('startTest', subunit
.RemotedTestCase("old mcdonald"))])
127 def test_start_testing_colon(self
):
128 self
.protocol
.lineReceived("testing: old mcdonald\n")
129 self
.assertEqual(self
.client
._events
,
130 [('startTest', subunit
.RemotedTestCase("old mcdonald"))])
133 class TestTestProtocolServerPassThrough(unittest
.TestCase
):
136 self
.stdout
= StringIO()
137 self
.test
= subunit
.RemotedTestCase("old mcdonald")
138 self
.client
= ExtendedTestResult()
139 self
.protocol
= subunit
.TestProtocolServer(self
.client
, self
.stdout
)
141 def keywords_before_test(self
):
142 self
.protocol
.lineReceived("failure a\n")
143 self
.protocol
.lineReceived("failure: a\n")
144 self
.protocol
.lineReceived("error a\n")
145 self
.protocol
.lineReceived("error: a\n")
146 self
.protocol
.lineReceived("success a\n")
147 self
.protocol
.lineReceived("success: a\n")
148 self
.protocol
.lineReceived("successful a\n")
149 self
.protocol
.lineReceived("successful: a\n")
150 self
.protocol
.lineReceived("]\n")
151 self
.assertEqual(self
.stdout
.getvalue(), "failure a\n"
161 def test_keywords_before_test(self
):
162 self
.keywords_before_test()
163 self
.assertEqual(self
.client
._events
, [])
165 def test_keywords_after_error(self
):
166 self
.protocol
.lineReceived("test old mcdonald\n")
167 self
.protocol
.lineReceived("error old mcdonald\n")
168 self
.keywords_before_test()
170 ('startTest', self
.test
),
171 ('addError', self
.test
, {}),
172 ('stopTest', self
.test
),
173 ], self
.client
._events
)
175 def test_keywords_after_failure(self
):
176 self
.protocol
.lineReceived("test old mcdonald\n")
177 self
.protocol
.lineReceived("failure old mcdonald\n")
178 self
.keywords_before_test()
179 self
.assertEqual(self
.client
._events
, [
180 ('startTest', self
.test
),
181 ('addFailure', self
.test
, {}),
182 ('stopTest', self
.test
),
185 def test_keywords_after_success(self
):
186 self
.protocol
.lineReceived("test old mcdonald\n")
187 self
.protocol
.lineReceived("success old mcdonald\n")
188 self
.keywords_before_test()
190 ('startTest', self
.test
),
191 ('addSuccess', self
.test
),
192 ('stopTest', self
.test
),
193 ], self
.client
._events
)
195 def test_keywords_after_test(self
):
196 self
.protocol
.lineReceived("test old mcdonald\n")
197 self
.protocol
.lineReceived("test old mcdonald\n")
198 self
.protocol
.lineReceived("failure a\n")
199 self
.protocol
.lineReceived("failure: a\n")
200 self
.protocol
.lineReceived("error a\n")
201 self
.protocol
.lineReceived("error: a\n")
202 self
.protocol
.lineReceived("success a\n")
203 self
.protocol
.lineReceived("success: a\n")
204 self
.protocol
.lineReceived("successful a\n")
205 self
.protocol
.lineReceived("successful: a\n")
206 self
.protocol
.lineReceived("]\n")
207 self
.protocol
.lineReceived("failure old mcdonald\n")
208 self
.assertEqual(self
.stdout
.getvalue(), "test old mcdonald\n"
218 self
.assertEqual(self
.client
._events
, [
219 ('startTest', self
.test
),
220 ('addFailure', self
.test
, {}),
221 ('stopTest', self
.test
),
224 def test_keywords_during_failure(self
):
225 # A smoke test to make sure that the details parsers have control
227 self
.protocol
.lineReceived("test old mcdonald\n")
228 self
.protocol
.lineReceived("failure: old mcdonald [\n")
229 self
.protocol
.lineReceived("test old mcdonald\n")
230 self
.protocol
.lineReceived("failure a\n")
231 self
.protocol
.lineReceived("failure: a\n")
232 self
.protocol
.lineReceived("error a\n")
233 self
.protocol
.lineReceived("error: a\n")
234 self
.protocol
.lineReceived("success a\n")
235 self
.protocol
.lineReceived("success: a\n")
236 self
.protocol
.lineReceived("successful a\n")
237 self
.protocol
.lineReceived("successful: a\n")
238 self
.protocol
.lineReceived(" ]\n")
239 self
.protocol
.lineReceived("]\n")
240 self
.assertEqual(self
.stdout
.getvalue(), "")
242 details
['traceback'] = Content(ContentType("text", "x-traceback"),
244 "test old mcdonald\n"
254 self
.assertEqual(self
.client
._events
, [
255 ('startTest', self
.test
),
256 ('addFailure', self
.test
, details
),
257 ('stopTest', self
.test
),
260 def test_stdout_passthrough(self
):
261 """Lines received which cannot be interpreted as any protocol action
262 should be passed through to sys.stdout.
264 bytes
= "randombytes\n"
265 self
.protocol
.lineReceived(bytes
)
266 self
.assertEqual(self
.stdout
.getvalue(), bytes
)
269 class TestTestProtocolServerLostConnection(unittest
.TestCase
):
272 self
.client
= Python26TestResult()
273 self
.protocol
= subunit
.TestProtocolServer(self
.client
)
274 self
.test
= subunit
.RemotedTestCase("old mcdonald")
276 def test_lost_connection_no_input(self
):
277 self
.protocol
.lostConnection()
278 self
.assertEqual([], self
.client
._events
)
280 def test_lost_connection_after_start(self
):
281 self
.protocol
.lineReceived("test old mcdonald\n")
282 self
.protocol
.lostConnection()
283 failure
= subunit
.RemoteError(
284 "lost connection during test 'old mcdonald'")
286 ('startTest', self
.test
),
287 ('addError', self
.test
, failure
),
288 ('stopTest', self
.test
),
289 ], self
.client
._events
)
291 def test_lost_connected_after_error(self
):
292 self
.protocol
.lineReceived("test old mcdonald\n")
293 self
.protocol
.lineReceived("error old mcdonald\n")
294 self
.protocol
.lostConnection()
296 ('startTest', self
.test
),
297 ('addError', self
.test
, subunit
.RemoteError("")),
298 ('stopTest', self
.test
),
299 ], self
.client
._events
)
301 def do_connection_lost(self
, outcome
, opening
):
302 self
.protocol
.lineReceived("test old mcdonald\n")
303 self
.protocol
.lineReceived("%s old mcdonald %s" % (outcome
, opening
))
304 self
.protocol
.lostConnection()
305 failure
= subunit
.RemoteError(
306 "lost connection during %s report of test 'old mcdonald'" %
309 ('startTest', self
.test
),
310 ('addError', self
.test
, failure
),
311 ('stopTest', self
.test
),
312 ], self
.client
._events
)
314 def test_lost_connection_during_error(self
):
315 self
.do_connection_lost("error", "[\n")
317 def test_lost_connection_during_error_details(self
):
318 self
.do_connection_lost("error", "[ multipart\n")
320 def test_lost_connected_after_failure(self
):
321 self
.protocol
.lineReceived("test old mcdonald\n")
322 self
.protocol
.lineReceived("failure old mcdonald\n")
323 self
.protocol
.lostConnection()
325 ('startTest', self
.test
),
326 ('addFailure', self
.test
, subunit
.RemoteError("")),
327 ('stopTest', self
.test
),
328 ], self
.client
._events
)
330 def test_lost_connection_during_failure(self
):
331 self
.do_connection_lost("failure", "[\n")
333 def test_lost_connection_during_failure_details(self
):
334 self
.do_connection_lost("failure", "[ multipart\n")
336 def test_lost_connection_after_success(self
):
337 self
.protocol
.lineReceived("test old mcdonald\n")
338 self
.protocol
.lineReceived("success old mcdonald\n")
339 self
.protocol
.lostConnection()
341 ('startTest', self
.test
),
342 ('addSuccess', self
.test
),
343 ('stopTest', self
.test
),
344 ], self
.client
._events
)
346 def test_lost_connection_during_success(self
):
347 self
.do_connection_lost("success", "[\n")
349 def test_lost_connection_during_success_details(self
):
350 self
.do_connection_lost("success", "[ multipart\n")
352 def test_lost_connection_during_skip(self
):
353 self
.do_connection_lost("skip", "[\n")
355 def test_lost_connection_during_skip_details(self
):
356 self
.do_connection_lost("skip", "[ multipart\n")
358 def test_lost_connection_during_xfail(self
):
359 self
.do_connection_lost("xfail", "[\n")
361 def test_lost_connection_during_xfail_details(self
):
362 self
.do_connection_lost("xfail", "[ multipart\n")
365 class TestInTestMultipart(unittest
.TestCase
):
368 self
.client
= ExtendedTestResult()
369 self
.protocol
= subunit
.TestProtocolServer(self
.client
)
370 self
.protocol
.lineReceived("test mcdonalds farm\n")
371 self
.test
= subunit
.RemotedTestCase("mcdonalds farm")
373 def test__outcome_sets_details_parser(self
):
374 self
.protocol
._reading
_success
_details
.details_parser
= None
375 self
.protocol
._state
._outcome
(0, "mcdonalds farm [ multipart\n",
376 None, self
.protocol
._reading
_success
_details
)
377 parser
= self
.protocol
._reading
_success
_details
.details_parser
378 self
.assertNotEqual(None, parser
)
379 self
.assertTrue(isinstance(parser
,
380 subunit
.details
.MultipartDetailsParser
))
383 class TestTestProtocolServerAddError(unittest
.TestCase
):
386 self
.client
= ExtendedTestResult()
387 self
.protocol
= subunit
.TestProtocolServer(self
.client
)
388 self
.protocol
.lineReceived("test mcdonalds farm\n")
389 self
.test
= subunit
.RemotedTestCase("mcdonalds farm")
391 def simple_error_keyword(self
, keyword
):
392 self
.protocol
.lineReceived("%s mcdonalds farm\n" % keyword
)
395 ('startTest', self
.test
),
396 ('addError', self
.test
, details
),
397 ('stopTest', self
.test
),
398 ], self
.client
._events
)
400 def test_simple_error(self
):
401 self
.simple_error_keyword("error")
403 def test_simple_error_colon(self
):
404 self
.simple_error_keyword("error:")
406 def test_error_empty_message(self
):
407 self
.protocol
.lineReceived("error mcdonalds farm [\n")
408 self
.protocol
.lineReceived("]\n")
410 details
['traceback'] = Content(ContentType("text", "x-traceback"),
413 ('startTest', self
.test
),
414 ('addError', self
.test
, details
),
415 ('stopTest', self
.test
),
416 ], self
.client
._events
)
418 def error_quoted_bracket(self
, keyword
):
419 self
.protocol
.lineReceived("%s mcdonalds farm [\n" % keyword
)
420 self
.protocol
.lineReceived(" ]\n")
421 self
.protocol
.lineReceived("]\n")
423 details
['traceback'] = Content(ContentType("text", "x-traceback"),
426 ('startTest', self
.test
),
427 ('addError', self
.test
, details
),
428 ('stopTest', self
.test
),
429 ], self
.client
._events
)
431 def test_error_quoted_bracket(self
):
432 self
.error_quoted_bracket("error")
434 def test_error_colon_quoted_bracket(self
):
435 self
.error_quoted_bracket("error:")
438 class TestTestProtocolServerAddFailure(unittest
.TestCase
):
441 self
.client
= ExtendedTestResult()
442 self
.protocol
= subunit
.TestProtocolServer(self
.client
)
443 self
.protocol
.lineReceived("test mcdonalds farm\n")
444 self
.test
= subunit
.RemotedTestCase("mcdonalds farm")
446 def assertFailure(self
, details
):
448 ('startTest', self
.test
),
449 ('addFailure', self
.test
, details
),
450 ('stopTest', self
.test
),
451 ], self
.client
._events
)
453 def simple_failure_keyword(self
, keyword
):
454 self
.protocol
.lineReceived("%s mcdonalds farm\n" % keyword
)
456 self
.assertFailure(details
)
458 def test_simple_failure(self
):
459 self
.simple_failure_keyword("failure")
461 def test_simple_failure_colon(self
):
462 self
.simple_failure_keyword("failure:")
464 def test_failure_empty_message(self
):
465 self
.protocol
.lineReceived("failure mcdonalds farm [\n")
466 self
.protocol
.lineReceived("]\n")
468 details
['traceback'] = Content(ContentType("text", "x-traceback"),
470 self
.assertFailure(details
)
472 def failure_quoted_bracket(self
, keyword
):
473 self
.protocol
.lineReceived("%s mcdonalds farm [\n" % keyword
)
474 self
.protocol
.lineReceived(" ]\n")
475 self
.protocol
.lineReceived("]\n")
477 details
['traceback'] = Content(ContentType("text", "x-traceback"),
479 self
.assertFailure(details
)
481 def test_failure_quoted_bracket(self
):
482 self
.failure_quoted_bracket("failure")
484 def test_failure_colon_quoted_bracket(self
):
485 self
.failure_quoted_bracket("failure:")
488 class TestTestProtocolServerAddxFail(unittest
.TestCase
):
489 """Tests for the xfail keyword.
491 In Python this can thunk through to Success due to stdlib limitations (see
495 def capture_expected_failure(self
, test
, err
):
496 self
._events
.append((test
, err
))
498 def setup_python26(self
):
499 """Setup a test object ready to be xfailed and thunk to success."""
500 self
.client
= Python26TestResult()
501 self
.setup_protocol()
503 def setup_python27(self
):
504 """Setup a test object ready to be xfailed."""
505 self
.client
= Python27TestResult()
506 self
.setup_protocol()
508 def setup_python_ex(self
):
509 """Setup a test object ready to be xfailed with details."""
510 self
.client
= ExtendedTestResult()
511 self
.setup_protocol()
513 def setup_protocol(self
):
514 """Setup the protocol based on self.client."""
515 self
.protocol
= subunit
.TestProtocolServer(self
.client
)
516 self
.protocol
.lineReceived("test mcdonalds farm\n")
517 self
.test
= self
.client
._events
[-1][-1]
519 def simple_xfail_keyword(self
, keyword
, as_success
):
520 self
.protocol
.lineReceived("%s mcdonalds farm\n" % keyword
)
521 self
.check_success_or_xfail(as_success
)
523 def check_success_or_xfail(self
, as_success
, error_message
=None):
526 ('startTest', self
.test
),
527 ('addSuccess', self
.test
),
528 ('stopTest', self
.test
),
529 ], self
.client
._events
)
532 if error_message
is not None:
533 details
['traceback'] = Content(
534 ContentType("text", "x-traceback"), lambda:[error_message
])
535 if isinstance(self
.client
, ExtendedTestResult
):
538 if error_message
is not None:
539 value
= subunit
.RemoteError('Text attachment: traceback\n'
540 '------------\n' + error_message
+ '------------\n')
542 value
= subunit
.RemoteError()
544 ('startTest', self
.test
),
545 ('addExpectedFailure', self
.test
, value
),
546 ('stopTest', self
.test
),
547 ], self
.client
._events
)
549 def test_simple_xfail(self
):
550 self
.setup_python26()
551 self
.simple_xfail_keyword("xfail", True)
552 self
.setup_python27()
553 self
.simple_xfail_keyword("xfail", False)
554 self
.setup_python_ex()
555 self
.simple_xfail_keyword("xfail", False)
557 def test_simple_xfail_colon(self
):
558 self
.setup_python26()
559 self
.simple_xfail_keyword("xfail:", True)
560 self
.setup_python27()
561 self
.simple_xfail_keyword("xfail:", False)
562 self
.setup_python_ex()
563 self
.simple_xfail_keyword("xfail:", False)
565 def test_xfail_empty_message(self
):
566 self
.setup_python26()
567 self
.empty_message(True)
568 self
.setup_python27()
569 self
.empty_message(False)
570 self
.setup_python_ex()
571 self
.empty_message(False, error_message
="")
573 def empty_message(self
, as_success
, error_message
="\n"):
574 self
.protocol
.lineReceived("xfail mcdonalds farm [\n")
575 self
.protocol
.lineReceived("]\n")
576 self
.check_success_or_xfail(as_success
, error_message
)
578 def xfail_quoted_bracket(self
, keyword
, as_success
):
579 # This tests it is accepted, but cannot test it is used today, because
580 # of not having a way to expose it in Python so far.
581 self
.protocol
.lineReceived("%s mcdonalds farm [\n" % keyword
)
582 self
.protocol
.lineReceived(" ]\n")
583 self
.protocol
.lineReceived("]\n")
584 self
.check_success_or_xfail(as_success
, "]\n")
586 def test_xfail_quoted_bracket(self
):
587 self
.setup_python26()
588 self
.xfail_quoted_bracket("xfail", True)
589 self
.setup_python27()
590 self
.xfail_quoted_bracket("xfail", False)
591 self
.setup_python_ex()
592 self
.xfail_quoted_bracket("xfail", False)
594 def test_xfail_colon_quoted_bracket(self
):
595 self
.setup_python26()
596 self
.xfail_quoted_bracket("xfail:", True)
597 self
.setup_python27()
598 self
.xfail_quoted_bracket("xfail:", False)
599 self
.setup_python_ex()
600 self
.xfail_quoted_bracket("xfail:", False)
603 class TestTestProtocolServerAddSkip(unittest
.TestCase
):
604 """Tests for the skip keyword.
606 In Python this meets the testtools extended TestResult contract.
607 (See https://launchpad.net/testtools).
611 """Setup a test object ready to be skipped."""
612 self
.client
= ExtendedTestResult()
613 self
.protocol
= subunit
.TestProtocolServer(self
.client
)
614 self
.protocol
.lineReceived("test mcdonalds farm\n")
615 self
.test
= self
.client
._events
[-1][-1]
617 def assertSkip(self
, reason
):
619 if reason
is not None:
620 details
['reason'] = Content(
621 ContentType("text", "plain"), lambda:[reason
])
623 ('startTest', self
.test
),
624 ('addSkip', self
.test
, details
),
625 ('stopTest', self
.test
),
626 ], self
.client
._events
)
628 def simple_skip_keyword(self
, keyword
):
629 self
.protocol
.lineReceived("%s mcdonalds farm\n" % keyword
)
630 self
.assertSkip(None)
632 def test_simple_skip(self
):
633 self
.simple_skip_keyword("skip")
635 def test_simple_skip_colon(self
):
636 self
.simple_skip_keyword("skip:")
638 def test_skip_empty_message(self
):
639 self
.protocol
.lineReceived("skip mcdonalds farm [\n")
640 self
.protocol
.lineReceived("]\n")
643 def skip_quoted_bracket(self
, keyword
):
644 # This tests it is accepted, but cannot test it is used today, because
645 # of not having a way to expose it in Python so far.
646 self
.protocol
.lineReceived("%s mcdonalds farm [\n" % keyword
)
647 self
.protocol
.lineReceived(" ]\n")
648 self
.protocol
.lineReceived("]\n")
649 self
.assertSkip("]\n")
651 def test_skip_quoted_bracket(self
):
652 self
.skip_quoted_bracket("skip")
654 def test_skip_colon_quoted_bracket(self
):
655 self
.skip_quoted_bracket("skip:")
658 class TestTestProtocolServerAddSuccess(unittest
.TestCase
):
661 self
.client
= ExtendedTestResult()
662 self
.protocol
= subunit
.TestProtocolServer(self
.client
)
663 self
.protocol
.lineReceived("test mcdonalds farm\n")
664 self
.test
= subunit
.RemotedTestCase("mcdonalds farm")
666 def simple_success_keyword(self
, keyword
):
667 self
.protocol
.lineReceived("%s mcdonalds farm\n" % keyword
)
669 ('startTest', self
.test
),
670 ('addSuccess', self
.test
),
671 ('stopTest', self
.test
),
672 ], self
.client
._events
)
674 def test_simple_success(self
):
675 self
.simple_success_keyword("failure")
677 def test_simple_success_colon(self
):
678 self
.simple_success_keyword("failure:")
680 def test_simple_success(self
):
681 self
.simple_success_keyword("successful")
683 def test_simple_success_colon(self
):
684 self
.simple_success_keyword("successful:")
686 def assertSuccess(self
, details
):
688 ('startTest', self
.test
),
689 ('addSuccess', self
.test
, details
),
690 ('stopTest', self
.test
),
691 ], self
.client
._events
)
693 def test_success_empty_message(self
):
694 self
.protocol
.lineReceived("success mcdonalds farm [\n")
695 self
.protocol
.lineReceived("]\n")
697 details
['message'] = Content(ContentType("text", "plain"),
699 self
.assertSuccess(details
)
701 def success_quoted_bracket(self
, keyword
):
702 # This tests it is accepted, but cannot test it is used today, because
703 # of not having a way to expose it in Python so far.
704 self
.protocol
.lineReceived("%s mcdonalds farm [\n" % keyword
)
705 self
.protocol
.lineReceived(" ]\n")
706 self
.protocol
.lineReceived("]\n")
708 details
['message'] = Content(ContentType("text", "plain"),
710 self
.assertSuccess(details
)
712 def test_success_quoted_bracket(self
):
713 self
.success_quoted_bracket("success")
715 def test_success_colon_quoted_bracket(self
):
716 self
.success_quoted_bracket("success:")
719 class TestTestProtocolServerProgress(unittest
.TestCase
):
720 """Test receipt of progress: directives."""
722 def test_progress_accepted_stdlib(self
):
723 self
.result
= Python26TestResult()
724 self
.stream
= StringIO()
725 self
.protocol
= subunit
.TestProtocolServer(self
.result
,
727 self
.protocol
.lineReceived("progress: 23")
728 self
.protocol
.lineReceived("progress: -2")
729 self
.protocol
.lineReceived("progress: +4")
730 self
.assertEqual("", self
.stream
.getvalue())
732 def test_progress_accepted_extended(self
):
733 # With a progress capable TestResult, progress events are emitted.
734 self
.result
= ExtendedTestResult()
735 self
.stream
= StringIO()
736 self
.protocol
= subunit
.TestProtocolServer(self
.result
,
738 self
.protocol
.lineReceived("progress: 23")
739 self
.protocol
.lineReceived("progress: push")
740 self
.protocol
.lineReceived("progress: -2")
741 self
.protocol
.lineReceived("progress: pop")
742 self
.protocol
.lineReceived("progress: +4")
743 self
.assertEqual("", self
.stream
.getvalue())
745 ('progress', 23, subunit
.PROGRESS_SET
),
746 ('progress', None, subunit
.PROGRESS_PUSH
),
747 ('progress', -2, subunit
.PROGRESS_CUR
),
748 ('progress', None, subunit
.PROGRESS_POP
),
749 ('progress', 4, subunit
.PROGRESS_CUR
),
750 ], self
.result
._events
)
753 class TestTestProtocolServerStreamTags(unittest
.TestCase
):
754 """Test managing tags on the protocol level."""
757 self
.client
= ExtendedTestResult()
758 self
.protocol
= subunit
.TestProtocolServer(self
.client
)
760 def test_initial_tags(self
):
761 self
.protocol
.lineReceived("tags: foo bar:baz quux\n")
763 ('tags', set(["foo", "bar:baz", "quux"]), set()),
764 ], self
.client
._events
)
766 def test_minus_removes_tags(self
):
767 self
.protocol
.lineReceived("tags: -bar quux\n")
769 ('tags', set(["quux"]), set(["bar"])),
770 ], self
.client
._events
)
772 def test_tags_do_not_get_set_on_test(self
):
773 self
.protocol
.lineReceived("test mcdonalds farm\n")
774 test
= self
.client
._events
[0][-1]
775 self
.assertEqual(None, getattr(test
, 'tags', None))
777 def test_tags_do_not_get_set_on_global_tags(self
):
778 self
.protocol
.lineReceived("tags: foo bar\n")
779 self
.protocol
.lineReceived("test mcdonalds farm\n")
780 test
= self
.client
._events
[-1][-1]
781 self
.assertEqual(None, getattr(test
, 'tags', None))
783 def test_tags_get_set_on_test_tags(self
):
784 self
.protocol
.lineReceived("test mcdonalds farm\n")
785 test
= self
.client
._events
[-1][-1]
786 self
.protocol
.lineReceived("tags: foo bar\n")
787 self
.protocol
.lineReceived("success mcdonalds farm\n")
788 self
.assertEqual(None, getattr(test
, 'tags', None))
791 class TestTestProtocolServerStreamTime(unittest
.TestCase
):
792 """Test managing time information at the protocol level."""
794 def test_time_accepted_stdlib(self
):
795 self
.result
= Python26TestResult()
796 self
.stream
= StringIO()
797 self
.protocol
= subunit
.TestProtocolServer(self
.result
,
799 self
.protocol
.lineReceived("time: 2001-12-12 12:59:59Z\n")
800 self
.assertEqual("", self
.stream
.getvalue())
802 def test_time_accepted_extended(self
):
803 self
.result
= ExtendedTestResult()
804 self
.stream
= StringIO()
805 self
.protocol
= subunit
.TestProtocolServer(self
.result
,
807 self
.protocol
.lineReceived("time: 2001-12-12 12:59:59Z\n")
808 self
.assertEqual("", self
.stream
.getvalue())
810 ('time', datetime
.datetime(2001, 12, 12, 12, 59, 59, 0,
812 ], self
.result
._events
)
815 class TestRemotedTestCase(unittest
.TestCase
):
817 def test_simple(self
):
818 test
= subunit
.RemotedTestCase("A test description")
819 self
.assertRaises(NotImplementedError, test
.setUp
)
820 self
.assertRaises(NotImplementedError, test
.tearDown
)
821 self
.assertEqual("A test description",
822 test
.shortDescription())
823 self
.assertEqual("A test description",
825 self
.assertEqual("A test description (subunit.RemotedTestCase)", "%s" % test
)
826 self
.assertEqual("<subunit.RemotedTestCase description="
827 "'A test description'>", "%r" % test
)
828 result
= unittest
.TestResult()
830 self
.assertEqual([(test
, _remote_exception_str
+ ": "
831 "Cannot run RemotedTestCases.\n\n")],
833 self
.assertEqual(1, result
.testsRun
)
834 another_test
= subunit
.RemotedTestCase("A test description")
835 self
.assertEqual(test
, another_test
)
836 different_test
= subunit
.RemotedTestCase("ofo")
837 self
.assertNotEqual(test
, different_test
)
838 self
.assertNotEqual(another_test
, different_test
)
841 class TestRemoteError(unittest
.TestCase
):
844 error
= subunit
.RemoteError("Something went wrong")
845 another_error
= subunit
.RemoteError("Something went wrong")
846 different_error
= subunit
.RemoteError("boo!")
847 self
.assertEqual(error
, another_error
)
848 self
.assertNotEqual(error
, different_error
)
849 self
.assertNotEqual(different_error
, another_error
)
851 def test_empty_constructor(self
):
852 self
.assertEqual(subunit
.RemoteError(), subunit
.RemoteError(""))
855 class TestExecTestCase(unittest
.TestCase
):
857 class SampleExecTestCase(subunit
.ExecTestCase
):
859 def test_sample_method(self
):
860 """sample-script.py"""
861 # the sample script runs three tests, one each
862 # that fails, errors and succeeds
864 def test_sample_method_args(self
):
865 """sample-script.py foo"""
866 # sample that will run just one test.
868 def test_construct(self
):
869 test
= self
.SampleExecTestCase("test_sample_method")
870 self
.assertEqual(test
.script
,
871 subunit
.join_dir(__file__
, 'sample-script.py'))
874 result
= unittest
.TestResult()
875 test
= self
.SampleExecTestCase("test_sample_method_args")
877 self
.assertEqual(1, result
.testsRun
)
880 result
= ExtendedTestResult()
881 test
= self
.SampleExecTestCase("test_sample_method")
883 mcdonald
= subunit
.RemotedTestCase("old mcdonald")
884 bing
= subunit
.RemotedTestCase("bing crosby")
886 bing_details
['traceback'] = Content(ContentType("text", "x-traceback"),
887 lambda:["foo.c:53:ERROR invalid state\n"])
888 an_error
= subunit
.RemotedTestCase("an error")
891 ('startTest', mcdonald
),
892 ('addSuccess', mcdonald
),
893 ('stopTest', mcdonald
),
895 ('addFailure', bing
, bing_details
),
897 ('startTest', an_error
),
898 ('addError', an_error
, error_details
),
899 ('stopTest', an_error
),
902 def test_debug(self
):
903 test
= self
.SampleExecTestCase("test_sample_method")
906 def test_count_test_cases(self
):
907 """TODO run the child process and count responses to determine the count."""
909 def test_join_dir(self
):
910 sibling
= subunit
.join_dir(__file__
, 'foo')
911 expected
= '%s/foo' % (os
.path
.split(__file__
)[0],)
912 self
.assertEqual(sibling
, expected
)
915 class DoExecTestCase(subunit
.ExecTestCase
):
917 def test_working_script(self
):
918 """sample-two-script.py"""
921 class TestIsolatedTestCase(unittest
.TestCase
):
923 class SampleIsolatedTestCase(subunit
.IsolatedTestCase
):
930 TestIsolatedTestCase
.SampleIsolatedTestCase
.SETUP
= True
933 TestIsolatedTestCase
.SampleIsolatedTestCase
.TEARDOWN
= True
935 def test_sets_global_state(self
):
936 TestIsolatedTestCase
.SampleIsolatedTestCase
.TEST
= True
939 def test_construct(self
):
940 test
= self
.SampleIsolatedTestCase("test_sets_global_state")
943 result
= unittest
.TestResult()
944 test
= self
.SampleIsolatedTestCase("test_sets_global_state")
946 self
.assertEqual(result
.testsRun
, 1)
947 self
.assertEqual(self
.SampleIsolatedTestCase
.SETUP
, False)
948 self
.assertEqual(self
.SampleIsolatedTestCase
.TEARDOWN
, False)
949 self
.assertEqual(self
.SampleIsolatedTestCase
.TEST
, False)
951 def test_debug(self
):
953 #test = self.SampleExecTestCase("test_sample_method")
957 class TestIsolatedTestSuite(unittest
.TestCase
):
959 class SampleTestToIsolate(unittest
.TestCase
):
966 TestIsolatedTestSuite
.SampleTestToIsolate
.SETUP
= True
969 TestIsolatedTestSuite
.SampleTestToIsolate
.TEARDOWN
= True
971 def test_sets_global_state(self
):
972 TestIsolatedTestSuite
.SampleTestToIsolate
.TEST
= True
975 def test_construct(self
):
976 suite
= subunit
.IsolatedTestSuite()
979 result
= unittest
.TestResult()
980 suite
= subunit
.IsolatedTestSuite()
981 sub_suite
= unittest
.TestSuite()
982 sub_suite
.addTest(self
.SampleTestToIsolate("test_sets_global_state"))
983 sub_suite
.addTest(self
.SampleTestToIsolate("test_sets_global_state"))
984 suite
.addTest(sub_suite
)
985 suite
.addTest(self
.SampleTestToIsolate("test_sets_global_state"))
987 self
.assertEqual(result
.testsRun
, 3)
988 self
.assertEqual(self
.SampleTestToIsolate
.SETUP
, False)
989 self
.assertEqual(self
.SampleTestToIsolate
.TEARDOWN
, False)
990 self
.assertEqual(self
.SampleTestToIsolate
.TEST
, False)
993 class TestTestProtocolClient(unittest
.TestCase
):
997 self
.protocol
= subunit
.TestProtocolClient(self
.io
)
998 self
.test
= TestTestProtocolClient("test_start_test")
999 self
.sample_details
= {'something':Content(
1000 ContentType('text', 'plain'), lambda:['serialised\nform'])}
1001 self
.sample_tb_details
= dict(self
.sample_details
)
1002 self
.sample_tb_details
['traceback'] = TracebackContent(
1003 subunit
.RemoteError("boo qux"), self
.test
)
1005 def test_start_test(self
):
1006 """Test startTest on a TestProtocolClient."""
1007 self
.protocol
.startTest(self
.test
)
1008 self
.assertEqual(self
.io
.getvalue(), "test: %s\n" % self
.test
.id())
1010 def test_stop_test(self
):
1011 # stopTest doesn't output anything.
1012 self
.protocol
.stopTest(self
.test
)
1013 self
.assertEqual(self
.io
.getvalue(), "")
1015 def test_add_success(self
):
1016 """Test addSuccess on a TestProtocolClient."""
1017 self
.protocol
.addSuccess(self
.test
)
1019 self
.io
.getvalue(), "successful: %s\n" % self
.test
.id())
1021 def test_add_success_details(self
):
1022 """Test addSuccess on a TestProtocolClient with details."""
1023 self
.protocol
.addSuccess(self
.test
, details
=self
.sample_details
)
1025 self
.io
.getvalue(), "successful: %s [ multipart\n"
1026 "Content-Type: text/plain\n"
1028 "F\r\nserialised\nform0\r\n]\n" % self
.test
.id())
1030 def test_add_failure(self
):
1031 """Test addFailure on a TestProtocolClient."""
1032 self
.protocol
.addFailure(
1033 self
.test
, subunit
.RemoteError("boo qux"))
1036 ('failure: %s [\n' + _remote_exception_str
+ ': boo qux\n]\n')
1039 def test_add_failure_details(self
):
1040 """Test addFailure on a TestProtocolClient with details."""
1041 self
.protocol
.addFailure(
1042 self
.test
, details
=self
.sample_tb_details
)
1045 ("failure: %s [ multipart\n"
1046 "Content-Type: text/plain\n"
1048 "F\r\nserialised\nform0\r\n"
1049 "Content-Type: text/x-traceback;charset=utf8,language=python\n"
1051 "1A\r\n" + _remote_exception_str
+ ": boo qux\n0\r\n"
1052 "]\n") % self
.test
.id())
1054 def test_add_error(self
):
1055 """Test stopTest on a TestProtocolClient."""
1056 self
.protocol
.addError(
1057 self
.test
, subunit
.RemoteError("phwoar crikey"))
1061 _remote_exception_str
+ ": phwoar crikey\n"
1062 "]\n") % self
.test
.id())
1064 def test_add_error_details(self
):
1065 """Test stopTest on a TestProtocolClient with details."""
1066 self
.protocol
.addError(
1067 self
.test
, details
=self
.sample_tb_details
)
1070 ("error: %s [ multipart\n"
1071 "Content-Type: text/plain\n"
1073 "F\r\nserialised\nform0\r\n"
1074 "Content-Type: text/x-traceback;charset=utf8,language=python\n"
1076 "1A\r\n" + _remote_exception_str
+ ": boo qux\n0\r\n"
1077 "]\n") % self
.test
.id())
1079 def test_add_expected_failure(self
):
1080 """Test addExpectedFailure on a TestProtocolClient."""
1081 self
.protocol
.addExpectedFailure(
1082 self
.test
, subunit
.RemoteError("phwoar crikey"))
1086 _remote_exception_str
+ ": phwoar crikey\n"
1087 "]\n") % self
.test
.id())
1089 def test_add_expected_failure_details(self
):
1090 """Test addExpectedFailure on a TestProtocolClient with details."""
1091 self
.protocol
.addExpectedFailure(
1092 self
.test
, details
=self
.sample_tb_details
)
1095 ("xfail: %s [ multipart\n"
1096 "Content-Type: text/plain\n"
1098 "F\r\nserialised\nform0\r\n"
1099 "Content-Type: text/x-traceback;charset=utf8,language=python\n"
1101 "1A\r\n"+ _remote_exception_str
+ ": boo qux\n0\r\n"
1102 "]\n") % self
.test
.id())
1104 def test_add_skip(self
):
1105 """Test addSkip on a TestProtocolClient."""
1106 self
.protocol
.addSkip(
1107 self
.test
, "Has it really?")
1110 'skip: %s [\nHas it really?\n]\n' % self
.test
.id())
1112 def test_add_skip_details(self
):
1113 """Test addSkip on a TestProtocolClient with details."""
1114 details
= {'reason':Content(
1115 ContentType('text', 'plain'), lambda:['Has it really?'])}
1116 self
.protocol
.addSkip(
1117 self
.test
, details
=details
)
1120 "skip: %s [ multipart\n"
1121 "Content-Type: text/plain\n"
1123 "E\r\nHas it really?0\r\n"
1124 "]\n" % self
.test
.id())
1126 def test_progress_set(self
):
1127 self
.protocol
.progress(23, subunit
.PROGRESS_SET
)
1128 self
.assertEqual(self
.io
.getvalue(), 'progress: 23\n')
1130 def test_progress_neg_cur(self
):
1131 self
.protocol
.progress(-23, subunit
.PROGRESS_CUR
)
1132 self
.assertEqual(self
.io
.getvalue(), 'progress: -23\n')
1134 def test_progress_pos_cur(self
):
1135 self
.protocol
.progress(23, subunit
.PROGRESS_CUR
)
1136 self
.assertEqual(self
.io
.getvalue(), 'progress: +23\n')
1138 def test_progress_pop(self
):
1139 self
.protocol
.progress(1234, subunit
.PROGRESS_POP
)
1140 self
.assertEqual(self
.io
.getvalue(), 'progress: pop\n')
1142 def test_progress_push(self
):
1143 self
.protocol
.progress(1234, subunit
.PROGRESS_PUSH
)
1144 self
.assertEqual(self
.io
.getvalue(), 'progress: push\n')
1146 def test_time(self
):
1147 # Calling time() outputs a time signal immediately.
1149 datetime
.datetime(2009,10,11,12,13,14,15, iso8601
.Utc()))
1151 "time: 2009-10-11 12:13:14.000015Z\n",
1154 def test_add_unexpected_success(self
):
1155 """Test addUnexpectedSuccess on a TestProtocolClient."""
1156 self
.protocol
.addUnexpectedSuccess(self
.test
)
1158 self
.io
.getvalue(), "successful: %s\n" % self
.test
.id())
1160 def test_add_unexpected_success_details(self
):
1161 """Test addUnexpectedSuccess on a TestProtocolClient with details."""
1162 self
.protocol
.addUnexpectedSuccess(self
.test
, details
=self
.sample_details
)
1164 self
.io
.getvalue(), "successful: %s [ multipart\n"
1165 "Content-Type: text/plain\n"
1167 "F\r\nserialised\nform0\r\n]\n" % self
.test
.id())
1171 loader
= subunit
.tests
.TestUtil
.TestLoader()
1172 result
= loader
.loadTestsFromName(__name__
)