2 # subunit: extensions to python unittest to get test results from subprocesses.
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
21 from StringIO import StringIO
26 class MockTestProtocolServerClient(object):
27 """A mock protocol server client to test callbacks."""
32 self.failure_calls = []
34 self.success_calls = []
35 super(MockTestProtocolServerClient, self).__init__()
37 def addError(self, test, error):
38 self.error_calls.append((test, error))
40 def addFailure(self, test, error):
41 self.failure_calls.append((test, error))
43 def addSuccess(self, test):
44 self.success_calls.append(test)
46 def stopTest(self, test):
47 self.end_calls.append(test)
49 def startTest(self, test):
50 self.start_calls.append(test)
52 except AttributeError:
53 MockTestProtocolServer = None
56 class TestMockTestProtocolServer(unittest.TestCase):
58 def test_start_test(self):
59 protocol = MockTestProtocolServerClient()
60 protocol.startTest(subunit.RemotedTestCase("test old mcdonald"))
61 self.assertEqual(protocol.start_calls,
62 [subunit.RemotedTestCase("test old mcdonald")])
63 self.assertEqual(protocol.end_calls, [])
64 self.assertEqual(protocol.error_calls, [])
65 self.assertEqual(protocol.failure_calls, [])
66 self.assertEqual(protocol.success_calls, [])
68 def test_add_error(self):
69 protocol = MockTestProtocolServerClient()
70 protocol.addError(subunit.RemotedTestCase("old mcdonald"),
71 subunit.RemoteError("omg it works"))
72 self.assertEqual(protocol.start_calls, [])
73 self.assertEqual(protocol.end_calls, [])
74 self.assertEqual(protocol.error_calls, [(
75 subunit.RemotedTestCase("old mcdonald"),
76 subunit.RemoteError("omg it works"))])
77 self.assertEqual(protocol.failure_calls, [])
78 self.assertEqual(protocol.success_calls, [])
80 def test_add_failure(self):
81 protocol = MockTestProtocolServerClient()
82 protocol.addFailure(subunit.RemotedTestCase("old mcdonald"),
83 subunit.RemoteError("omg it works"))
84 self.assertEqual(protocol.start_calls, [])
85 self.assertEqual(protocol.end_calls, [])
86 self.assertEqual(protocol.error_calls, [])
87 self.assertEqual(protocol.failure_calls, [
88 (subunit.RemotedTestCase("old mcdonald"),
89 subunit.RemoteError("omg it works"))])
90 self.assertEqual(protocol.success_calls, [])
92 def test_add_success(self):
93 protocol = MockTestProtocolServerClient()
94 protocol.addSuccess(subunit.RemotedTestCase("test old mcdonald"))
95 self.assertEqual(protocol.start_calls, [])
96 self.assertEqual(protocol.end_calls, [])
97 self.assertEqual(protocol.error_calls, [])
98 self.assertEqual(protocol.failure_calls, [])
99 self.assertEqual(protocol.success_calls,
100 [subunit.RemotedTestCase("test old mcdonald")])
102 def test_end_test(self):
103 protocol = MockTestProtocolServerClient()
104 protocol.stopTest(subunit.RemotedTestCase("test old mcdonald"))
105 self.assertEqual(protocol.end_calls,
106 [subunit.RemotedTestCase("test old mcdonald")])
107 self.assertEqual(protocol.error_calls, [])
108 self.assertEqual(protocol.failure_calls, [])
109 self.assertEqual(protocol.success_calls, [])
110 self.assertEqual(protocol.start_calls, [])
112 class TestTestImports(unittest.TestCase):
114 def test_imports(self):
115 from subunit import TestProtocolServer
116 from subunit import RemotedTestCase
117 from subunit import RemoteError
118 from subunit import ExecTestCase
121 class TestTestProtocolServerPipe(unittest.TestCase):
123 def test_story(self):
124 client = unittest.TestResult()
125 protocol = subunit.TestProtocolServer(client)
126 pipe = StringIO("test old mcdonald\n"
127 "success old mcdonald\n"
129 "failure bing crosby [\n"
130 "foo.c:53:ERROR invalid state\n"
134 protocol.readFrom(pipe)
135 mcdonald = subunit.RemotedTestCase("old mcdonald")
136 bing = subunit.RemotedTestCase("bing crosby")
137 an_error = subunit.RemotedTestCase("an error")
138 self.assertEqual(client.errors,
139 [(an_error, 'RemoteError:\n\n\n')])
140 self.assertEqual(client.failures,
142 "RemoteError:\nfoo.c:53:ERROR invalid state\n\n")])
143 self.assertEqual(client.testsRun, 3)
146 class TestTestProtocolServerStartTest(unittest.TestCase):
149 self.client = MockTestProtocolServerClient()
150 self.protocol = subunit.TestProtocolServer(self.client)
152 def test_start_test(self):
153 self.protocol.lineReceived("test old mcdonald\n")
154 self.assertEqual(self.client.start_calls,
155 [subunit.RemotedTestCase("old mcdonald")])
157 def test_start_testing(self):
158 self.protocol.lineReceived("testing old mcdonald\n")
159 self.assertEqual(self.client.start_calls,
160 [subunit.RemotedTestCase("old mcdonald")])
162 def test_start_test_colon(self):
163 self.protocol.lineReceived("test: old mcdonald\n")
164 self.assertEqual(self.client.start_calls,
165 [subunit.RemotedTestCase("old mcdonald")])
167 def test_start_testing_colon(self):
168 self.protocol.lineReceived("testing: old mcdonald\n")
169 self.assertEqual(self.client.start_calls,
170 [subunit.RemotedTestCase("old mcdonald")])
173 class TestTestProtocolServerPassThrough(unittest.TestCase):
176 from StringIO import StringIO
177 self.real_stdout = sys.stdout
178 self.stdout = StringIO()
179 sys.stdout = self.stdout
180 self.test = subunit.RemotedTestCase("old mcdonald")
181 self.client = MockTestProtocolServerClient()
182 self.protocol = subunit.TestProtocolServer(self.client)
185 sys.stdout = self.real_stdout
187 def keywords_before_test(self):
188 self.protocol.lineReceived("failure a\n")
189 self.protocol.lineReceived("failure: a\n")
190 self.protocol.lineReceived("error a\n")
191 self.protocol.lineReceived("error: a\n")
192 self.protocol.lineReceived("success a\n")
193 self.protocol.lineReceived("success: a\n")
194 self.protocol.lineReceived("successful a\n")
195 self.protocol.lineReceived("successful: a\n")
196 self.protocol.lineReceived("]\n")
197 self.assertEqual(self.stdout.getvalue(), "failure a\n"
207 def test_keywords_before_test(self):
208 self.keywords_before_test()
209 self.assertEqual(self.client.start_calls, [])
210 self.assertEqual(self.client.error_calls, [])
211 self.assertEqual(self.client.failure_calls, [])
212 self.assertEqual(self.client.success_calls, [])
214 def test_keywords_after_error(self):
215 self.protocol.lineReceived("test old mcdonald\n")
216 self.protocol.lineReceived("error old mcdonald\n")
217 self.keywords_before_test()
218 self.assertEqual(self.client.start_calls, [self.test])
219 self.assertEqual(self.client.end_calls, [self.test])
220 self.assertEqual(self.client.error_calls,
221 [(self.test, subunit.RemoteError(""))])
222 self.assertEqual(self.client.failure_calls, [])
223 self.assertEqual(self.client.success_calls, [])
225 def test_keywords_after_failure(self):
226 self.protocol.lineReceived("test old mcdonald\n")
227 self.protocol.lineReceived("failure old mcdonald\n")
228 self.keywords_before_test()
229 self.assertEqual(self.client.start_calls, [self.test])
230 self.assertEqual(self.client.end_calls, [self.test])
231 self.assertEqual(self.client.error_calls, [])
232 self.assertEqual(self.client.failure_calls,
233 [(self.test, subunit.RemoteError())])
234 self.assertEqual(self.client.success_calls, [])
236 def test_keywords_after_success(self):
237 self.protocol.lineReceived("test old mcdonald\n")
238 self.protocol.lineReceived("success old mcdonald\n")
239 self.keywords_before_test()
240 self.assertEqual(self.client.start_calls, [self.test])
241 self.assertEqual(self.client.end_calls, [self.test])
242 self.assertEqual(self.client.error_calls, [])
243 self.assertEqual(self.client.failure_calls, [])
244 self.assertEqual(self.client.success_calls, [self.test])
246 def test_keywords_after_test(self):
247 self.protocol.lineReceived("test old mcdonald\n")
248 self.protocol.lineReceived("test old mcdonald\n")
249 self.protocol.lineReceived("failure a\n")
250 self.protocol.lineReceived("failure: a\n")
251 self.protocol.lineReceived("error a\n")
252 self.protocol.lineReceived("error: a\n")
253 self.protocol.lineReceived("success a\n")
254 self.protocol.lineReceived("success: a\n")
255 self.protocol.lineReceived("successful a\n")
256 self.protocol.lineReceived("successful: a\n")
257 self.protocol.lineReceived("]\n")
258 self.protocol.lineReceived("failure old mcdonald\n")
259 self.assertEqual(self.stdout.getvalue(), "test old mcdonald\n"
269 self.assertEqual(self.client.start_calls, [self.test])
270 self.assertEqual(self.client.end_calls, [self.test])
271 self.assertEqual(self.client.failure_calls,
272 [(self.test, subunit.RemoteError())])
273 self.assertEqual(self.client.error_calls, [])
274 self.assertEqual(self.client.success_calls, [])
276 def test_keywords_during_failure(self):
277 self.protocol.lineReceived("test old mcdonald\n")
278 self.protocol.lineReceived("failure: old mcdonald [\n")
279 self.protocol.lineReceived("test old mcdonald\n")
280 self.protocol.lineReceived("failure a\n")
281 self.protocol.lineReceived("failure: a\n")
282 self.protocol.lineReceived("error a\n")
283 self.protocol.lineReceived("error: a\n")
284 self.protocol.lineReceived("success a\n")
285 self.protocol.lineReceived("success: a\n")
286 self.protocol.lineReceived("successful a\n")
287 self.protocol.lineReceived("successful: a\n")
288 self.protocol.lineReceived(" ]\n")
289 self.protocol.lineReceived("]\n")
290 self.assertEqual(self.stdout.getvalue(), "")
291 self.assertEqual(self.client.start_calls, [self.test])
292 self.assertEqual(self.client.failure_calls,
293 [(self.test, subunit.RemoteError("test old mcdonald\n"
303 self.assertEqual(self.client.end_calls, [self.test])
304 self.assertEqual(self.client.error_calls, [])
305 self.assertEqual(self.client.success_calls, [])
308 class TestTestProtocolServerLostConnection(unittest.TestCase):
311 self.client = MockTestProtocolServerClient()
312 self.protocol = subunit.TestProtocolServer(self.client)
313 self.test = subunit.RemotedTestCase("old mcdonald")
315 def test_lost_connection_no_input(self):
316 self.protocol.lostConnection()
317 self.assertEqual(self.client.start_calls, [])
318 self.assertEqual(self.client.error_calls, [])
319 self.assertEqual(self.client.failure_calls, [])
320 self.assertEqual(self.client.success_calls, [])
322 def test_lost_connection_after_start(self):
323 self.protocol.lineReceived("test old mcdonald\n")
324 self.protocol.lostConnection()
325 self.assertEqual(self.client.start_calls, [self.test])
326 self.assertEqual(self.client.end_calls, [self.test])
327 self.assertEqual(self.client.error_calls, [
328 (self.test, subunit.RemoteError("lost connection during "
329 "test 'old mcdonald'"))])
330 self.assertEqual(self.client.failure_calls, [])
331 self.assertEqual(self.client.success_calls, [])
333 def test_lost_connected_after_error(self):
334 self.protocol.lineReceived("test old mcdonald\n")
335 self.protocol.lineReceived("error old mcdonald\n")
336 self.protocol.lostConnection()
337 self.assertEqual(self.client.start_calls, [self.test])
338 self.assertEqual(self.client.failure_calls, [])
339 self.assertEqual(self.client.end_calls, [self.test])
340 self.assertEqual(self.client.error_calls, [
341 (self.test, subunit.RemoteError(""))])
342 self.assertEqual(self.client.success_calls, [])
344 def test_lost_connection_during_error(self):
345 self.protocol.lineReceived("test old mcdonald\n")
346 self.protocol.lineReceived("error old mcdonald [\n")
347 self.protocol.lostConnection()
348 self.assertEqual(self.client.start_calls, [self.test])
349 self.assertEqual(self.client.end_calls, [self.test])
350 self.assertEqual(self.client.error_calls, [
351 (self.test, subunit.RemoteError("lost connection during error "
352 "report of test 'old mcdonald'"))])
353 self.assertEqual(self.client.failure_calls, [])
354 self.assertEqual(self.client.success_calls, [])
356 def test_lost_connected_after_failure(self):
357 self.protocol.lineReceived("test old mcdonald\n")
358 self.protocol.lineReceived("failure old mcdonald\n")
359 self.protocol.lostConnection()
360 test = subunit.RemotedTestCase("old mcdonald")
361 self.assertEqual(self.client.start_calls, [self.test])
362 self.assertEqual(self.client.end_calls, [self.test])
363 self.assertEqual(self.client.error_calls, [])
364 self.assertEqual(self.client.failure_calls,
365 [(self.test, subunit.RemoteError())])
366 self.assertEqual(self.client.success_calls, [])
368 def test_lost_connection_during_failure(self):
369 self.protocol.lineReceived("test old mcdonald\n")
370 self.protocol.lineReceived("failure old mcdonald [\n")
371 self.protocol.lostConnection()
372 self.assertEqual(self.client.start_calls, [self.test])
373 self.assertEqual(self.client.end_calls, [self.test])
374 self.assertEqual(self.client.error_calls,
376 subunit.RemoteError("lost connection during "
378 " of test 'old mcdonald'"))])
379 self.assertEqual(self.client.failure_calls, [])
380 self.assertEqual(self.client.success_calls, [])
382 def test_lost_connection_after_success(self):
383 self.protocol.lineReceived("test old mcdonald\n")
384 self.protocol.lineReceived("success old mcdonald\n")
385 self.protocol.lostConnection()
386 self.assertEqual(self.client.start_calls, [self.test])
387 self.assertEqual(self.client.end_calls, [self.test])
388 self.assertEqual(self.client.error_calls, [])
389 self.assertEqual(self.client.failure_calls, [])
390 self.assertEqual(self.client.success_calls, [self.test])
393 class TestTestProtocolServerAddError(unittest.TestCase):
396 self.client = MockTestProtocolServerClient()
397 self.protocol = subunit.TestProtocolServer(self.client)
398 self.protocol.lineReceived("test mcdonalds farm\n")
399 self.test = subunit.RemotedTestCase("mcdonalds farm")
401 def simple_error_keyword(self, keyword):
402 self.protocol.lineReceived("%s mcdonalds farm\n" % keyword)
403 self.assertEqual(self.client.start_calls, [self.test])
404 self.assertEqual(self.client.end_calls, [self.test])
405 self.assertEqual(self.client.error_calls, [
406 (self.test, subunit.RemoteError(""))])
407 self.assertEqual(self.client.failure_calls, [])
409 def test_simple_error(self):
410 self.simple_error_keyword("error")
412 def test_simple_error_colon(self):
413 self.simple_error_keyword("error:")
415 def test_error_empty_message(self):
416 self.protocol.lineReceived("error mcdonalds farm [\n")
417 self.protocol.lineReceived("]\n")
418 self.assertEqual(self.client.start_calls, [self.test])
419 self.assertEqual(self.client.end_calls, [self.test])
420 self.assertEqual(self.client.error_calls, [
421 (self.test, subunit.RemoteError(""))])
422 self.assertEqual(self.client.failure_calls, [])
424 def error_quoted_bracket(self, keyword):
425 self.protocol.lineReceived("%s mcdonalds farm [\n" % keyword)
426 self.protocol.lineReceived(" ]\n")
427 self.protocol.lineReceived("]\n")
428 self.assertEqual(self.client.start_calls, [self.test])
429 self.assertEqual(self.client.end_calls, [self.test])
430 self.assertEqual(self.client.error_calls, [
431 (self.test, subunit.RemoteError("]\n"))])
432 self.assertEqual(self.client.failure_calls, [])
434 def test_error_quoted_bracket(self):
435 self.error_quoted_bracket("error")
437 def test_error_colon_quoted_bracket(self):
438 self.error_quoted_bracket("error:")
441 class TestTestProtocolServerAddFailure(unittest.TestCase):
444 self.client = MockTestProtocolServerClient()
445 self.protocol = subunit.TestProtocolServer(self.client)
446 self.protocol.lineReceived("test mcdonalds farm\n")
447 self.test = subunit.RemotedTestCase("mcdonalds farm")
449 def simple_failure_keyword(self, keyword):
450 self.protocol.lineReceived("%s mcdonalds farm\n" % keyword)
451 self.assertEqual(self.client.start_calls, [self.test])
452 self.assertEqual(self.client.end_calls, [self.test])
453 self.assertEqual(self.client.error_calls, [])
454 self.assertEqual(self.client.failure_calls,
455 [(self.test, subunit.RemoteError())])
457 def test_simple_failure(self):
458 self.simple_failure_keyword("failure")
460 def test_simple_failure_colon(self):
461 self.simple_failure_keyword("failure:")
463 def test_failure_empty_message(self):
464 self.protocol.lineReceived("failure mcdonalds farm [\n")
465 self.protocol.lineReceived("]\n")
466 self.assertEqual(self.client.start_calls, [self.test])
467 self.assertEqual(self.client.end_calls, [self.test])
468 self.assertEqual(self.client.error_calls, [])
469 self.assertEqual(self.client.failure_calls,
470 [(self.test, subunit.RemoteError())])
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")
476 self.assertEqual(self.client.start_calls, [self.test])
477 self.assertEqual(self.client.end_calls, [self.test])
478 self.assertEqual(self.client.error_calls, [])
479 self.assertEqual(self.client.failure_calls,
480 [(self.test, subunit.RemoteError("]\n"))])
482 def test_failure_quoted_bracket(self):
483 self.failure_quoted_bracket("failure")
485 def test_failure_colon_quoted_bracket(self):
486 self.failure_quoted_bracket("failure:")
489 class TestTestProtocolServerAddSuccess(unittest.TestCase):
492 self.client = MockTestProtocolServerClient()
493 self.protocol = subunit.TestProtocolServer(self.client)
494 self.protocol.lineReceived("test mcdonalds farm\n")
495 self.test = subunit.RemotedTestCase("mcdonalds farm")
497 def simple_success_keyword(self, keyword):
498 self.protocol.lineReceived("%s mcdonalds farm\n" % keyword)
499 self.assertEqual(self.client.start_calls, [self.test])
500 self.assertEqual(self.client.end_calls, [self.test])
501 self.assertEqual(self.client.error_calls, [])
502 self.assertEqual(self.client.success_calls, [self.test])
504 def test_simple_success(self):
505 self.simple_success_keyword("failure")
507 def test_simple_success_colon(self):
508 self.simple_success_keyword("failure:")
510 def test_simple_success(self):
511 self.simple_success_keyword("successful")
513 def test_simple_success_colon(self):
514 self.simple_success_keyword("successful:")
517 class TestRemotedTestCase(unittest.TestCase):
519 def test_simple(self):
520 test = subunit.RemotedTestCase("A test description")
521 self.assertRaises(NotImplementedError, test.setUp)
522 self.assertRaises(NotImplementedError, test.tearDown)
523 self.assertEqual("A test description",
524 test.shortDescription())
525 self.assertEqual("subunit.RemotedTestCase.A test description",
527 self.assertEqual("A test description (subunit.RemotedTestCase)", "%s" % test)
528 self.assertEqual("<subunit.RemotedTestCase description="
529 "'A test description'>", "%r" % test)
530 result = unittest.TestResult()
532 self.assertEqual([(test, "RemoteError:\n"
533 "Cannot run RemotedTestCases.\n\n")],
535 self.assertEqual(1, result.testsRun)
536 another_test = subunit.RemotedTestCase("A test description")
537 self.assertEqual(test, another_test)
538 different_test = subunit.RemotedTestCase("ofo")
539 self.assertNotEqual(test, different_test)
540 self.assertNotEqual(another_test, different_test)
543 class TestRemoteError(unittest.TestCase):
546 error = subunit.RemoteError("Something went wrong")
547 another_error = subunit.RemoteError("Something went wrong")
548 different_error = subunit.RemoteError("boo!")
549 self.assertEqual(error, another_error)
550 self.assertNotEqual(error, different_error)
551 self.assertNotEqual(different_error, another_error)
553 def test_empty_constructor(self):
554 self.assertEqual(subunit.RemoteError(), subunit.RemoteError(""))
556 class TestExecTestCase(unittest.TestCase):
558 class SampleExecTestCase(subunit.ExecTestCase):
560 def test_sample_method(self):
561 """./lib/subunit/tests/sample-script.py"""
562 # the sample script runs three tests, one each
563 # that fails, errors and succeeds
566 def test_construct(self):
567 test = self.SampleExecTestCase("test_sample_method")
568 self.assertEqual(test.script, "./lib/subunit/tests/sample-script.py")
571 runner = MockTestProtocolServerClient()
572 test = self.SampleExecTestCase("test_sample_method")
574 mcdonald = subunit.RemotedTestCase("old mcdonald")
575 bing = subunit.RemotedTestCase("bing crosby")
576 an_error = subunit.RemotedTestCase("an error")
577 self.assertEqual(runner.error_calls,
578 [(an_error, subunit.RemoteError())])
579 self.assertEqual(runner.failure_calls,
582 "foo.c:53:ERROR invalid state\n"))])
583 self.assertEqual(runner.start_calls, [mcdonald, bing, an_error])
584 self.assertEqual(runner.end_calls, [mcdonald, bing, an_error])
586 def test_debug(self):
587 test = self.SampleExecTestCase("test_sample_method")
590 def test_count_test_cases(self):
591 """TODO run the child process and count responses to determine the count."""
593 class DoExecTestCase(subunit.ExecTestCase):
595 def test_working_script(self):
596 """./lib/subunit/tests/sample-two-script.py"""
600 loader = subunit.tests.TestUtil.TestLoader()
601 result = loader.loadTestsFromName(__name__)