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.
21
from testtools import skipIf, TestCase
22
from testtools.compat import _b, _u, BytesIO, 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, _remote_exception_str_chunked
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 = BytesIO(_b("test old mcdonald\n"
62
"success old mcdonald\n"))
63
protocol.readFrom(pipe)
64
self.assertEqual(client.testsRun, 1)
65
self.assertEqual(pipe.getvalue(), out.getvalue())
67
def test_not_command(self):
68
client = unittest.TestResult()
70
protocol = subunit.TestProtocolServer(client,
71
stream=subunit.DiscardStream(), forward_stream=out)
72
pipe = BytesIO(_b("success old mcdonald\n"))
73
protocol.readFrom(pipe)
74
self.assertEqual(client.testsRun, 0)
75
self.assertEqual(_b(""), out.getvalue())
78
class TestTestProtocolServerPipe(unittest.TestCase):
81
client = unittest.TestResult()
82
protocol = subunit.TestProtocolServer(client)
83
pipe = BytesIO(_b("test old mcdonald\n"
84
"success old mcdonald\n"
86
"failure bing crosby [\n"
87
"foo.c:53:ERROR invalid state\n"
91
protocol.readFrom(pipe)
92
bing = subunit.RemotedTestCase("bing crosby")
93
an_error = subunit.RemotedTestCase("an error")
94
self.assertEqual(client.errors,
95
[(an_error, _remote_exception_str + '\n')])
98
[(bing, _remote_exception_str + ": Text attachment: traceback\n"
99
"------------\nfoo.c:53:ERROR invalid state\n"
100
"------------\n\n")])
101
self.assertEqual(client.testsRun, 3)
103
def test_non_test_characters_forwarded_immediately(self):
107
class TestTestProtocolServerStartTest(unittest.TestCase):
110
self.client = Python26TestResult()
111
self.stream = BytesIO()
112
self.protocol = subunit.TestProtocolServer(self.client, self.stream)
114
def test_start_test(self):
115
self.protocol.lineReceived(_b("test old mcdonald\n"))
116
self.assertEqual(self.client._events,
117
[('startTest', subunit.RemotedTestCase("old mcdonald"))])
119
def test_start_testing(self):
120
self.protocol.lineReceived(_b("testing old mcdonald\n"))
121
self.assertEqual(self.client._events,
122
[('startTest', subunit.RemotedTestCase("old mcdonald"))])
124
def test_start_test_colon(self):
125
self.protocol.lineReceived(_b("test: old mcdonald\n"))
126
self.assertEqual(self.client._events,
127
[('startTest', subunit.RemotedTestCase("old mcdonald"))])
129
def test_indented_test_colon_ignored(self):
130
ignored_line = _b(" test: old mcdonald\n")
131
self.protocol.lineReceived(ignored_line)
132
self.assertEqual([], self.client._events)
133
self.assertEqual(self.stream.getvalue(), ignored_line)
135
def test_start_testing_colon(self):
136
self.protocol.lineReceived(_b("testing: old mcdonald\n"))
137
self.assertEqual(self.client._events,
138
[('startTest', subunit.RemotedTestCase("old mcdonald"))])
141
class TestTestProtocolServerPassThrough(unittest.TestCase):
144
self.stdout = BytesIO()
145
self.test = subunit.RemotedTestCase("old mcdonald")
146
self.client = ExtendedTestResult()
147
self.protocol = subunit.TestProtocolServer(self.client, self.stdout)
149
def keywords_before_test(self):
150
self.protocol.lineReceived(_b("failure a\n"))
151
self.protocol.lineReceived(_b("failure: a\n"))
152
self.protocol.lineReceived(_b("error a\n"))
153
self.protocol.lineReceived(_b("error: a\n"))
154
self.protocol.lineReceived(_b("success a\n"))
155
self.protocol.lineReceived(_b("success: a\n"))
156
self.protocol.lineReceived(_b("successful a\n"))
157
self.protocol.lineReceived(_b("successful: a\n"))
158
self.protocol.lineReceived(_b("]\n"))
159
self.assertEqual(self.stdout.getvalue(), _b("failure a\n"
169
def test_keywords_before_test(self):
170
self.keywords_before_test()
171
self.assertEqual(self.client._events, [])
173
def test_keywords_after_error(self):
174
self.protocol.lineReceived(_b("test old mcdonald\n"))
175
self.protocol.lineReceived(_b("error old mcdonald\n"))
176
self.keywords_before_test()
178
('startTest', self.test),
179
('addError', self.test, {}),
180
('stopTest', self.test),
181
], self.client._events)
183
def test_keywords_after_failure(self):
184
self.protocol.lineReceived(_b("test old mcdonald\n"))
185
self.protocol.lineReceived(_b("failure old mcdonald\n"))
186
self.keywords_before_test()
187
self.assertEqual(self.client._events, [
188
('startTest', self.test),
189
('addFailure', self.test, {}),
190
('stopTest', self.test),
193
def test_keywords_after_success(self):
194
self.protocol.lineReceived(_b("test old mcdonald\n"))
195
self.protocol.lineReceived(_b("success old mcdonald\n"))
196
self.keywords_before_test()
198
('startTest', self.test),
199
('addSuccess', self.test),
200
('stopTest', self.test),
201
], self.client._events)
203
def test_keywords_after_test(self):
204
self.protocol.lineReceived(_b("test old mcdonald\n"))
205
self.protocol.lineReceived(_b("test old mcdonald\n"))
206
self.protocol.lineReceived(_b("failure a\n"))
207
self.protocol.lineReceived(_b("failure: a\n"))
208
self.protocol.lineReceived(_b("error a\n"))
209
self.protocol.lineReceived(_b("error: a\n"))
210
self.protocol.lineReceived(_b("success a\n"))
211
self.protocol.lineReceived(_b("success: a\n"))
212
self.protocol.lineReceived(_b("successful a\n"))
213
self.protocol.lineReceived(_b("successful: a\n"))
214
self.protocol.lineReceived(_b("]\n"))
215
self.protocol.lineReceived(_b("failure old mcdonald\n"))
216
self.assertEqual(self.stdout.getvalue(), _b("test old mcdonald\n"
226
self.assertEqual(self.client._events, [
227
('startTest', self.test),
228
('addFailure', self.test, {}),
229
('stopTest', self.test),
232
def test_keywords_during_failure(self):
233
# A smoke test to make sure that the details parsers have control
235
self.protocol.lineReceived(_b("test old mcdonald\n"))
236
self.protocol.lineReceived(_b("failure: old mcdonald [\n"))
237
self.protocol.lineReceived(_b("test old mcdonald\n"))
238
self.protocol.lineReceived(_b("failure a\n"))
239
self.protocol.lineReceived(_b("failure: a\n"))
240
self.protocol.lineReceived(_b("error a\n"))
241
self.protocol.lineReceived(_b("error: a\n"))
242
self.protocol.lineReceived(_b("success a\n"))
243
self.protocol.lineReceived(_b("success: a\n"))
244
self.protocol.lineReceived(_b("successful a\n"))
245
self.protocol.lineReceived(_b("successful: a\n"))
246
self.protocol.lineReceived(_b(" ]\n"))
247
self.protocol.lineReceived(_b("]\n"))
248
self.assertEqual(self.stdout.getvalue(), _b(""))
250
details['traceback'] = Content(ContentType("text", "x-traceback",
251
{'charset': 'utf8'}),
253
"test old mcdonald\n"
263
self.assertEqual(self.client._events, [
264
('startTest', self.test),
265
('addFailure', self.test, details),
266
('stopTest', self.test),
269
def test_stdout_passthrough(self):
270
"""Lines received which cannot be interpreted as any protocol action
271
should be passed through to sys.stdout.
273
bytes = _b("randombytes\n")
274
self.protocol.lineReceived(bytes)
275
self.assertEqual(self.stdout.getvalue(), bytes)
278
class TestTestProtocolServerLostConnection(unittest.TestCase):
281
self.client = Python26TestResult()
282
self.protocol = subunit.TestProtocolServer(self.client)
283
self.test = subunit.RemotedTestCase("old mcdonald")
285
def test_lost_connection_no_input(self):
286
self.protocol.lostConnection()
287
self.assertEqual([], self.client._events)
289
def test_lost_connection_after_start(self):
290
self.protocol.lineReceived(_b("test old mcdonald\n"))
291
self.protocol.lostConnection()
292
failure = subunit.RemoteError(
293
_u("lost connection during test 'old mcdonald'"))
295
('startTest', self.test),
296
('addError', self.test, failure),
297
('stopTest', self.test),
298
], self.client._events)
300
def test_lost_connected_after_error(self):
301
self.protocol.lineReceived(_b("test old mcdonald\n"))
302
self.protocol.lineReceived(_b("error old mcdonald\n"))
303
self.protocol.lostConnection()
305
('startTest', self.test),
306
('addError', self.test, subunit.RemoteError(_u(""))),
307
('stopTest', self.test),
308
], self.client._events)
310
def do_connection_lost(self, outcome, opening):
311
self.protocol.lineReceived(_b("test old mcdonald\n"))
312
self.protocol.lineReceived(_b("%s old mcdonald %s" % (outcome, opening)))
313
self.protocol.lostConnection()
314
failure = subunit.RemoteError(
315
_u("lost connection during %s report of test 'old mcdonald'") %
318
('startTest', self.test),
319
('addError', self.test, failure),
320
('stopTest', self.test),
321
], self.client._events)
323
def test_lost_connection_during_error(self):
324
self.do_connection_lost("error", "[\n")
326
def test_lost_connection_during_error_details(self):
327
self.do_connection_lost("error", "[ multipart\n")
329
def test_lost_connected_after_failure(self):
330
self.protocol.lineReceived(_b("test old mcdonald\n"))
331
self.protocol.lineReceived(_b("failure old mcdonald\n"))
332
self.protocol.lostConnection()
334
('startTest', self.test),
335
('addFailure', self.test, subunit.RemoteError(_u(""))),
336
('stopTest', self.test),
337
], self.client._events)
339
def test_lost_connection_during_failure(self):
340
self.do_connection_lost("failure", "[\n")
342
def test_lost_connection_during_failure_details(self):
343
self.do_connection_lost("failure", "[ multipart\n")
345
def test_lost_connection_after_success(self):
346
self.protocol.lineReceived(_b("test old mcdonald\n"))
347
self.protocol.lineReceived(_b("success old mcdonald\n"))
348
self.protocol.lostConnection()
350
('startTest', self.test),
351
('addSuccess', self.test),
352
('stopTest', self.test),
353
], self.client._events)
355
def test_lost_connection_during_success(self):
356
self.do_connection_lost("success", "[\n")
358
def test_lost_connection_during_success_details(self):
359
self.do_connection_lost("success", "[ multipart\n")
361
def test_lost_connection_during_skip(self):
362
self.do_connection_lost("skip", "[\n")
364
def test_lost_connection_during_skip_details(self):
365
self.do_connection_lost("skip", "[ multipart\n")
367
def test_lost_connection_during_xfail(self):
368
self.do_connection_lost("xfail", "[\n")
370
def test_lost_connection_during_xfail_details(self):
371
self.do_connection_lost("xfail", "[ multipart\n")
373
def test_lost_connection_during_uxsuccess(self):
374
self.do_connection_lost("uxsuccess", "[\n")
376
def test_lost_connection_during_uxsuccess_details(self):
377
self.do_connection_lost("uxsuccess", "[ multipart\n")
380
class TestInTestMultipart(unittest.TestCase):
383
self.client = ExtendedTestResult()
384
self.protocol = subunit.TestProtocolServer(self.client)
385
self.protocol.lineReceived(_b("test mcdonalds farm\n"))
386
self.test = subunit.RemotedTestCase(_u("mcdonalds farm"))
388
def test__outcome_sets_details_parser(self):
389
self.protocol._reading_success_details.details_parser = None
390
self.protocol._state._outcome(0, _b("mcdonalds farm [ multipart\n"),
391
None, self.protocol._reading_success_details)
392
parser = self.protocol._reading_success_details.details_parser
393
self.assertNotEqual(None, parser)
394
self.assertTrue(isinstance(parser,
395
subunit.details.MultipartDetailsParser))
398
class TestTestProtocolServerAddError(unittest.TestCase):
401
self.client = ExtendedTestResult()
402
self.protocol = subunit.TestProtocolServer(self.client)
403
self.protocol.lineReceived(_b("test mcdonalds farm\n"))
404
self.test = subunit.RemotedTestCase("mcdonalds farm")
406
def simple_error_keyword(self, keyword):
407
self.protocol.lineReceived(_b("%s mcdonalds farm\n" % keyword))
410
('startTest', self.test),
411
('addError', self.test, details),
412
('stopTest', self.test),
413
], self.client._events)
415
def test_simple_error(self):
416
self.simple_error_keyword("error")
418
def test_simple_error_colon(self):
419
self.simple_error_keyword("error:")
421
def test_error_empty_message(self):
422
self.protocol.lineReceived(_b("error mcdonalds farm [\n"))
423
self.protocol.lineReceived(_b("]\n"))
425
details['traceback'] = Content(ContentType("text", "x-traceback",
426
{'charset': 'utf8'}), lambda:[_b("")])
428
('startTest', self.test),
429
('addError', self.test, details),
430
('stopTest', self.test),
431
], self.client._events)
433
def error_quoted_bracket(self, keyword):
434
self.protocol.lineReceived(_b("%s mcdonalds farm [\n" % keyword))
435
self.protocol.lineReceived(_b(" ]\n"))
436
self.protocol.lineReceived(_b("]\n"))
438
details['traceback'] = Content(ContentType("text", "x-traceback",
439
{'charset': 'utf8'}), lambda:[_b("]\n")])
441
('startTest', self.test),
442
('addError', self.test, details),
443
('stopTest', self.test),
444
], self.client._events)
446
def test_error_quoted_bracket(self):
447
self.error_quoted_bracket("error")
449
def test_error_colon_quoted_bracket(self):
450
self.error_quoted_bracket("error:")
453
class TestTestProtocolServerAddFailure(unittest.TestCase):
456
self.client = ExtendedTestResult()
457
self.protocol = subunit.TestProtocolServer(self.client)
458
self.protocol.lineReceived(_b("test mcdonalds farm\n"))
459
self.test = subunit.RemotedTestCase("mcdonalds farm")
461
def assertFailure(self, details):
463
('startTest', self.test),
464
('addFailure', self.test, details),
465
('stopTest', self.test),
466
], self.client._events)
468
def simple_failure_keyword(self, keyword):
469
self.protocol.lineReceived(_b("%s mcdonalds farm\n" % keyword))
471
self.assertFailure(details)
473
def test_simple_failure(self):
474
self.simple_failure_keyword("failure")
476
def test_simple_failure_colon(self):
477
self.simple_failure_keyword("failure:")
479
def test_failure_empty_message(self):
480
self.protocol.lineReceived(_b("failure mcdonalds farm [\n"))
481
self.protocol.lineReceived(_b("]\n"))
483
details['traceback'] = Content(ContentType("text", "x-traceback",
484
{'charset': 'utf8'}), lambda:[_b("")])
485
self.assertFailure(details)
487
def failure_quoted_bracket(self, keyword):
488
self.protocol.lineReceived(_b("%s mcdonalds farm [\n" % keyword))
489
self.protocol.lineReceived(_b(" ]\n"))
490
self.protocol.lineReceived(_b("]\n"))
492
details['traceback'] = Content(ContentType("text", "x-traceback",
493
{'charset': 'utf8'}), lambda:[_b("]\n")])
494
self.assertFailure(details)
496
def test_failure_quoted_bracket(self):
497
self.failure_quoted_bracket("failure")
499
def test_failure_colon_quoted_bracket(self):
500
self.failure_quoted_bracket("failure:")
503
class TestTestProtocolServerAddxFail(unittest.TestCase):
504
"""Tests for the xfail keyword.
506
In Python this can thunk through to Success due to stdlib limitations (see
510
def capture_expected_failure(self, test, err):
511
self._events.append((test, err))
513
def setup_python26(self):
514
"""Setup a test object ready to be xfailed and thunk to success."""
515
self.client = Python26TestResult()
516
self.setup_protocol()
518
def setup_python27(self):
519
"""Setup a test object ready to be xfailed."""
520
self.client = Python27TestResult()
521
self.setup_protocol()
523
def setup_python_ex(self):
524
"""Setup a test object ready to be xfailed with details."""
525
self.client = ExtendedTestResult()
526
self.setup_protocol()
528
def setup_protocol(self):
529
"""Setup the protocol based on self.client."""
530
self.protocol = subunit.TestProtocolServer(self.client)
531
self.protocol.lineReceived(_b("test mcdonalds farm\n"))
532
self.test = self.client._events[-1][-1]
534
def simple_xfail_keyword(self, keyword, as_success):
535
self.protocol.lineReceived(_b("%s mcdonalds farm\n" % keyword))
536
self.check_success_or_xfail(as_success)
538
def check_success_or_xfail(self, as_success, error_message=None):
541
('startTest', self.test),
542
('addSuccess', self.test),
543
('stopTest', self.test),
544
], self.client._events)
547
if error_message is not None:
548
details['traceback'] = Content(
549
ContentType("text", "x-traceback", {'charset': 'utf8'}),
550
lambda:[_b(error_message)])
551
if isinstance(self.client, ExtendedTestResult):
554
if error_message is not None:
555
value = subunit.RemoteError(_u("Text attachment: traceback\n"
556
"------------\n") + _u(error_message) +
557
_u("------------\n"))
559
value = subunit.RemoteError()
561
('startTest', self.test),
562
('addExpectedFailure', self.test, value),
563
('stopTest', self.test),
564
], self.client._events)
566
def test_simple_xfail(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_simple_xfail_colon(self):
575
self.setup_python26()
576
self.simple_xfail_keyword("xfail:", True)
577
self.setup_python27()
578
self.simple_xfail_keyword("xfail:", False)
579
self.setup_python_ex()
580
self.simple_xfail_keyword("xfail:", False)
582
def test_xfail_empty_message(self):
583
self.setup_python26()
584
self.empty_message(True)
585
self.setup_python27()
586
self.empty_message(False)
587
self.setup_python_ex()
588
self.empty_message(False, error_message="")
590
def empty_message(self, as_success, error_message="\n"):
591
self.protocol.lineReceived(_b("xfail mcdonalds farm [\n"))
592
self.protocol.lineReceived(_b("]\n"))
593
self.check_success_or_xfail(as_success, error_message)
595
def xfail_quoted_bracket(self, keyword, as_success):
596
# This tests it is accepted, but cannot test it is used today, because
597
# of not having a way to expose it in Python so far.
598
self.protocol.lineReceived(_b("%s mcdonalds farm [\n" % keyword))
599
self.protocol.lineReceived(_b(" ]\n"))
600
self.protocol.lineReceived(_b("]\n"))
601
self.check_success_or_xfail(as_success, "]\n")
603
def test_xfail_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)
611
def test_xfail_colon_quoted_bracket(self):
612
self.setup_python26()
613
self.xfail_quoted_bracket("xfail:", True)
614
self.setup_python27()
615
self.xfail_quoted_bracket("xfail:", False)
616
self.setup_python_ex()
617
self.xfail_quoted_bracket("xfail:", False)
620
class TestTestProtocolServerAddunexpectedSuccess(TestCase):
621
"""Tests for the uxsuccess keyword."""
623
def capture_expected_failure(self, test, err):
624
self._events.append((test, err))
626
def setup_python26(self):
627
"""Setup a test object ready to be xfailed and thunk to success."""
628
self.client = Python26TestResult()
629
self.setup_protocol()
631
def setup_python27(self):
632
"""Setup a test object ready to be xfailed."""
633
self.client = Python27TestResult()
634
self.setup_protocol()
636
def setup_python_ex(self):
637
"""Setup a test object ready to be xfailed with details."""
638
self.client = ExtendedTestResult()
639
self.setup_protocol()
641
def setup_protocol(self):
642
"""Setup the protocol based on self.client."""
643
self.protocol = subunit.TestProtocolServer(self.client)
644
self.protocol.lineReceived(_b("test mcdonalds farm\n"))
645
self.test = self.client._events[-1][-1]
647
def simple_uxsuccess_keyword(self, keyword, as_fail):
648
self.protocol.lineReceived(_b("%s mcdonalds farm\n" % keyword))
649
self.check_fail_or_uxsuccess(as_fail)
651
def check_fail_or_uxsuccess(self, as_fail, error_message=None):
653
if error_message is not None:
654
details['traceback'] = Content(
655
ContentType("text", "x-traceback", {'charset': 'utf8'}),
656
lambda:[_b(error_message)])
657
if isinstance(self.client, ExtendedTestResult):
662
self.client._events[1] = self.client._events[1][:2]
663
# The value is generated within the extended to original decorator:
664
# todo use the testtools matcher to check on this.
666
('startTest', self.test),
667
('addFailure', self.test),
668
('stopTest', self.test),
669
], self.client._events)
672
('startTest', self.test),
673
('addUnexpectedSuccess', self.test, value),
674
('stopTest', self.test),
675
], self.client._events)
678
('startTest', self.test),
679
('addUnexpectedSuccess', self.test),
680
('stopTest', self.test),
681
], self.client._events)
683
def test_simple_uxsuccess(self):
684
self.setup_python26()
685
self.simple_uxsuccess_keyword("uxsuccess", True)
686
self.setup_python27()
687
self.simple_uxsuccess_keyword("uxsuccess", False)
688
self.setup_python_ex()
689
self.simple_uxsuccess_keyword("uxsuccess", False)
691
def test_simple_uxsuccess_colon(self):
692
self.setup_python26()
693
self.simple_uxsuccess_keyword("uxsuccess:", True)
694
self.setup_python27()
695
self.simple_uxsuccess_keyword("uxsuccess:", False)
696
self.setup_python_ex()
697
self.simple_uxsuccess_keyword("uxsuccess:", False)
699
def test_uxsuccess_empty_message(self):
700
self.setup_python26()
701
self.empty_message(True)
702
self.setup_python27()
703
self.empty_message(False)
704
self.setup_python_ex()
705
self.empty_message(False, error_message="")
707
def empty_message(self, as_fail, error_message="\n"):
708
self.protocol.lineReceived(_b("uxsuccess mcdonalds farm [\n"))
709
self.protocol.lineReceived(_b("]\n"))
710
self.check_fail_or_uxsuccess(as_fail, error_message)
712
def uxsuccess_quoted_bracket(self, keyword, as_fail):
713
self.protocol.lineReceived(_b("%s mcdonalds farm [\n" % keyword))
714
self.protocol.lineReceived(_b(" ]\n"))
715
self.protocol.lineReceived(_b("]\n"))
716
self.check_fail_or_uxsuccess(as_fail, "]\n")
718
def test_uxsuccess_quoted_bracket(self):
719
self.setup_python26()
720
self.uxsuccess_quoted_bracket("uxsuccess", True)
721
self.setup_python27()
722
self.uxsuccess_quoted_bracket("uxsuccess", False)
723
self.setup_python_ex()
724
self.uxsuccess_quoted_bracket("uxsuccess", False)
726
def test_uxsuccess_colon_quoted_bracket(self):
727
self.setup_python26()
728
self.uxsuccess_quoted_bracket("uxsuccess:", True)
729
self.setup_python27()
730
self.uxsuccess_quoted_bracket("uxsuccess:", False)
731
self.setup_python_ex()
732
self.uxsuccess_quoted_bracket("uxsuccess:", False)
735
class TestTestProtocolServerAddSkip(unittest.TestCase):
736
"""Tests for the skip keyword.
738
In Python this meets the testtools extended TestResult contract.
739
(See https://launchpad.net/testtools).
743
"""Setup a test object ready to be skipped."""
744
self.client = ExtendedTestResult()
745
self.protocol = subunit.TestProtocolServer(self.client)
746
self.protocol.lineReceived(_b("test mcdonalds farm\n"))
747
self.test = self.client._events[-1][-1]
749
def assertSkip(self, reason):
751
if reason is not None:
752
details['reason'] = Content(
753
ContentType("text", "plain"), lambda:[reason])
755
('startTest', self.test),
756
('addSkip', self.test, details),
757
('stopTest', self.test),
758
], self.client._events)
760
def simple_skip_keyword(self, keyword):
761
self.protocol.lineReceived(_b("%s mcdonalds farm\n" % keyword))
762
self.assertSkip(None)
764
def test_simple_skip(self):
765
self.simple_skip_keyword("skip")
767
def test_simple_skip_colon(self):
768
self.simple_skip_keyword("skip:")
770
def test_skip_empty_message(self):
771
self.protocol.lineReceived(_b("skip mcdonalds farm [\n"))
772
self.protocol.lineReceived(_b("]\n"))
773
self.assertSkip(_b(""))
775
def skip_quoted_bracket(self, keyword):
776
# This tests it is accepted, but cannot test it is used today, because
777
# of not having a way to expose it in Python so far.
778
self.protocol.lineReceived(_b("%s mcdonalds farm [\n" % keyword))
779
self.protocol.lineReceived(_b(" ]\n"))
780
self.protocol.lineReceived(_b("]\n"))
781
self.assertSkip(_b("]\n"))
783
def test_skip_quoted_bracket(self):
784
self.skip_quoted_bracket("skip")
786
def test_skip_colon_quoted_bracket(self):
787
self.skip_quoted_bracket("skip:")
790
class TestTestProtocolServerAddSuccess(unittest.TestCase):
793
self.client = ExtendedTestResult()
794
self.protocol = subunit.TestProtocolServer(self.client)
795
self.protocol.lineReceived(_b("test mcdonalds farm\n"))
796
self.test = subunit.RemotedTestCase("mcdonalds farm")
798
def simple_success_keyword(self, keyword):
799
self.protocol.lineReceived(_b("%s mcdonalds farm\n" % keyword))
801
('startTest', self.test),
802
('addSuccess', self.test),
803
('stopTest', self.test),
804
], self.client._events)
806
def test_simple_success(self):
807
self.simple_success_keyword("successful")
809
def test_simple_success_colon(self):
810
self.simple_success_keyword("successful:")
812
def assertSuccess(self, details):
814
('startTest', self.test),
815
('addSuccess', self.test, details),
816
('stopTest', self.test),
817
], self.client._events)
819
def test_success_empty_message(self):
820
self.protocol.lineReceived(_b("success mcdonalds farm [\n"))
821
self.protocol.lineReceived(_b("]\n"))
823
details['message'] = Content(ContentType("text", "plain"),
825
self.assertSuccess(details)
827
def success_quoted_bracket(self, keyword):
828
# This tests it is accepted, but cannot test it is used today, because
829
# of not having a way to expose it in Python so far.
830
self.protocol.lineReceived(_b("%s mcdonalds farm [\n" % keyword))
831
self.protocol.lineReceived(_b(" ]\n"))
832
self.protocol.lineReceived(_b("]\n"))
834
details['message'] = Content(ContentType("text", "plain"),
836
self.assertSuccess(details)
838
def test_success_quoted_bracket(self):
839
self.success_quoted_bracket("success")
841
def test_success_colon_quoted_bracket(self):
842
self.success_quoted_bracket("success:")
845
class TestTestProtocolServerProgress(unittest.TestCase):
846
"""Test receipt of progress: directives."""
848
def test_progress_accepted_stdlib(self):
849
self.result = Python26TestResult()
850
self.stream = BytesIO()
851
self.protocol = subunit.TestProtocolServer(self.result,
853
self.protocol.lineReceived(_b("progress: 23"))
854
self.protocol.lineReceived(_b("progress: -2"))
855
self.protocol.lineReceived(_b("progress: +4"))
856
self.assertEqual(_b(""), self.stream.getvalue())
858
def test_progress_accepted_extended(self):
859
# With a progress capable TestResult, progress events are emitted.
860
self.result = ExtendedTestResult()
861
self.stream = BytesIO()
862
self.protocol = subunit.TestProtocolServer(self.result,
864
self.protocol.lineReceived(_b("progress: 23"))
865
self.protocol.lineReceived(_b("progress: push"))
866
self.protocol.lineReceived(_b("progress: -2"))
867
self.protocol.lineReceived(_b("progress: pop"))
868
self.protocol.lineReceived(_b("progress: +4"))
869
self.assertEqual(_b(""), self.stream.getvalue())
871
('progress', 23, subunit.PROGRESS_SET),
872
('progress', None, subunit.PROGRESS_PUSH),
873
('progress', -2, subunit.PROGRESS_CUR),
874
('progress', None, subunit.PROGRESS_POP),
875
('progress', 4, subunit.PROGRESS_CUR),
876
], self.result._events)
879
class TestTestProtocolServerStreamTags(unittest.TestCase):
880
"""Test managing tags on the protocol level."""
883
self.client = ExtendedTestResult()
884
self.protocol = subunit.TestProtocolServer(self.client)
886
def test_initial_tags(self):
887
self.protocol.lineReceived(_b("tags: foo bar:baz quux\n"))
889
('tags', set(["foo", "bar:baz", "quux"]), set()),
890
], self.client._events)
892
def test_minus_removes_tags(self):
893
self.protocol.lineReceived(_b("tags: -bar quux\n"))
895
('tags', set(["quux"]), set(["bar"])),
896
], self.client._events)
898
def test_tags_do_not_get_set_on_test(self):
899
self.protocol.lineReceived(_b("test mcdonalds farm\n"))
900
test = self.client._events[0][-1]
901
self.assertEqual(None, getattr(test, 'tags', None))
903
def test_tags_do_not_get_set_on_global_tags(self):
904
self.protocol.lineReceived(_b("tags: foo bar\n"))
905
self.protocol.lineReceived(_b("test mcdonalds farm\n"))
906
test = self.client._events[-1][-1]
907
self.assertEqual(None, getattr(test, 'tags', None))
909
def test_tags_get_set_on_test_tags(self):
910
self.protocol.lineReceived(_b("test mcdonalds farm\n"))
911
test = self.client._events[-1][-1]
912
self.protocol.lineReceived(_b("tags: foo bar\n"))
913
self.protocol.lineReceived(_b("success mcdonalds farm\n"))
914
self.assertEqual(None, getattr(test, 'tags', None))
917
class TestTestProtocolServerStreamTime(unittest.TestCase):
918
"""Test managing time information at the protocol level."""
920
def test_time_accepted_stdlib(self):
921
self.result = Python26TestResult()
922
self.stream = BytesIO()
923
self.protocol = subunit.TestProtocolServer(self.result,
925
self.protocol.lineReceived(_b("time: 2001-12-12 12:59:59Z\n"))
926
self.assertEqual(_b(""), self.stream.getvalue())
928
def test_time_accepted_extended(self):
929
self.result = ExtendedTestResult()
930
self.stream = BytesIO()
931
self.protocol = subunit.TestProtocolServer(self.result,
933
self.protocol.lineReceived(_b("time: 2001-12-12 12:59:59Z\n"))
934
self.assertEqual(_b(""), self.stream.getvalue())
936
('time', datetime.datetime(2001, 12, 12, 12, 59, 59, 0,
938
], self.result._events)
941
class TestRemotedTestCase(unittest.TestCase):
943
def test_simple(self):
944
test = subunit.RemotedTestCase("A test description")
945
self.assertRaises(NotImplementedError, test.setUp)
946
self.assertRaises(NotImplementedError, test.tearDown)
947
self.assertEqual("A test description",
948
test.shortDescription())
949
self.assertEqual("A test description",
951
self.assertEqual("A test description (subunit.RemotedTestCase)", "%s" % test)
952
self.assertEqual("<subunit.RemotedTestCase description="
953
"'A test description'>", "%r" % test)
954
result = unittest.TestResult()
956
self.assertEqual([(test, _remote_exception_str + ": "
957
"Cannot run RemotedTestCases.\n\n")],
959
self.assertEqual(1, result.testsRun)
960
another_test = subunit.RemotedTestCase("A test description")
961
self.assertEqual(test, another_test)
962
different_test = subunit.RemotedTestCase("ofo")
963
self.assertNotEqual(test, different_test)
964
self.assertNotEqual(another_test, different_test)
967
class TestRemoteError(unittest.TestCase):
970
error = subunit.RemoteError(_u("Something went wrong"))
971
another_error = subunit.RemoteError(_u("Something went wrong"))
972
different_error = subunit.RemoteError(_u("boo!"))
973
self.assertEqual(error, another_error)
974
self.assertNotEqual(error, different_error)
975
self.assertNotEqual(different_error, another_error)
977
def test_empty_constructor(self):
978
self.assertEqual(subunit.RemoteError(), subunit.RemoteError(_u("")))
981
class TestExecTestCase(unittest.TestCase):
983
class SampleExecTestCase(subunit.ExecTestCase):
985
def test_sample_method(self):
986
"""sample-script.py"""
987
# the sample script runs three tests, one each
988
# that fails, errors and succeeds
990
def test_sample_method_args(self):
991
"""sample-script.py foo"""
992
# sample that will run just one test.
994
def test_construct(self):
995
test = self.SampleExecTestCase("test_sample_method")
996
self.assertEqual(test.script,
997
subunit.join_dir(__file__, 'sample-script.py'))
1000
result = unittest.TestResult()
1001
test = self.SampleExecTestCase("test_sample_method_args")
1003
self.assertEqual(1, result.testsRun)
1006
result = ExtendedTestResult()
1007
test = self.SampleExecTestCase("test_sample_method")
1009
mcdonald = subunit.RemotedTestCase("old mcdonald")
1010
bing = subunit.RemotedTestCase("bing crosby")
1012
bing_details['traceback'] = Content(ContentType("text", "x-traceback",
1013
{'charset': 'utf8'}), lambda:[_b("foo.c:53:ERROR invalid state\n")])
1014
an_error = subunit.RemotedTestCase("an error")
1017
('startTest', mcdonald),
1018
('addSuccess', mcdonald),
1019
('stopTest', mcdonald),
1020
('startTest', bing),
1021
('addFailure', bing, bing_details),
1023
('startTest', an_error),
1024
('addError', an_error, error_details),
1025
('stopTest', an_error),
1028
def test_debug(self):
1029
test = self.SampleExecTestCase("test_sample_method")
1032
def test_count_test_cases(self):
1033
"""TODO run the child process and count responses to determine the count."""
1035
def test_join_dir(self):
1036
sibling = subunit.join_dir(__file__, 'foo')
1037
filedir = os.path.abspath(os.path.dirname(__file__))
1038
expected = os.path.join(filedir, 'foo')
1039
self.assertEqual(sibling, expected)
1042
class DoExecTestCase(subunit.ExecTestCase):
1044
def test_working_script(self):
1045
"""sample-two-script.py"""
1048
class TestIsolatedTestCase(TestCase):
1050
class SampleIsolatedTestCase(subunit.IsolatedTestCase):
1057
TestIsolatedTestCase.SampleIsolatedTestCase.SETUP = True
1060
TestIsolatedTestCase.SampleIsolatedTestCase.TEARDOWN = True
1062
def test_sets_global_state(self):
1063
TestIsolatedTestCase.SampleIsolatedTestCase.TEST = True
1066
def test_construct(self):
1067
self.SampleIsolatedTestCase("test_sets_global_state")
1069
@skipIf(os.name != "posix", "Need a posix system for forking tests")
1071
result = unittest.TestResult()
1072
test = self.SampleIsolatedTestCase("test_sets_global_state")
1074
self.assertEqual(result.testsRun, 1)
1075
self.assertEqual(self.SampleIsolatedTestCase.SETUP, False)
1076
self.assertEqual(self.SampleIsolatedTestCase.TEARDOWN, False)
1077
self.assertEqual(self.SampleIsolatedTestCase.TEST, False)
1079
def test_debug(self):
1081
#test = self.SampleExecTestCase("test_sample_method")
1085
class TestIsolatedTestSuite(TestCase):
1087
class SampleTestToIsolate(unittest.TestCase):
1094
TestIsolatedTestSuite.SampleTestToIsolate.SETUP = True
1097
TestIsolatedTestSuite.SampleTestToIsolate.TEARDOWN = True
1099
def test_sets_global_state(self):
1100
TestIsolatedTestSuite.SampleTestToIsolate.TEST = True
1103
def test_construct(self):
1104
subunit.IsolatedTestSuite()
1106
@skipIf(os.name != "posix", "Need a posix system for forking tests")
1108
result = unittest.TestResult()
1109
suite = subunit.IsolatedTestSuite()
1110
sub_suite = unittest.TestSuite()
1111
sub_suite.addTest(self.SampleTestToIsolate("test_sets_global_state"))
1112
sub_suite.addTest(self.SampleTestToIsolate("test_sets_global_state"))
1113
suite.addTest(sub_suite)
1114
suite.addTest(self.SampleTestToIsolate("test_sets_global_state"))
1116
self.assertEqual(result.testsRun, 3)
1117
self.assertEqual(self.SampleTestToIsolate.SETUP, False)
1118
self.assertEqual(self.SampleTestToIsolate.TEARDOWN, False)
1119
self.assertEqual(self.SampleTestToIsolate.TEST, False)
1122
class TestTestProtocolClient(unittest.TestCase):
1126
self.protocol = subunit.TestProtocolClient(self.io)
1127
self.test = TestTestProtocolClient("test_start_test")
1128
self.sample_details = {'something':Content(
1129
ContentType('text', 'plain'), lambda:[_b('serialised\nform')])}
1130
self.sample_tb_details = dict(self.sample_details)
1131
self.sample_tb_details['traceback'] = TracebackContent(
1132
subunit.RemoteError(_u("boo qux")), self.test)
1134
def test_start_test(self):
1135
"""Test startTest on a TestProtocolClient."""
1136
self.protocol.startTest(self.test)
1137
self.assertEqual(self.io.getvalue(), _b("test: %s\n" % self.test.id()))
1139
def test_stop_test(self):
1140
# stopTest doesn't output anything.
1141
self.protocol.stopTest(self.test)
1142
self.assertEqual(self.io.getvalue(), _b(""))
1144
def test_add_success(self):
1145
"""Test addSuccess on a TestProtocolClient."""
1146
self.protocol.addSuccess(self.test)
1148
self.io.getvalue(), _b("successful: %s\n" % self.test.id()))
1150
def test_add_success_details(self):
1151
"""Test addSuccess on a TestProtocolClient with details."""
1152
self.protocol.addSuccess(self.test, details=self.sample_details)
1154
self.io.getvalue(), _b("successful: %s [ multipart\n"
1155
"Content-Type: text/plain\n"
1157
"F\r\nserialised\nform0\r\n]\n" % self.test.id()))
1159
def test_add_failure(self):
1160
"""Test addFailure on a TestProtocolClient."""
1161
self.protocol.addFailure(
1162
self.test, subunit.RemoteError(_u("boo qux")))
1165
_b(('failure: %s [\n' + _remote_exception_str + ': boo qux\n]\n')
1168
def test_add_failure_details(self):
1169
"""Test addFailure on a TestProtocolClient with details."""
1170
self.protocol.addFailure(
1171
self.test, details=self.sample_tb_details)
1174
_b(("failure: %s [ multipart\n"
1175
"Content-Type: text/plain\n"
1177
"F\r\nserialised\nform0\r\n"
1178
"Content-Type: text/x-traceback;charset=utf8,language=python\n"
1179
"traceback\n" + _remote_exception_str_chunked + ": boo qux\n0\r\n"
1180
"]\n") % self.test.id()))
1182
def test_add_error(self):
1183
"""Test stopTest on a TestProtocolClient."""
1184
self.protocol.addError(
1185
self.test, subunit.RemoteError(_u("phwoar crikey")))
1188
_b(('error: %s [\n' +
1189
_remote_exception_str + ": phwoar crikey\n"
1190
"]\n") % self.test.id()))
1192
def test_add_error_details(self):
1193
"""Test stopTest on a TestProtocolClient with details."""
1194
self.protocol.addError(
1195
self.test, details=self.sample_tb_details)
1198
_b(("error: %s [ multipart\n"
1199
"Content-Type: text/plain\n"
1201
"F\r\nserialised\nform0\r\n"
1202
"Content-Type: text/x-traceback;charset=utf8,language=python\n"
1203
"traceback\n" + _remote_exception_str_chunked + ": boo qux\n0\r\n"
1204
"]\n") % self.test.id()))
1206
def test_add_expected_failure(self):
1207
"""Test addExpectedFailure on a TestProtocolClient."""
1208
self.protocol.addExpectedFailure(
1209
self.test, subunit.RemoteError(_u("phwoar crikey")))
1212
_b(('xfail: %s [\n' +
1213
_remote_exception_str + ": phwoar crikey\n"
1214
"]\n") % self.test.id()))
1216
def test_add_expected_failure_details(self):
1217
"""Test addExpectedFailure on a TestProtocolClient with details."""
1218
self.protocol.addExpectedFailure(
1219
self.test, details=self.sample_tb_details)
1222
_b(("xfail: %s [ multipart\n"
1223
"Content-Type: text/plain\n"
1225
"F\r\nserialised\nform0\r\n"
1226
"Content-Type: text/x-traceback;charset=utf8,language=python\n"
1227
"traceback\n" + _remote_exception_str_chunked + ": boo qux\n0\r\n"
1228
"]\n") % self.test.id()))
1231
def test_add_skip(self):
1232
"""Test addSkip on a TestProtocolClient."""
1233
self.protocol.addSkip(
1234
self.test, "Has it really?")
1237
_b('skip: %s [\nHas it really?\n]\n' % self.test.id()))
1239
def test_add_skip_details(self):
1240
"""Test addSkip on a TestProtocolClient with details."""
1241
details = {'reason':Content(
1242
ContentType('text', 'plain'), lambda:[_b('Has it really?')])}
1243
self.protocol.addSkip(self.test, details=details)
1246
_b("skip: %s [ multipart\n"
1247
"Content-Type: text/plain\n"
1249
"E\r\nHas it really?0\r\n"
1250
"]\n" % self.test.id()))
1252
def test_progress_set(self):
1253
self.protocol.progress(23, subunit.PROGRESS_SET)
1254
self.assertEqual(self.io.getvalue(), _b('progress: 23\n'))
1256
def test_progress_neg_cur(self):
1257
self.protocol.progress(-23, subunit.PROGRESS_CUR)
1258
self.assertEqual(self.io.getvalue(), _b('progress: -23\n'))
1260
def test_progress_pos_cur(self):
1261
self.protocol.progress(23, subunit.PROGRESS_CUR)
1262
self.assertEqual(self.io.getvalue(), _b('progress: +23\n'))
1264
def test_progress_pop(self):
1265
self.protocol.progress(1234, subunit.PROGRESS_POP)
1266
self.assertEqual(self.io.getvalue(), _b('progress: pop\n'))
1268
def test_progress_push(self):
1269
self.protocol.progress(1234, subunit.PROGRESS_PUSH)
1270
self.assertEqual(self.io.getvalue(), _b('progress: push\n'))
1272
def test_time(self):
1273
# Calling time() outputs a time signal immediately.
1275
datetime.datetime(2009,10,11,12,13,14,15, iso8601.Utc()))
1277
_b("time: 2009-10-11 12:13:14.000015Z\n"),
1280
def test_add_unexpected_success(self):
1281
"""Test addUnexpectedSuccess on a TestProtocolClient."""
1282
self.protocol.addUnexpectedSuccess(self.test)
1284
self.io.getvalue(), _b("uxsuccess: %s\n" % self.test.id()))
1286
def test_add_unexpected_success_details(self):
1287
"""Test addUnexpectedSuccess on a TestProtocolClient with details."""
1288
self.protocol.addUnexpectedSuccess(self.test, details=self.sample_details)
1290
self.io.getvalue(), _b("uxsuccess: %s [ multipart\n"
1291
"Content-Type: text/plain\n"
1293
"F\r\nserialised\nform0\r\n]\n" % self.test.id()))
1297
loader = subunit.tests.TestUtil.TestLoader()
1298
result = loader.loadTestsFromName(__name__)