2
# subunit: extensions to python unittest to get test results from subprocesses.
2
# subunit: extensions to Python unittest to get test results from subprocesses.
3
3
# Copyright (C) 2005 Robert Collins <robertc@robertcollins.net>
5
# This program is free software; you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 2 of the License, or
8
# (at your option) any later version.
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
15
# You should have received a copy of the GNU General Public License
16
# along with this program; if not, write to the Free Software
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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
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 (
27
class MockTestProtocolServerClient(object):
28
"""A mock protocol server client to test callbacks."""
33
self.failure_calls = []
35
self.success_calls = []
36
super(MockTestProtocolServerClient, self).__init__()
38
def addError(self, test, error):
39
self.error_calls.append((test, error))
41
def addFailure(self, test, error):
42
self.failure_calls.append((test, error))
44
def addSuccess(self, test):
45
self.success_calls.append(test)
47
def stopTest(self, test):
48
self.end_calls.append(test)
50
def startTest(self, test):
51
self.start_calls.append(test)
53
except AttributeError:
54
MockTestProtocolServer = None
57
class TestMockTestProtocolServer(unittest.TestCase):
59
def test_start_test(self):
60
protocol = MockTestProtocolServerClient()
61
protocol.startTest(subunit.RemotedTestCase("test old mcdonald"))
62
self.assertEqual(protocol.start_calls,
63
[subunit.RemotedTestCase("test old mcdonald")])
64
self.assertEqual(protocol.end_calls, [])
65
self.assertEqual(protocol.error_calls, [])
66
self.assertEqual(protocol.failure_calls, [])
67
self.assertEqual(protocol.success_calls, [])
69
def test_add_error(self):
70
protocol = MockTestProtocolServerClient()
71
protocol.addError(subunit.RemotedTestCase("old mcdonald"),
72
subunit.RemoteError("omg it works"))
73
self.assertEqual(protocol.start_calls, [])
74
self.assertEqual(protocol.end_calls, [])
75
self.assertEqual(protocol.error_calls, [(
76
subunit.RemotedTestCase("old mcdonald"),
77
subunit.RemoteError("omg it works"))])
78
self.assertEqual(protocol.failure_calls, [])
79
self.assertEqual(protocol.success_calls, [])
81
def test_add_failure(self):
82
protocol = MockTestProtocolServerClient()
83
protocol.addFailure(subunit.RemotedTestCase("old mcdonald"),
84
subunit.RemoteError("omg it works"))
85
self.assertEqual(protocol.start_calls, [])
86
self.assertEqual(protocol.end_calls, [])
87
self.assertEqual(protocol.error_calls, [])
88
self.assertEqual(protocol.failure_calls, [
89
(subunit.RemotedTestCase("old mcdonald"),
90
subunit.RemoteError("omg it works"))])
91
self.assertEqual(protocol.success_calls, [])
93
def test_add_success(self):
94
protocol = MockTestProtocolServerClient()
95
protocol.addSuccess(subunit.RemotedTestCase("test old mcdonald"))
96
self.assertEqual(protocol.start_calls, [])
97
self.assertEqual(protocol.end_calls, [])
98
self.assertEqual(protocol.error_calls, [])
99
self.assertEqual(protocol.failure_calls, [])
100
self.assertEqual(protocol.success_calls,
101
[subunit.RemotedTestCase("test old mcdonald")])
103
def test_end_test(self):
104
protocol = MockTestProtocolServerClient()
105
protocol.stopTest(subunit.RemotedTestCase("test old mcdonald"))
106
self.assertEqual(protocol.end_calls,
107
[subunit.RemotedTestCase("test old mcdonald")])
108
self.assertEqual(protocol.error_calls, [])
109
self.assertEqual(protocol.failure_calls, [])
110
self.assertEqual(protocol.success_calls, [])
111
self.assertEqual(protocol.start_calls, [])
32
from subunit import _remote_exception_str
33
import subunit.iso8601 as iso8601
114
36
class TestTestImports(unittest.TestCase):
116
38
def test_imports(self):
39
from subunit import DiscardStream
117
40
from subunit import TestProtocolServer
118
41
from subunit import RemotedTestCase
119
42
from subunit import RemoteError
120
43
from subunit import ExecTestCase
121
44
from subunit import IsolatedTestCase
122
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())
125
79
class TestTestProtocolServerPipe(unittest.TestCase):
140
94
bing = subunit.RemotedTestCase("bing crosby")
141
95
an_error = subunit.RemotedTestCase("an error")
142
96
self.assertEqual(client.errors,
143
[(an_error, 'RemoteException: \n\n')])
97
[(an_error, _remote_exception_str + '\n')])
146
[(bing, "RemoteException: foo.c:53:ERROR invalid state\n\n")])
100
[(bing, _remote_exception_str + ": Text attachment: traceback\n"
101
"------------\nfoo.c:53:ERROR invalid state\n"
102
"------------\n\n")])
147
103
self.assertEqual(client.testsRun, 3)
105
def test_non_test_characters_forwarded_immediately(self):
150
109
class TestTestProtocolServerStartTest(unittest.TestCase):
153
self.client = MockTestProtocolServerClient()
112
self.client = Python26TestResult()
154
113
self.protocol = subunit.TestProtocolServer(self.client)
156
115
def test_start_test(self):
157
116
self.protocol.lineReceived("test old mcdonald\n")
158
self.assertEqual(self.client.start_calls,
159
[subunit.RemotedTestCase("old mcdonald")])
117
self.assertEqual(self.client._events,
118
[('startTest', subunit.RemotedTestCase("old mcdonald"))])
161
120
def test_start_testing(self):
162
121
self.protocol.lineReceived("testing old mcdonald\n")
163
self.assertEqual(self.client.start_calls,
164
[subunit.RemotedTestCase("old mcdonald")])
122
self.assertEqual(self.client._events,
123
[('startTest', subunit.RemotedTestCase("old mcdonald"))])
166
125
def test_start_test_colon(self):
167
126
self.protocol.lineReceived("test: old mcdonald\n")
168
self.assertEqual(self.client.start_calls,
169
[subunit.RemotedTestCase("old mcdonald")])
127
self.assertEqual(self.client._events,
128
[('startTest', subunit.RemotedTestCase("old mcdonald"))])
130
def test_indented_test_colon_ignored(self):
131
self.protocol.lineReceived(" test: old mcdonald\n")
132
self.assertEqual([], self.client._events)
171
134
def test_start_testing_colon(self):
172
135
self.protocol.lineReceived("testing: old mcdonald\n")
173
self.assertEqual(self.client.start_calls,
174
[subunit.RemotedTestCase("old mcdonald")])
136
self.assertEqual(self.client._events,
137
[('startTest', subunit.RemotedTestCase("old mcdonald"))])
177
140
class TestTestProtocolServerPassThrough(unittest.TestCase):
180
from StringIO import StringIO
181
143
self.stdout = StringIO()
182
144
self.test = subunit.RemotedTestCase("old mcdonald")
183
self.client = MockTestProtocolServerClient()
145
self.client = ExtendedTestResult()
184
146
self.protocol = subunit.TestProtocolServer(self.client, self.stdout)
186
148
def keywords_before_test(self):
206
168
def test_keywords_before_test(self):
207
169
self.keywords_before_test()
208
self.assertEqual(self.client.start_calls, [])
209
self.assertEqual(self.client.error_calls, [])
210
self.assertEqual(self.client.failure_calls, [])
211
self.assertEqual(self.client.success_calls, [])
170
self.assertEqual(self.client._events, [])
213
172
def test_keywords_after_error(self):
214
173
self.protocol.lineReceived("test old mcdonald\n")
215
174
self.protocol.lineReceived("error old mcdonald\n")
216
175
self.keywords_before_test()
217
self.assertEqual(self.client.start_calls, [self.test])
218
self.assertEqual(self.client.end_calls, [self.test])
219
self.assertEqual(self.client.error_calls,
220
[(self.test, subunit.RemoteError(""))])
221
self.assertEqual(self.client.failure_calls, [])
222
self.assertEqual(self.client.success_calls, [])
177
('startTest', self.test),
178
('addError', self.test, {}),
179
('stopTest', self.test),
180
], self.client._events)
224
182
def test_keywords_after_failure(self):
225
183
self.protocol.lineReceived("test old mcdonald\n")
226
184
self.protocol.lineReceived("failure old mcdonald\n")
227
185
self.keywords_before_test()
228
self.assertEqual(self.client.start_calls, [self.test])
229
self.assertEqual(self.client.end_calls, [self.test])
230
self.assertEqual(self.client.error_calls, [])
231
self.assertEqual(self.client.failure_calls,
232
[(self.test, subunit.RemoteError())])
233
self.assertEqual(self.client.success_calls, [])
186
self.assertEqual(self.client._events, [
187
('startTest', self.test),
188
('addFailure', self.test, {}),
189
('stopTest', self.test),
235
192
def test_keywords_after_success(self):
236
193
self.protocol.lineReceived("test old mcdonald\n")
237
194
self.protocol.lineReceived("success old mcdonald\n")
238
195
self.keywords_before_test()
239
self.assertEqual(self.client.start_calls, [self.test])
240
self.assertEqual(self.client.end_calls, [self.test])
241
self.assertEqual(self.client.error_calls, [])
242
self.assertEqual(self.client.failure_calls, [])
243
self.assertEqual(self.client.success_calls, [self.test])
197
('startTest', self.test),
198
('addSuccess', self.test),
199
('stopTest', self.test),
200
], self.client._events)
245
202
def test_keywords_after_test(self):
246
203
self.protocol.lineReceived("test old mcdonald\n")
315
277
class TestTestProtocolServerLostConnection(unittest.TestCase):
318
self.client = MockTestProtocolServerClient()
280
self.client = Python26TestResult()
319
281
self.protocol = subunit.TestProtocolServer(self.client)
320
282
self.test = subunit.RemotedTestCase("old mcdonald")
322
284
def test_lost_connection_no_input(self):
323
285
self.protocol.lostConnection()
324
self.assertEqual(self.client.start_calls, [])
325
self.assertEqual(self.client.error_calls, [])
326
self.assertEqual(self.client.failure_calls, [])
327
self.assertEqual(self.client.success_calls, [])
286
self.assertEqual([], self.client._events)
329
288
def test_lost_connection_after_start(self):
330
289
self.protocol.lineReceived("test old mcdonald\n")
331
290
self.protocol.lostConnection()
332
self.assertEqual(self.client.start_calls, [self.test])
333
self.assertEqual(self.client.end_calls, [self.test])
334
self.assertEqual(self.client.error_calls, [
335
(self.test, subunit.RemoteError("lost connection during "
336
"test 'old mcdonald'"))])
337
self.assertEqual(self.client.failure_calls, [])
338
self.assertEqual(self.client.success_calls, [])
291
failure = subunit.RemoteError(
292
u"lost connection during test 'old mcdonald'")
294
('startTest', self.test),
295
('addError', self.test, failure),
296
('stopTest', self.test),
297
], self.client._events)
340
299
def test_lost_connected_after_error(self):
341
300
self.protocol.lineReceived("test old mcdonald\n")
342
301
self.protocol.lineReceived("error old mcdonald\n")
343
302
self.protocol.lostConnection()
344
self.assertEqual(self.client.start_calls, [self.test])
345
self.assertEqual(self.client.failure_calls, [])
346
self.assertEqual(self.client.end_calls, [self.test])
347
self.assertEqual(self.client.error_calls, [
348
(self.test, subunit.RemoteError(""))])
349
self.assertEqual(self.client.success_calls, [])
304
('startTest', self.test),
305
('addError', self.test, subunit.RemoteError(u"")),
306
('stopTest', self.test),
307
], self.client._events)
309
def do_connection_lost(self, outcome, opening):
310
self.protocol.lineReceived("test old mcdonald\n")
311
self.protocol.lineReceived("%s old mcdonald %s" % (outcome, opening))
312
self.protocol.lostConnection()
313
failure = subunit.RemoteError(
314
u"lost connection during %s report of test 'old mcdonald'" %
317
('startTest', self.test),
318
('addError', self.test, failure),
319
('stopTest', self.test),
320
], self.client._events)
351
322
def test_lost_connection_during_error(self):
352
self.protocol.lineReceived("test old mcdonald\n")
353
self.protocol.lineReceived("error old mcdonald [\n")
354
self.protocol.lostConnection()
355
self.assertEqual(self.client.start_calls, [self.test])
356
self.assertEqual(self.client.end_calls, [self.test])
357
self.assertEqual(self.client.error_calls, [
358
(self.test, subunit.RemoteError("lost connection during error "
359
"report of test 'old mcdonald'"))])
360
self.assertEqual(self.client.failure_calls, [])
361
self.assertEqual(self.client.success_calls, [])
323
self.do_connection_lost("error", "[\n")
325
def test_lost_connection_during_error_details(self):
326
self.do_connection_lost("error", "[ multipart\n")
363
328
def test_lost_connected_after_failure(self):
364
329
self.protocol.lineReceived("test old mcdonald\n")
365
330
self.protocol.lineReceived("failure old mcdonald\n")
366
331
self.protocol.lostConnection()
367
test = subunit.RemotedTestCase("old mcdonald")
368
self.assertEqual(self.client.start_calls, [self.test])
369
self.assertEqual(self.client.end_calls, [self.test])
370
self.assertEqual(self.client.error_calls, [])
371
self.assertEqual(self.client.failure_calls,
372
[(self.test, subunit.RemoteError())])
373
self.assertEqual(self.client.success_calls, [])
333
('startTest', self.test),
334
('addFailure', self.test, subunit.RemoteError(u"")),
335
('stopTest', self.test),
336
], self.client._events)
375
338
def test_lost_connection_during_failure(self):
376
self.protocol.lineReceived("test old mcdonald\n")
377
self.protocol.lineReceived("failure old mcdonald [\n")
378
self.protocol.lostConnection()
379
self.assertEqual(self.client.start_calls, [self.test])
380
self.assertEqual(self.client.end_calls, [self.test])
381
self.assertEqual(self.client.error_calls,
383
subunit.RemoteError("lost connection during "
385
" of test 'old mcdonald'"))])
386
self.assertEqual(self.client.failure_calls, [])
387
self.assertEqual(self.client.success_calls, [])
339
self.do_connection_lost("failure", "[\n")
341
def test_lost_connection_during_failure_details(self):
342
self.do_connection_lost("failure", "[ multipart\n")
389
344
def test_lost_connection_after_success(self):
390
345
self.protocol.lineReceived("test old mcdonald\n")
391
346
self.protocol.lineReceived("success old mcdonald\n")
392
347
self.protocol.lostConnection()
393
self.assertEqual(self.client.start_calls, [self.test])
394
self.assertEqual(self.client.end_calls, [self.test])
395
self.assertEqual(self.client.error_calls, [])
396
self.assertEqual(self.client.failure_calls, [])
397
self.assertEqual(self.client.success_calls, [self.test])
349
('startTest', self.test),
350
('addSuccess', self.test),
351
('stopTest', self.test),
352
], self.client._events)
354
def test_lost_connection_during_success(self):
355
self.do_connection_lost("success", "[\n")
357
def test_lost_connection_during_success_details(self):
358
self.do_connection_lost("success", "[ multipart\n")
360
def test_lost_connection_during_skip(self):
361
self.do_connection_lost("skip", "[\n")
363
def test_lost_connection_during_skip_details(self):
364
self.do_connection_lost("skip", "[ multipart\n")
366
def test_lost_connection_during_xfail(self):
367
self.do_connection_lost("xfail", "[\n")
369
def test_lost_connection_during_xfail_details(self):
370
self.do_connection_lost("xfail", "[ multipart\n")
373
class TestInTestMultipart(unittest.TestCase):
376
self.client = ExtendedTestResult()
377
self.protocol = subunit.TestProtocolServer(self.client)
378
self.protocol.lineReceived("test mcdonalds farm\n")
379
self.test = subunit.RemotedTestCase("mcdonalds farm")
381
def test__outcome_sets_details_parser(self):
382
self.protocol._reading_success_details.details_parser = None
383
self.protocol._state._outcome(0, "mcdonalds farm [ multipart\n",
384
None, self.protocol._reading_success_details)
385
parser = self.protocol._reading_success_details.details_parser
386
self.assertNotEqual(None, parser)
387
self.assertTrue(isinstance(parser,
388
subunit.details.MultipartDetailsParser))
400
391
class TestTestProtocolServerAddError(unittest.TestCase):
403
self.client = MockTestProtocolServerClient()
394
self.client = ExtendedTestResult()
404
395
self.protocol = subunit.TestProtocolServer(self.client)
405
396
self.protocol.lineReceived("test mcdonalds farm\n")
406
397
self.test = subunit.RemotedTestCase("mcdonalds farm")
408
399
def simple_error_keyword(self, keyword):
409
400
self.protocol.lineReceived("%s mcdonalds farm\n" % keyword)
410
self.assertEqual(self.client.start_calls, [self.test])
411
self.assertEqual(self.client.end_calls, [self.test])
412
self.assertEqual(self.client.error_calls, [
413
(self.test, subunit.RemoteError(""))])
414
self.assertEqual(self.client.failure_calls, [])
403
('startTest', self.test),
404
('addError', self.test, details),
405
('stopTest', self.test),
406
], self.client._events)
416
408
def test_simple_error(self):
417
409
self.simple_error_keyword("error")
422
414
def test_error_empty_message(self):
423
415
self.protocol.lineReceived("error mcdonalds farm [\n")
424
416
self.protocol.lineReceived("]\n")
425
self.assertEqual(self.client.start_calls, [self.test])
426
self.assertEqual(self.client.end_calls, [self.test])
427
self.assertEqual(self.client.error_calls, [
428
(self.test, subunit.RemoteError(""))])
429
self.assertEqual(self.client.failure_calls, [])
418
details['traceback'] = Content(ContentType("text", "x-traceback",
419
{'charset': 'utf8'}), lambda:[""])
421
('startTest', self.test),
422
('addError', self.test, details),
423
('stopTest', self.test),
424
], self.client._events)
431
426
def error_quoted_bracket(self, keyword):
432
427
self.protocol.lineReceived("%s mcdonalds farm [\n" % keyword)
433
428
self.protocol.lineReceived(" ]\n")
434
429
self.protocol.lineReceived("]\n")
435
self.assertEqual(self.client.start_calls, [self.test])
436
self.assertEqual(self.client.end_calls, [self.test])
437
self.assertEqual(self.client.error_calls, [
438
(self.test, subunit.RemoteError("]\n"))])
439
self.assertEqual(self.client.failure_calls, [])
431
details['traceback'] = Content(ContentType("text", "x-traceback",
432
{'charset': 'utf8'}), lambda:["]\n"])
434
('startTest', self.test),
435
('addError', self.test, details),
436
('stopTest', self.test),
437
], self.client._events)
441
439
def test_error_quoted_bracket(self):
442
440
self.error_quoted_bracket("error")
493
493
self.failure_quoted_bracket("failure:")
496
class TestTestProtocolServerAddxFail(unittest.TestCase):
497
"""Tests for the xfail keyword.
499
In Python this can thunk through to Success due to stdlib limitations (see
503
def capture_expected_failure(self, test, err):
504
self._events.append((test, err))
506
def setup_python26(self):
507
"""Setup a test object ready to be xfailed and thunk to success."""
508
self.client = Python26TestResult()
509
self.setup_protocol()
511
def setup_python27(self):
512
"""Setup a test object ready to be xfailed."""
513
self.client = Python27TestResult()
514
self.setup_protocol()
516
def setup_python_ex(self):
517
"""Setup a test object ready to be xfailed with details."""
518
self.client = ExtendedTestResult()
519
self.setup_protocol()
521
def setup_protocol(self):
522
"""Setup the protocol based on self.client."""
523
self.protocol = subunit.TestProtocolServer(self.client)
524
self.protocol.lineReceived("test mcdonalds farm\n")
525
self.test = self.client._events[-1][-1]
527
def simple_xfail_keyword(self, keyword, as_success):
528
self.protocol.lineReceived("%s mcdonalds farm\n" % keyword)
529
self.check_success_or_xfail(as_success)
531
def check_success_or_xfail(self, as_success, error_message=None):
534
('startTest', self.test),
535
('addSuccess', self.test),
536
('stopTest', self.test),
537
], self.client._events)
540
if error_message is not None:
541
details['traceback'] = Content(
542
ContentType("text", "x-traceback", {'charset': 'utf8'}),
543
lambda:[error_message])
544
if isinstance(self.client, ExtendedTestResult):
547
if error_message is not None:
548
value = subunit.RemoteError(u'Text attachment: traceback\n'
549
'------------\n' + error_message + '------------\n')
551
value = subunit.RemoteError()
553
('startTest', self.test),
554
('addExpectedFailure', self.test, value),
555
('stopTest', self.test),
556
], self.client._events)
558
def test_simple_xfail(self):
559
self.setup_python26()
560
self.simple_xfail_keyword("xfail", True)
561
self.setup_python27()
562
self.simple_xfail_keyword("xfail", False)
563
self.setup_python_ex()
564
self.simple_xfail_keyword("xfail", False)
566
def test_simple_xfail_colon(self):
567
self.setup_python26()
568
self.simple_xfail_keyword("xfail:", True)
569
self.setup_python27()
570
self.simple_xfail_keyword("xfail:", False)
571
self.setup_python_ex()
572
self.simple_xfail_keyword("xfail:", False)
574
def test_xfail_empty_message(self):
575
self.setup_python26()
576
self.empty_message(True)
577
self.setup_python27()
578
self.empty_message(False)
579
self.setup_python_ex()
580
self.empty_message(False, error_message="")
582
def empty_message(self, as_success, error_message="\n"):
583
self.protocol.lineReceived("xfail mcdonalds farm [\n")
584
self.protocol.lineReceived("]\n")
585
self.check_success_or_xfail(as_success, error_message)
587
def xfail_quoted_bracket(self, keyword, as_success):
588
# This tests it is accepted, but cannot test it is used today, because
589
# of not having a way to expose it in Python so far.
590
self.protocol.lineReceived("%s mcdonalds farm [\n" % keyword)
591
self.protocol.lineReceived(" ]\n")
592
self.protocol.lineReceived("]\n")
593
self.check_success_or_xfail(as_success, "]\n")
595
def test_xfail_quoted_bracket(self):
596
self.setup_python26()
597
self.xfail_quoted_bracket("xfail", True)
598
self.setup_python27()
599
self.xfail_quoted_bracket("xfail", False)
600
self.setup_python_ex()
601
self.xfail_quoted_bracket("xfail", False)
603
def test_xfail_colon_quoted_bracket(self):
604
self.setup_python26()
605
self.xfail_quoted_bracket("xfail:", True)
606
self.setup_python27()
607
self.xfail_quoted_bracket("xfail:", False)
608
self.setup_python_ex()
609
self.xfail_quoted_bracket("xfail:", False)
612
class TestTestProtocolServerAddSkip(unittest.TestCase):
613
"""Tests for the skip keyword.
615
In Python this meets the testtools extended TestResult contract.
616
(See https://launchpad.net/testtools).
620
"""Setup a test object ready to be skipped."""
621
self.client = ExtendedTestResult()
622
self.protocol = subunit.TestProtocolServer(self.client)
623
self.protocol.lineReceived("test mcdonalds farm\n")
624
self.test = self.client._events[-1][-1]
626
def assertSkip(self, reason):
628
if reason is not None:
629
details['reason'] = Content(
630
ContentType("text", "plain"), lambda:[reason])
632
('startTest', self.test),
633
('addSkip', self.test, details),
634
('stopTest', self.test),
635
], self.client._events)
637
def simple_skip_keyword(self, keyword):
638
self.protocol.lineReceived("%s mcdonalds farm\n" % keyword)
639
self.assertSkip(None)
641
def test_simple_skip(self):
642
self.simple_skip_keyword("skip")
644
def test_simple_skip_colon(self):
645
self.simple_skip_keyword("skip:")
647
def test_skip_empty_message(self):
648
self.protocol.lineReceived("skip mcdonalds farm [\n")
649
self.protocol.lineReceived("]\n")
652
def skip_quoted_bracket(self, keyword):
653
# This tests it is accepted, but cannot test it is used today, because
654
# of not having a way to expose it in Python so far.
655
self.protocol.lineReceived("%s mcdonalds farm [\n" % keyword)
656
self.protocol.lineReceived(" ]\n")
657
self.protocol.lineReceived("]\n")
658
self.assertSkip("]\n")
660
def test_skip_quoted_bracket(self):
661
self.skip_quoted_bracket("skip")
663
def test_skip_colon_quoted_bracket(self):
664
self.skip_quoted_bracket("skip:")
496
667
class TestTestProtocolServerAddSuccess(unittest.TestCase):
499
self.client = MockTestProtocolServerClient()
670
self.client = ExtendedTestResult()
500
671
self.protocol = subunit.TestProtocolServer(self.client)
501
672
self.protocol.lineReceived("test mcdonalds farm\n")
502
673
self.test = subunit.RemotedTestCase("mcdonalds farm")
504
675
def simple_success_keyword(self, keyword):
505
676
self.protocol.lineReceived("%s mcdonalds farm\n" % keyword)
506
self.assertEqual(self.client.start_calls, [self.test])
507
self.assertEqual(self.client.end_calls, [self.test])
508
self.assertEqual(self.client.error_calls, [])
509
self.assertEqual(self.client.success_calls, [self.test])
678
('startTest', self.test),
679
('addSuccess', self.test),
680
('stopTest', self.test),
681
], self.client._events)
511
683
def test_simple_success(self):
512
684
self.simple_success_keyword("failure")
520
692
def test_simple_success_colon(self):
521
693
self.simple_success_keyword("successful:")
695
def assertSuccess(self, details):
697
('startTest', self.test),
698
('addSuccess', self.test, details),
699
('stopTest', self.test),
700
], self.client._events)
702
def test_success_empty_message(self):
703
self.protocol.lineReceived("success mcdonalds farm [\n")
704
self.protocol.lineReceived("]\n")
706
details['message'] = Content(ContentType("text", "plain"),
708
self.assertSuccess(details)
710
def success_quoted_bracket(self, keyword):
711
# This tests it is accepted, but cannot test it is used today, because
712
# of not having a way to expose it in Python so far.
713
self.protocol.lineReceived("%s mcdonalds farm [\n" % keyword)
714
self.protocol.lineReceived(" ]\n")
715
self.protocol.lineReceived("]\n")
717
details['message'] = Content(ContentType("text", "plain"),
719
self.assertSuccess(details)
721
def test_success_quoted_bracket(self):
722
self.success_quoted_bracket("success")
724
def test_success_colon_quoted_bracket(self):
725
self.success_quoted_bracket("success:")
728
class TestTestProtocolServerProgress(unittest.TestCase):
729
"""Test receipt of progress: directives."""
731
def test_progress_accepted_stdlib(self):
732
self.result = Python26TestResult()
733
self.stream = StringIO()
734
self.protocol = subunit.TestProtocolServer(self.result,
736
self.protocol.lineReceived("progress: 23")
737
self.protocol.lineReceived("progress: -2")
738
self.protocol.lineReceived("progress: +4")
739
self.assertEqual("", self.stream.getvalue())
741
def test_progress_accepted_extended(self):
742
# With a progress capable TestResult, progress events are emitted.
743
self.result = ExtendedTestResult()
744
self.stream = StringIO()
745
self.protocol = subunit.TestProtocolServer(self.result,
747
self.protocol.lineReceived("progress: 23")
748
self.protocol.lineReceived("progress: push")
749
self.protocol.lineReceived("progress: -2")
750
self.protocol.lineReceived("progress: pop")
751
self.protocol.lineReceived("progress: +4")
752
self.assertEqual("", self.stream.getvalue())
754
('progress', 23, subunit.PROGRESS_SET),
755
('progress', None, subunit.PROGRESS_PUSH),
756
('progress', -2, subunit.PROGRESS_CUR),
757
('progress', None, subunit.PROGRESS_POP),
758
('progress', 4, subunit.PROGRESS_CUR),
759
], self.result._events)
762
class TestTestProtocolServerStreamTags(unittest.TestCase):
763
"""Test managing tags on the protocol level."""
766
self.client = ExtendedTestResult()
767
self.protocol = subunit.TestProtocolServer(self.client)
769
def test_initial_tags(self):
770
self.protocol.lineReceived("tags: foo bar:baz quux\n")
772
('tags', set(["foo", "bar:baz", "quux"]), set()),
773
], self.client._events)
775
def test_minus_removes_tags(self):
776
self.protocol.lineReceived("tags: -bar quux\n")
778
('tags', set(["quux"]), set(["bar"])),
779
], self.client._events)
781
def test_tags_do_not_get_set_on_test(self):
782
self.protocol.lineReceived("test mcdonalds farm\n")
783
test = self.client._events[0][-1]
784
self.assertEqual(None, getattr(test, 'tags', None))
786
def test_tags_do_not_get_set_on_global_tags(self):
787
self.protocol.lineReceived("tags: foo bar\n")
788
self.protocol.lineReceived("test mcdonalds farm\n")
789
test = self.client._events[-1][-1]
790
self.assertEqual(None, getattr(test, 'tags', None))
792
def test_tags_get_set_on_test_tags(self):
793
self.protocol.lineReceived("test mcdonalds farm\n")
794
test = self.client._events[-1][-1]
795
self.protocol.lineReceived("tags: foo bar\n")
796
self.protocol.lineReceived("success mcdonalds farm\n")
797
self.assertEqual(None, getattr(test, 'tags', None))
800
class TestTestProtocolServerStreamTime(unittest.TestCase):
801
"""Test managing time information at the protocol level."""
803
def test_time_accepted_stdlib(self):
804
self.result = Python26TestResult()
805
self.stream = StringIO()
806
self.protocol = subunit.TestProtocolServer(self.result,
808
self.protocol.lineReceived("time: 2001-12-12 12:59:59Z\n")
809
self.assertEqual("", self.stream.getvalue())
811
def test_time_accepted_extended(self):
812
self.result = ExtendedTestResult()
813
self.stream = StringIO()
814
self.protocol = subunit.TestProtocolServer(self.result,
816
self.protocol.lineReceived("time: 2001-12-12 12:59:59Z\n")
817
self.assertEqual("", self.stream.getvalue())
819
('time', datetime.datetime(2001, 12, 12, 12, 59, 59, 0,
821
], self.result._events)
524
824
class TestRemotedTestCase(unittest.TestCase):
570
870
# the sample script runs three tests, one each
571
871
# that fails, errors and succeeds
873
def test_sample_method_args(self):
874
"""sample-script.py foo"""
875
# sample that will run just one test.
574
877
def test_construct(self):
575
878
test = self.SampleExecTestCase("test_sample_method")
576
879
self.assertEqual(test.script,
577
880
subunit.join_dir(__file__, 'sample-script.py'))
883
result = unittest.TestResult()
884
test = self.SampleExecTestCase("test_sample_method_args")
886
self.assertEqual(1, result.testsRun)
579
888
def test_run(self):
580
runner = MockTestProtocolServerClient()
889
result = ExtendedTestResult()
581
890
test = self.SampleExecTestCase("test_sample_method")
583
892
mcdonald = subunit.RemotedTestCase("old mcdonald")
584
893
bing = subunit.RemotedTestCase("bing crosby")
895
bing_details['traceback'] = Content(ContentType("text", "x-traceback",
896
{'charset': 'utf8'}), lambda:["foo.c:53:ERROR invalid state\n"])
585
897
an_error = subunit.RemotedTestCase("an error")
586
self.assertEqual(runner.error_calls,
587
[(an_error, subunit.RemoteError())])
588
self.assertEqual(runner.failure_calls,
591
"foo.c:53:ERROR invalid state\n"))])
592
self.assertEqual(runner.start_calls, [mcdonald, bing, an_error])
593
self.assertEqual(runner.end_calls, [mcdonald, bing, an_error])
900
('startTest', mcdonald),
901
('addSuccess', mcdonald),
902
('stopTest', mcdonald),
904
('addFailure', bing, bing_details),
906
('startTest', an_error),
907
('addError', an_error, error_details),
908
('stopTest', an_error),
595
911
def test_debug(self):
596
912
test = self.SampleExecTestCase("test_sample_method")
707
1027
self.assertEqual(
708
1028
self.io.getvalue(), "successful: %s\n" % self.test.id())
1030
def test_add_success_details(self):
1031
"""Test addSuccess on a TestProtocolClient with details."""
1032
self.protocol.addSuccess(self.test, details=self.sample_details)
1034
self.io.getvalue(), "successful: %s [ multipart\n"
1035
"Content-Type: text/plain\n"
1037
"F\r\nserialised\nform0\r\n]\n" % self.test.id())
710
1039
def test_add_failure(self):
711
1040
"""Test addFailure on a TestProtocolClient."""
712
self.protocol.addFailure(self.test, subunit.RemoteError("boo"))
715
'failure: %s [\nRemoteException: boo\n]\n' % self.test.id())
1041
self.protocol.addFailure(
1042
self.test, subunit.RemoteError(u"boo qux"))
1045
('failure: %s [\n' + _remote_exception_str + ': boo qux\n]\n')
1048
def test_add_failure_details(self):
1049
"""Test addFailure on a TestProtocolClient with details."""
1050
self.protocol.addFailure(
1051
self.test, details=self.sample_tb_details)
1054
("failure: %s [ multipart\n"
1055
"Content-Type: text/plain\n"
1057
"F\r\nserialised\nform0\r\n"
1058
"Content-Type: text/x-traceback;charset=utf8,language=python\n"
1060
"1A\r\n" + _remote_exception_str + ": boo qux\n0\r\n"
1061
"]\n") % self.test.id())
717
1063
def test_add_error(self):
718
1064
"""Test stopTest on a TestProtocolClient."""
719
self.protocol.addError(self.test, subunit.RemoteError("phwoar"))
723
"RemoteException: phwoar\n"
1065
self.protocol.addError(
1066
self.test, subunit.RemoteError(u"phwoar crikey"))
1070
_remote_exception_str + ": phwoar crikey\n"
1071
"]\n") % self.test.id())
1073
def test_add_error_details(self):
1074
"""Test stopTest on a TestProtocolClient with details."""
1075
self.protocol.addError(
1076
self.test, details=self.sample_tb_details)
1079
("error: %s [ multipart\n"
1080
"Content-Type: text/plain\n"
1082
"F\r\nserialised\nform0\r\n"
1083
"Content-Type: text/x-traceback;charset=utf8,language=python\n"
1085
"1A\r\n" + _remote_exception_str + ": boo qux\n0\r\n"
1086
"]\n") % self.test.id())
1088
def test_add_expected_failure(self):
1089
"""Test addExpectedFailure on a TestProtocolClient."""
1090
self.protocol.addExpectedFailure(
1091
self.test, subunit.RemoteError(u"phwoar crikey"))
1095
_remote_exception_str + ": phwoar crikey\n"
1096
"]\n") % self.test.id())
1098
def test_add_expected_failure_details(self):
1099
"""Test addExpectedFailure on a TestProtocolClient with details."""
1100
self.protocol.addExpectedFailure(
1101
self.test, details=self.sample_tb_details)
1104
("xfail: %s [ multipart\n"
1105
"Content-Type: text/plain\n"
1107
"F\r\nserialised\nform0\r\n"
1108
"Content-Type: text/x-traceback;charset=utf8,language=python\n"
1110
"1A\r\n"+ _remote_exception_str + ": boo qux\n0\r\n"
1111
"]\n") % self.test.id())
1113
def test_add_skip(self):
1114
"""Test addSkip on a TestProtocolClient."""
1115
self.protocol.addSkip(
1116
self.test, "Has it really?")
1119
'skip: %s [\nHas it really?\n]\n' % self.test.id())
1121
def test_add_skip_details(self):
1122
"""Test addSkip on a TestProtocolClient with details."""
1123
details = {'reason':Content(
1124
ContentType('text', 'plain'), lambda:['Has it really?'])}
1125
self.protocol.addSkip(
1126
self.test, details=details)
1129
"skip: %s [ multipart\n"
1130
"Content-Type: text/plain\n"
1132
"E\r\nHas it really?0\r\n"
724
1133
"]\n" % self.test.id())
1135
def test_progress_set(self):
1136
self.protocol.progress(23, subunit.PROGRESS_SET)
1137
self.assertEqual(self.io.getvalue(), 'progress: 23\n')
1139
def test_progress_neg_cur(self):
1140
self.protocol.progress(-23, subunit.PROGRESS_CUR)
1141
self.assertEqual(self.io.getvalue(), 'progress: -23\n')
1143
def test_progress_pos_cur(self):
1144
self.protocol.progress(23, subunit.PROGRESS_CUR)
1145
self.assertEqual(self.io.getvalue(), 'progress: +23\n')
1147
def test_progress_pop(self):
1148
self.protocol.progress(1234, subunit.PROGRESS_POP)
1149
self.assertEqual(self.io.getvalue(), 'progress: pop\n')
1151
def test_progress_push(self):
1152
self.protocol.progress(1234, subunit.PROGRESS_PUSH)
1153
self.assertEqual(self.io.getvalue(), 'progress: push\n')
1155
def test_time(self):
1156
# Calling time() outputs a time signal immediately.
1158
datetime.datetime(2009,10,11,12,13,14,15, iso8601.Utc()))
1160
"time: 2009-10-11 12:13:14.000015Z\n",
1163
def test_add_unexpected_success(self):
1164
"""Test addUnexpectedSuccess on a TestProtocolClient."""
1165
self.protocol.addUnexpectedSuccess(self.test)
1167
self.io.getvalue(), "successful: %s\n" % self.test.id())
1169
def test_add_unexpected_success_details(self):
1170
"""Test addUnexpectedSuccess on a TestProtocolClient with details."""
1171
self.protocol.addUnexpectedSuccess(self.test, details=self.sample_details)
1173
self.io.getvalue(), "successful: %s [ multipart\n"
1174
"Content-Type: text/plain\n"
1176
"F\r\nserialised\nform0\r\n]\n" % self.test.id())
727
1179
def test_suite():
728
1180
loader = subunit.tests.TestUtil.TestLoader()