1 # Copyright (c) 2008-2011 testtools developers. See LICENSE for details.
3 """Tests for extensions to the base test library."""
5 from doctest import ELLIPSIS
6 from pprint import pformat
10 from testtools import (
15 clone_test_with_new_id,
22 from testtools.compat import (
26 from testtools.matchers import (
33 from testtools.testresult.doubles import (
38 from testtools.testresult.real import TestResult
39 from testtools.tests.helpers import (
45 exec('from __future__ import with_statement')
49 from testtools.tests.test_with_with import *
52 class TestPlaceHolder(TestCase):
54 run_test_with = FullStackRunTest
56 def makePlaceHolder(self, test_id="foo", short_description=None):
57 return PlaceHolder(test_id, short_description)
59 def test_id_comes_from_constructor(self):
60 # The id() of a PlaceHolder is whatever you pass into the constructor.
61 test = PlaceHolder("test id")
62 self.assertEqual("test id", test.id())
64 def test_shortDescription_is_id(self):
65 # The shortDescription() of a PlaceHolder is the id, by default.
66 test = PlaceHolder("test id")
67 self.assertEqual(test.id(), test.shortDescription())
69 def test_shortDescription_specified(self):
70 # If a shortDescription is provided to the constructor, then
71 # shortDescription() returns that instead.
72 test = PlaceHolder("test id", "description")
73 self.assertEqual("description", test.shortDescription())
75 def test_repr_just_id(self):
76 # repr(placeholder) shows you how the object was constructed.
77 test = PlaceHolder("test id")
79 "<testtools.testcase.PlaceHolder(%s)>" % repr(test.id()),
82 def test_repr_with_description(self):
83 # repr(placeholder) shows you how the object was constructed.
84 test = PlaceHolder("test id", "description")
86 "<testtools.testcase.PlaceHolder(%r, %r)>" % (
87 test.id(), test.shortDescription()),
90 def test_counts_as_one_test(self):
91 # A placeholder test counts as one test.
92 test = self.makePlaceHolder()
93 self.assertEqual(1, test.countTestCases())
95 def test_str_is_id(self):
96 # str(placeholder) is always the id(). We are not barbarians.
97 test = self.makePlaceHolder()
98 self.assertEqual(test.id(), str(test))
100 def test_runs_as_success(self):
101 # When run, a PlaceHolder test records a success.
102 test = self.makePlaceHolder()
104 test.run(LoggingResult(log))
106 [('startTest', test), ('addSuccess', test), ('stopTest', test)],
109 def test_call_is_run(self):
110 # A PlaceHolder can be called, in which case it behaves like run.
111 test = self.makePlaceHolder()
113 test.run(LoggingResult(run_log))
115 test(LoggingResult(call_log))
116 self.assertEqual(run_log, call_log)
118 def test_runs_without_result(self):
119 # A PlaceHolder can be run without a result, in which case there's no
120 # way to actually get at the result.
121 self.makePlaceHolder().run()
123 def test_debug(self):
124 # A PlaceHolder can be debugged.
125 self.makePlaceHolder().debug()
128 class TestErrorHolder(TestCase):
130 run_test_with = FullStackRunTest
132 def makeException(self):
134 raise RuntimeError("danger danger")
136 return sys.exc_info()
138 def makePlaceHolder(self, test_id="foo", error=None,
139 short_description=None):
141 error = self.makeException()
142 return ErrorHolder(test_id, error, short_description)
144 def test_id_comes_from_constructor(self):
145 # The id() of a PlaceHolder is whatever you pass into the constructor.
146 test = ErrorHolder("test id", self.makeException())
147 self.assertEqual("test id", test.id())
149 def test_shortDescription_is_id(self):
150 # The shortDescription() of a PlaceHolder is the id, by default.
151 test = ErrorHolder("test id", self.makeException())
152 self.assertEqual(test.id(), test.shortDescription())
154 def test_shortDescription_specified(self):
155 # If a shortDescription is provided to the constructor, then
156 # shortDescription() returns that instead.
157 test = ErrorHolder("test id", self.makeException(), "description")
158 self.assertEqual("description", test.shortDescription())
160 def test_repr_just_id(self):
161 # repr(placeholder) shows you how the object was constructed.
162 error = self.makeException()
163 test = ErrorHolder("test id", error)
165 "<testtools.testcase.ErrorHolder(%r, %r)>" % (test.id(), error),
168 def test_repr_with_description(self):
169 # repr(placeholder) shows you how the object was constructed.
170 error = self.makeException()
171 test = ErrorHolder("test id", error, "description")
173 "<testtools.testcase.ErrorHolder(%r, %r, %r)>" % (
174 test.id(), error, test.shortDescription()),
177 def test_counts_as_one_test(self):
178 # A placeholder test counts as one test.
179 test = self.makePlaceHolder()
180 self.assertEqual(1, test.countTestCases())
182 def test_str_is_id(self):
183 # str(placeholder) is always the id(). We are not barbarians.
184 test = self.makePlaceHolder()
185 self.assertEqual(test.id(), str(test))
187 def test_runs_as_error(self):
188 # When run, a PlaceHolder test records a success.
189 error = self.makeException()
190 test = self.makePlaceHolder(error=error)
192 test.run(LoggingResult(log))
194 [('startTest', test),
195 ('addError', test, error),
196 ('stopTest', test)], log)
198 def test_call_is_run(self):
199 # A PlaceHolder can be called, in which case it behaves like run.
200 test = self.makePlaceHolder()
202 test.run(LoggingResult(run_log))
204 test(LoggingResult(call_log))
205 self.assertEqual(run_log, call_log)
207 def test_runs_without_result(self):
208 # A PlaceHolder can be run without a result, in which case there's no
209 # way to actually get at the result.
210 self.makePlaceHolder().run()
212 def test_debug(self):
213 # A PlaceHolder can be debugged.
214 self.makePlaceHolder().debug()
217 class TestEquality(TestCase):
218 """Test ``TestCase``'s equality implementation."""
220 run_test_with = FullStackRunTest
222 def test_identicalIsEqual(self):
223 # TestCase's are equal if they are identical.
224 self.assertEqual(self, self)
226 def test_nonIdenticalInUnequal(self):
227 # TestCase's are not equal if they are not identical.
228 self.assertNotEqual(TestCase(methodName='run'),
229 TestCase(methodName='skip'))
232 class TestAssertions(TestCase):
233 """Test assertions in TestCase."""
235 run_test_with = FullStackRunTest
237 def raiseError(self, exceptionFactory, *args, **kwargs):
238 raise exceptionFactory(*args, **kwargs)
240 def test_formatTypes_single(self):
241 # Given a single class, _formatTypes returns the name.
244 self.assertEqual('Foo', self._formatTypes(Foo))
246 def test_formatTypes_multiple(self):
247 # Given multiple types, _formatTypes returns the names joined by
253 self.assertEqual('Foo, Bar', self._formatTypes([Foo, Bar]))
255 def test_assertRaises(self):
256 # assertRaises asserts that a callable raises a particular exception.
257 self.assertRaises(RuntimeError, self.raiseError, RuntimeError)
259 def test_assertRaises_fails_when_no_error_raised(self):
260 # assertRaises raises self.failureException when it's passed a
261 # callable that raises no error.
263 self.assertFails("<function <lambda> at ...> returned ('orange', 42)",
264 self.assertRaises, RuntimeError, lambda: ret)
266 def test_assertRaises_fails_when_different_error_raised(self):
267 # assertRaises re-raises an exception that it didn't expect.
268 self.assertThat(lambda: self.assertRaises(RuntimeError,
269 self.raiseError, ZeroDivisionError),
270 Raises(MatchesException(ZeroDivisionError)))
272 def test_assertRaises_returns_the_raised_exception(self):
273 # assertRaises returns the exception object that was raised. This is
274 # useful for testing that exceptions have the right message.
276 # This contraption stores the raised exception, so we can compare it
277 # to the return value of assertRaises.
278 raisedExceptions = []
281 raise RuntimeError('Deliberate error')
283 raisedExceptions.append(sys.exc_info()[1])
286 exception = self.assertRaises(RuntimeError, raiseError)
287 self.assertEqual(1, len(raisedExceptions))
289 exception is raisedExceptions[0],
290 "%r is not %r" % (exception, raisedExceptions[0]))
292 def test_assertRaises_with_multiple_exceptions(self):
293 # assertRaises((ExceptionOne, ExceptionTwo), function) asserts that
294 # function raises one of ExceptionTwo or ExceptionOne.
295 expectedExceptions = (RuntimeError, ZeroDivisionError)
297 expectedExceptions, self.raiseError, expectedExceptions[0])
299 expectedExceptions, self.raiseError, expectedExceptions[1])
301 def test_assertRaises_with_multiple_exceptions_failure_mode(self):
302 # If assertRaises is called expecting one of a group of exceptions and
303 # a callable that doesn't raise an exception, then fail with an
304 # appropriate error message.
305 expectedExceptions = (RuntimeError, ZeroDivisionError)
306 failure = self.assertRaises(
307 self.failureException,
308 self.assertRaises, expectedExceptions, lambda: None)
309 self.assertFails('<function <lambda> at ...> returned None',
310 self.assertRaises, expectedExceptions, lambda: None)
312 def assertFails(self, message, function, *args, **kwargs):
313 """Assert that function raises a failure with the given message."""
314 failure = self.assertRaises(
315 self.failureException, function, *args, **kwargs)
316 self.assertThat(failure, DocTestMatches(message, ELLIPSIS))
318 def test_assertIn_success(self):
319 # assertIn(needle, haystack) asserts that 'needle' is in 'haystack'.
320 self.assertIn(3, range(10))
321 self.assertIn('foo', 'foo bar baz')
322 self.assertIn('foo', 'foo bar baz'.split())
324 def test_assertIn_failure(self):
325 # assertIn(needle, haystack) fails the test when 'needle' is not in
327 self.assertFails('3 not in [0, 1, 2]', self.assertIn, 3, [0, 1, 2])
329 '%r not in %r' % ('qux', 'foo bar baz'),
330 self.assertIn, 'qux', 'foo bar baz')
332 def test_assertNotIn_success(self):
333 # assertNotIn(needle, haystack) asserts that 'needle' is not in
335 self.assertNotIn(3, [0, 1, 2])
336 self.assertNotIn('qux', 'foo bar baz')
338 def test_assertNotIn_failure(self):
339 # assertNotIn(needle, haystack) fails the test when 'needle' is in
341 self.assertFails('[1, 2, 3] matches Contains(3)', self.assertNotIn,
344 "'foo bar baz' matches Contains('foo')",
345 self.assertNotIn, 'foo', 'foo bar baz')
347 def test_assertIsInstance(self):
348 # assertIsInstance asserts that an object is an instance of a class.
351 """Simple class for testing assertIsInstance."""
354 self.assertIsInstance(foo, Foo)
356 def test_assertIsInstance_multiple_classes(self):
357 # assertIsInstance asserts that an object is an instance of one of a
361 """Simple class for testing assertIsInstance."""
364 """Another simple class for testing assertIsInstance."""
367 self.assertIsInstance(foo, (Foo, Bar))
368 self.assertIsInstance(Bar(), (Foo, Bar))
370 def test_assertIsInstance_failure(self):
371 # assertIsInstance(obj, klass) fails the test when obj is not an
375 """Simple class for testing assertIsInstance."""
378 "'42' is not an instance of %s" % self._formatTypes(Foo),
379 self.assertIsInstance, 42, Foo)
381 def test_assertIsInstance_failure_multiple_classes(self):
382 # assertIsInstance(obj, (klass1, klass2)) fails the test when obj is
383 # not an instance of klass1 or klass2.
386 """Simple class for testing assertIsInstance."""
389 """Another simple class for testing assertIsInstance."""
392 "'42' is not an instance of any of (%s)" % self._formatTypes([Foo, Bar]),
393 self.assertIsInstance, 42, (Foo, Bar))
395 def test_assertIsInstance_overridden_message(self):
396 # assertIsInstance(obj, klass, msg) permits a custom message.
397 self.assertFails("'42' is not an instance of str: foo",
398 self.assertIsInstance, 42, str, "foo")
400 def test_assertIs(self):
401 # assertIs asserts that an object is identical to another object.
402 self.assertIs(None, None)
404 self.assertIs(some_list, some_list)
405 some_object = object()
406 self.assertIs(some_object, some_object)
408 def test_assertIs_fails(self):
409 # assertIs raises assertion errors if one object is not identical to
411 self.assertFails('None is not 42', self.assertIs, None, 42)
412 self.assertFails('[42] is not [42]', self.assertIs, [42], [42])
414 def test_assertIs_fails_with_message(self):
415 # assertIs raises assertion errors if one object is not identical to
416 # another, and includes a user-supplied message, if it's provided.
418 'None is not 42: foo bar', self.assertIs, None, 42, 'foo bar')
420 def test_assertIsNot(self):
421 # assertIsNot asserts that an object is not identical to another
423 self.assertIsNot(None, 42)
424 self.assertIsNot([42], [42])
425 self.assertIsNot(object(), object())
427 def test_assertIsNot_fails(self):
428 # assertIsNot raises assertion errors if one object is identical to
430 self.assertFails('None matches Is(None)', self.assertIsNot, None, None)
433 '[42] matches Is([42])', self.assertIsNot, some_list, some_list)
435 def test_assertIsNot_fails_with_message(self):
436 # assertIsNot raises assertion errors if one object is identical to
437 # another, and includes a user-supplied message if it's provided.
439 'None matches Is(None): foo bar', self.assertIsNot, None, None,
442 def test_assertThat_matches_clean(self):
443 class Matcher(object):
444 def match(self, foo):
446 self.assertThat("foo", Matcher())
448 def test_assertThat_mismatch_raises_description(self):
450 class Mismatch(object):
451 def __init__(self, thing):
454 calls.append(('describe_diff', self.thing))
455 return "object is not a thing"
456 def get_details(self):
458 class Matcher(object):
459 def match(self, thing):
460 calls.append(('match', thing))
461 return Mismatch(thing)
463 calls.append(('__str__',))
464 return "a description"
465 class Test(TestCase):
467 self.assertThat("foo", Matcher())
468 result = Test("test").run()
471 ('describe_diff', "foo"),
473 self.assertFalse(result.wasSuccessful())
475 def test_assertThat_output(self):
477 matcher = Equals('bar')
478 expected = matcher.match(matchee).describe()
479 self.assertFails(expected, self.assertThat, matchee, matcher)
481 def test_assertThat_message_is_annotated(self):
483 matcher = Equals('bar')
484 expected = Annotate('woo', matcher).match(matchee).describe()
485 self.assertFails(expected, self.assertThat, matchee, matcher, 'woo')
487 def test_assertThat_verbose_output(self):
489 matcher = Equals('bar')
491 'Match failed. Matchee: %r\n'
493 'Difference: %s\n' % (
496 matcher.match(matchee).describe(),
499 expected, self.assertThat, matchee, matcher, verbose=True)
501 def get_error_string(self, e):
502 """Get the string showing how 'e' would be formatted in test output.
504 This is a little bit hacky, since it's designed to give consistent
505 output regardless of Python version.
507 In testtools, TestResult._exc_info_to_unicode is the point of dispatch
508 between various different implementations of methods that format
509 exceptions, so that's what we have to call. However, that method cares
510 about stack traces and formats the exception class. We don't care
511 about either of these, so we take its output and parse it a little.
513 error = TestResult()._exc_info_to_unicode((e.__class__, e, None), self)
514 # We aren't at all interested in the traceback.
515 if error.startswith('Traceback (most recent call last):\n'):
516 lines = error.splitlines(True)[1:]
517 for i, line in enumerate(lines):
518 if not line.startswith(' '):
520 error = ''.join(lines[i:])
521 # We aren't interested in how the exception type is formatted.
522 exc_class, error = error.split(': ', 1)
525 def test_assertThat_verbose_unicode(self):
526 # When assertThat is given matchees or matchers that contain non-ASCII
527 # unicode strings, we can still provide a meaningful error.
529 matcher = Equals(_u('a'))
531 'Match failed. Matchee: %s\n'
533 'Difference: %s\n\n' % (
534 repr(matchee).replace("\\xa7", matchee),
536 matcher.match(matchee).describe(),
538 e = self.assertRaises(
539 self.failureException, self.assertThat, matchee, matcher,
541 self.assertEqual(expected, self.get_error_string(e))
543 def test_assertEqual_nice_formatting(self):
544 message = "These things ought not be equal."
545 a = ['apple', 'banana', 'cherry']
546 b = {'Thatcher': 'One who mends roofs of straw',
547 'Major': 'A military officer, ranked below colonel',
548 'Blair': 'To shout loudly',
549 'Brown': 'The colour of healthy human faeces'}
550 expected_error = '\n'.join([
552 'reference = %s' % pformat(a),
553 'actual = %s' % pformat(b),
556 self.assertFails(expected_error, self.assertEqual, a, b, message)
557 self.assertFails(expected_error, self.assertEquals, a, b, message)
558 self.assertFails(expected_error, self.failUnlessEqual, a, b, message)
560 def test_assertEqual_formatting_no_message(self):
563 expected_error = "'cat' != 'dog'"
564 self.assertFails(expected_error, self.assertEqual, a, b)
565 self.assertFails(expected_error, self.assertEquals, a, b)
566 self.assertFails(expected_error, self.failUnlessEqual, a, b)
568 def test_assertEqual_non_ascii_str_with_newlines(self):
569 message = _u("Be careful mixing unicode and bytes")
571 b = "Just a longish string so the more verbose output form is used."
572 expected_error = '\n'.join([
578 'actual = %r' % (b,),
581 self.assertFails(expected_error, self.assertEqual, a, b, message)
583 def test_assertIsNone(self):
584 self.assertIsNone(None)
586 expected_error = 'None is not 0'
587 self.assertFails(expected_error, self.assertIsNone, 0)
589 def test_assertIsNotNone(self):
590 self.assertIsNotNone(0)
591 self.assertIsNotNone("0")
593 expected_error = 'None matches Is(None)'
594 self.assertFails(expected_error, self.assertIsNotNone, None)
597 class TestAddCleanup(TestCase):
598 """Tests for TestCase.addCleanup."""
600 run_test_with = FullStackRunTest
602 class LoggingTest(TestCase):
603 """A test that logs calls to setUp, runTest and tearDown."""
607 self._calls = ['setUp']
609 def brokenSetUp(self):
610 # A tearDown that deliberately fails.
611 self._calls = ['brokenSetUp']
612 raise RuntimeError('Deliberate Failure')
615 self._calls.append('runTest')
617 def brokenTest(self):
618 raise RuntimeError('Deliberate broken test')
621 self._calls.append('tearDown')
622 TestCase.tearDown(self)
626 self._result_calls = []
627 self.test = TestAddCleanup.LoggingTest('runTest')
628 self.logging_result = LoggingResult(self._result_calls)
630 def assertErrorLogEqual(self, messages):
631 self.assertEqual(messages, [call[0] for call in self._result_calls])
633 def assertTestLogEqual(self, messages):
634 """Assert that the call log equals 'messages'."""
635 case = self._result_calls[0][1]
636 self.assertEqual(messages, case._calls)
638 def logAppender(self, message):
639 """A cleanup that appends 'message' to the tests log.
641 Cleanups are callables that are added to a test by addCleanup. To
642 verify that our cleanups run in the right order, we add strings to a
643 list that acts as a log. This method returns a cleanup that will add
644 the given message to that log when run.
646 self.test._calls.append(message)
648 def test_fixture(self):
649 # A normal run of self.test logs 'setUp', 'runTest' and 'tearDown'.
650 # This test doesn't test addCleanup itself, it just sanity checks the
652 self.test.run(self.logging_result)
653 self.assertTestLogEqual(['setUp', 'runTest', 'tearDown'])
655 def test_cleanup_run_before_tearDown(self):
656 # Cleanup functions added with 'addCleanup' are called before tearDown
658 self.test.addCleanup(self.logAppender, 'cleanup')
659 self.test.run(self.logging_result)
660 self.assertTestLogEqual(['setUp', 'runTest', 'tearDown', 'cleanup'])
662 def test_add_cleanup_called_if_setUp_fails(self):
663 # Cleanup functions added with 'addCleanup' are called even if setUp
664 # fails. Note that tearDown has a different behavior: it is only
665 # called when setUp succeeds.
666 self.test.setUp = self.test.brokenSetUp
667 self.test.addCleanup(self.logAppender, 'cleanup')
668 self.test.run(self.logging_result)
669 self.assertTestLogEqual(['brokenSetUp', 'cleanup'])
671 def test_addCleanup_called_in_reverse_order(self):
672 # Cleanup functions added with 'addCleanup' are called in reverse
675 # One of the main uses of addCleanup is to dynamically create
676 # resources that need some sort of explicit tearDown. Often one
677 # resource will be created in terms of another, e.g.,
678 # self.first = self.makeFirst()
679 # self.second = self.makeSecond(self.first)
681 # When this happens, we generally want to clean up the second resource
682 # before the first one, since the second depends on the first.
683 self.test.addCleanup(self.logAppender, 'first')
684 self.test.addCleanup(self.logAppender, 'second')
685 self.test.run(self.logging_result)
686 self.assertTestLogEqual(
687 ['setUp', 'runTest', 'tearDown', 'second', 'first'])
689 def test_tearDown_runs_after_cleanup_failure(self):
690 # tearDown runs even if a cleanup function fails.
691 self.test.addCleanup(lambda: 1/0)
692 self.test.run(self.logging_result)
693 self.assertTestLogEqual(['setUp', 'runTest', 'tearDown'])
695 def test_cleanups_continue_running_after_error(self):
696 # All cleanups are always run, even if one or two of them fail.
697 self.test.addCleanup(self.logAppender, 'first')
698 self.test.addCleanup(lambda: 1/0)
699 self.test.addCleanup(self.logAppender, 'second')
700 self.test.run(self.logging_result)
701 self.assertTestLogEqual(
702 ['setUp', 'runTest', 'tearDown', 'second', 'first'])
704 def test_error_in_cleanups_are_captured(self):
705 # If a cleanup raises an error, we want to record it and fail the the
706 # test, even though we go on to run other cleanups.
707 self.test.addCleanup(lambda: 1/0)
708 self.test.run(self.logging_result)
709 self.assertErrorLogEqual(['startTest', 'addError', 'stopTest'])
711 def test_keyboard_interrupt_not_caught(self):
712 # If a cleanup raises KeyboardInterrupt, it gets reraised.
713 def raiseKeyboardInterrupt():
714 raise KeyboardInterrupt()
715 self.test.addCleanup(raiseKeyboardInterrupt)
716 self.assertThat(lambda:self.test.run(self.logging_result),
717 Raises(MatchesException(KeyboardInterrupt)))
719 def test_all_errors_from_MultipleExceptions_reported(self):
720 # When a MultipleExceptions exception is caught, all the errors are
726 exc_info1 = sys.exc_info()
730 exc_info2 = sys.exc_info()
731 raise MultipleExceptions(exc_info1, exc_info2)
732 self.test.addCleanup(raiseMany)
733 self.logging_result = ExtendedTestResult()
734 self.test.run(self.logging_result)
735 self.assertEqual(['startTest', 'addError', 'stopTest'],
736 [event[0] for event in self.logging_result._events])
737 self.assertEqual(set(['traceback', 'traceback-1']),
738 set(self.logging_result._events[1][2].keys()))
740 def test_multipleCleanupErrorsReported(self):
741 # Errors from all failing cleanups are reported as separate backtraces.
742 self.test.addCleanup(lambda: 1/0)
743 self.test.addCleanup(lambda: 1/0)
744 self.logging_result = ExtendedTestResult()
745 self.test.run(self.logging_result)
746 self.assertEqual(['startTest', 'addError', 'stopTest'],
747 [event[0] for event in self.logging_result._events])
748 self.assertEqual(set(['traceback', 'traceback-1']),
749 set(self.logging_result._events[1][2].keys()))
751 def test_multipleErrorsCoreAndCleanupReported(self):
752 # Errors from all failing cleanups are reported, with stopTest,
753 # startTest inserted.
754 self.test = TestAddCleanup.LoggingTest('brokenTest')
755 self.test.addCleanup(lambda: 1/0)
756 self.test.addCleanup(lambda: 1/0)
757 self.logging_result = ExtendedTestResult()
758 self.test.run(self.logging_result)
759 self.assertEqual(['startTest', 'addError', 'stopTest'],
760 [event[0] for event in self.logging_result._events])
761 self.assertEqual(set(['traceback', 'traceback-1', 'traceback-2']),
762 set(self.logging_result._events[1][2].keys()))
765 class TestWithDetails(TestCase):
767 run_test_with = FullStackRunTest
769 def assertDetailsProvided(self, case, expected_outcome, expected_keys):
770 """Assert that when case is run, details are provided to the result.
772 :param case: A TestCase to run.
773 :param expected_outcome: The call that should be made.
774 :param expected_keys: The keys to look for.
776 result = ExtendedTestResult()
778 case = result._events[0][1]
781 (expected_outcome, case),
784 self.assertEqual(3, len(result._events))
785 self.assertEqual(expected[0], result._events[0])
786 self.assertEqual(expected[1], result._events[1][0:2])
787 # Checking the TB is right is rather tricky. doctest line matching
788 # would help, but 'meh'.
789 self.assertEqual(sorted(expected_keys),
790 sorted(result._events[1][2].keys()))
791 self.assertEqual(expected[-1], result._events[-1])
793 def get_content(self):
794 return content.Content(
795 content.ContentType("text", "foo"), lambda: [_b('foo')])
798 class TestExpectedFailure(TestWithDetails):
799 """Tests for expected failures and unexpected successess."""
801 run_test_with = FullStackRunTest
803 def make_unexpected_case(self):
804 class Case(TestCase):
806 raise testcase._UnexpectedSuccess
810 def test_raising__UnexpectedSuccess_py27(self):
811 case = self.make_unexpected_case()
812 result = Python27TestResult()
814 case = result._events[0][1]
817 ('addUnexpectedSuccess', case),
821 def test_raising__UnexpectedSuccess_extended(self):
822 case = self.make_unexpected_case()
823 result = ExtendedTestResult()
825 case = result._events[0][1]
828 ('addUnexpectedSuccess', case, {}),
832 def make_xfail_case_xfails(self):
833 content = self.get_content()
834 class Case(TestCase):
836 self.addDetail("foo", content)
837 self.expectFailure("we are sad", self.assertEqual,
842 def make_xfail_case_succeeds(self):
843 content = self.get_content()
844 class Case(TestCase):
846 self.addDetail("foo", content)
847 self.expectFailure("we are sad", self.assertEqual,
852 def test_expectFailure_KnownFailure_extended(self):
853 case = self.make_xfail_case_xfails()
854 self.assertDetailsProvided(case, "addExpectedFailure",
855 ["foo", "traceback", "reason"])
857 def test_expectFailure_KnownFailure_unexpected_success(self):
858 case = self.make_xfail_case_succeeds()
859 self.assertDetailsProvided(case, "addUnexpectedSuccess",
863 class TestUniqueFactories(TestCase):
864 """Tests for getUniqueString and getUniqueInteger."""
866 run_test_with = FullStackRunTest
868 def test_getUniqueInteger(self):
869 # getUniqueInteger returns an integer that increments each time you
871 one = self.getUniqueInteger()
872 self.assertEqual(1, one)
873 two = self.getUniqueInteger()
874 self.assertEqual(2, two)
876 def test_getUniqueString(self):
877 # getUniqueString returns the current test id followed by a unique
879 name_one = self.getUniqueString()
880 self.assertEqual('%s-%d' % (self.id(), 1), name_one)
881 name_two = self.getUniqueString()
882 self.assertEqual('%s-%d' % (self.id(), 2), name_two)
884 def test_getUniqueString_prefix(self):
885 # If getUniqueString is given an argument, it uses that argument as
886 # the prefix of the unique string, rather than the test id.
887 name_one = self.getUniqueString('foo')
888 self.assertThat(name_one, Equals('foo-1'))
889 name_two = self.getUniqueString('bar')
890 self.assertThat(name_two, Equals('bar-2'))
893 class TestCloneTestWithNewId(TestCase):
894 """Tests for clone_test_with_new_id."""
896 run_test_with = FullStackRunTest
898 def test_clone_test_with_new_id(self):
899 class FooTestCase(TestCase):
902 test = FooTestCase('test_foo')
904 newName = self.getUniqueString()
905 newTest = clone_test_with_new_id(test, newName)
906 self.assertEqual(newName, newTest.id())
907 self.assertEqual(oldName, test.id(),
908 "the original test instance should be unchanged.")
910 def test_cloned_testcase_does_not_share_details(self):
911 """A cloned TestCase does not share the details dict."""
912 class Test(TestCase):
915 'foo', content.Content('text/plain', lambda: 'foo'))
916 orig_test = Test('test_foo')
917 cloned_test = clone_test_with_new_id(orig_test, self.getUniqueString())
918 orig_test.run(unittest.TestResult())
919 self.assertEqual('foo', orig_test.getDetails()['foo'].iter_bytes())
920 self.assertEqual(None, cloned_test.getDetails().get('foo'))
923 class TestDetailsProvided(TestWithDetails):
925 run_test_with = FullStackRunTest
927 def test_addDetail(self):
928 mycontent = self.get_content()
929 self.addDetail("foo", mycontent)
930 details = self.getDetails()
931 self.assertEqual({"foo": mycontent}, details)
933 def test_addError(self):
934 class Case(TestCase):
936 this.addDetail("foo", self.get_content())
938 self.assertDetailsProvided(Case("test"), "addError",
939 ["foo", "traceback"])
941 def test_addFailure(self):
942 class Case(TestCase):
944 this.addDetail("foo", self.get_content())
946 self.assertDetailsProvided(Case("test"), "addFailure",
947 ["foo", "traceback"])
949 def test_addSkip(self):
950 class Case(TestCase):
952 this.addDetail("foo", self.get_content())
954 self.assertDetailsProvided(Case("test"), "addSkip",
957 def test_addSucccess(self):
958 class Case(TestCase):
960 this.addDetail("foo", self.get_content())
961 self.assertDetailsProvided(Case("test"), "addSuccess",
964 def test_addUnexpectedSuccess(self):
965 class Case(TestCase):
967 this.addDetail("foo", self.get_content())
968 raise testcase._UnexpectedSuccess()
969 self.assertDetailsProvided(Case("test"), "addUnexpectedSuccess",
972 def test_addDetails_from_Mismatch(self):
973 content = self.get_content()
974 class Mismatch(object):
977 def get_details(self):
978 return {"foo": content}
979 class Matcher(object):
980 def match(self, thing):
983 return "a description"
984 class Case(TestCase):
986 self.assertThat("foo", Matcher())
987 self.assertDetailsProvided(Case("test"), "addFailure",
988 ["foo", "traceback"])
990 def test_multiple_addDetails_from_Mismatch(self):
991 content = self.get_content()
992 class Mismatch(object):
995 def get_details(self):
996 return {"foo": content, "bar": content}
997 class Matcher(object):
998 def match(self, thing):
1001 return "a description"
1002 class Case(TestCase):
1004 self.assertThat("foo", Matcher())
1005 self.assertDetailsProvided(Case("test"), "addFailure",
1006 ["bar", "foo", "traceback"])
1008 def test_addDetails_with_same_name_as_key_from_get_details(self):
1009 content = self.get_content()
1010 class Mismatch(object):
1013 def get_details(self):
1014 return {"foo": content}
1015 class Matcher(object):
1016 def match(self, thing):
1019 return "a description"
1020 class Case(TestCase):
1022 self.addDetail("foo", content)
1023 self.assertThat("foo", Matcher())
1024 self.assertDetailsProvided(Case("test"), "addFailure",
1025 ["foo", "foo-1", "traceback"])
1028 class TestSetupTearDown(TestCase):
1030 run_test_with = FullStackRunTest
1032 def test_setUpNotCalled(self):
1033 class DoesnotcallsetUp(TestCase):
1036 def test_method(self):
1038 result = unittest.TestResult()
1039 DoesnotcallsetUp('test_method').run(result)
1040 self.assertEqual(1, len(result.errors))
1042 def test_tearDownNotCalled(self):
1043 class DoesnotcalltearDown(TestCase):
1044 def test_method(self):
1048 result = unittest.TestResult()
1049 DoesnotcalltearDown('test_method').run(result)
1050 self.assertEqual(1, len(result.errors))
1053 class TestSkipping(TestCase):
1054 """Tests for skipping of tests functionality."""
1056 run_test_with = FullStackRunTest
1058 def test_skip_causes_skipException(self):
1059 self.assertThat(lambda:self.skip("Skip this test"),
1060 Raises(MatchesException(self.skipException)))
1062 def test_can_use_skipTest(self):
1063 self.assertThat(lambda:self.skipTest("Skip this test"),
1064 Raises(MatchesException(self.skipException)))
1066 def test_skip_without_reason_works(self):
1067 class Test(TestCase):
1069 raise self.skipException()
1071 result = ExtendedTestResult()
1073 self.assertEqual('addSkip', result._events[1][0])
1074 self.assertEqual('no reason given.',
1075 ''.join(result._events[1][2]['reason'].iter_text()))
1077 def test_skipException_in_setup_calls_result_addSkip(self):
1078 class TestThatRaisesInSetUp(TestCase):
1080 TestCase.setUp(self)
1081 self.skip("skipping this test")
1082 def test_that_passes(self):
1085 result = LoggingResult(calls)
1086 test = TestThatRaisesInSetUp("test_that_passes")
1088 case = result._events[0][1]
1089 self.assertEqual([('startTest', case),
1090 ('addSkip', case, "skipping this test"), ('stopTest', case)],
1093 def test_skipException_in_test_method_calls_result_addSkip(self):
1094 class SkippingTest(TestCase):
1095 def test_that_raises_skipException(self):
1096 self.skip("skipping this test")
1097 result = Python27TestResult()
1098 test = SkippingTest("test_that_raises_skipException")
1100 case = result._events[0][1]
1101 self.assertEqual([('startTest', case),
1102 ('addSkip', case, "skipping this test"), ('stopTest', case)],
1105 def test_skip__in_setup_with_old_result_object_calls_addSuccess(self):
1106 class SkippingTest(TestCase):
1108 TestCase.setUp(self)
1109 raise self.skipException("skipping this test")
1110 def test_that_raises_skipException(self):
1112 result = Python26TestResult()
1113 test = SkippingTest("test_that_raises_skipException")
1115 self.assertEqual('addSuccess', result._events[1][0])
1117 def test_skip_with_old_result_object_calls_addError(self):
1118 class SkippingTest(TestCase):
1119 def test_that_raises_skipException(self):
1120 raise self.skipException("skipping this test")
1121 result = Python26TestResult()
1122 test = SkippingTest("test_that_raises_skipException")
1124 self.assertEqual('addSuccess', result._events[1][0])
1126 def test_skip_decorator(self):
1127 class SkippingTest(TestCase):
1128 @skip("skipping this test")
1129 def test_that_is_decorated_with_skip(self):
1131 result = Python26TestResult()
1132 test = SkippingTest("test_that_is_decorated_with_skip")
1134 self.assertEqual('addSuccess', result._events[1][0])
1136 def test_skipIf_decorator(self):
1137 class SkippingTest(TestCase):
1138 @skipIf(True, "skipping this test")
1139 def test_that_is_decorated_with_skipIf(self):
1141 result = Python26TestResult()
1142 test = SkippingTest("test_that_is_decorated_with_skipIf")
1144 self.assertEqual('addSuccess', result._events[1][0])
1146 def test_skipUnless_decorator(self):
1147 class SkippingTest(TestCase):
1148 @skipUnless(False, "skipping this test")
1149 def test_that_is_decorated_with_skipUnless(self):
1151 result = Python26TestResult()
1152 test = SkippingTest("test_that_is_decorated_with_skipUnless")
1154 self.assertEqual('addSuccess', result._events[1][0])
1157 class TestOnException(TestCase):
1159 run_test_with = FullStackRunTest
1161 def test_default_works(self):
1163 class Case(TestCase):
1165 self.onException(an_exc_info)
1167 case = Case("method")
1169 self.assertThat(events, Equals([True]))
1171 def test_added_handler_works(self):
1173 class Case(TestCase):
1175 self.addOnException(events.append)
1176 self.onException(an_exc_info)
1177 case = Case("method")
1179 self.assertThat(events, Equals([an_exc_info]))
1181 def test_handler_that_raises_is_not_caught(self):
1183 class Case(TestCase):
1185 self.addOnException(events.index)
1186 self.assertThat(lambda: self.onException(an_exc_info),
1187 Raises(MatchesException(ValueError)))
1188 case = Case("method")
1190 self.assertThat(events, Equals([]))
1193 class TestPatchSupport(TestCase):
1195 run_test_with = FullStackRunTest
1197 class Case(TestCase):
1201 def test_patch(self):
1202 # TestCase.patch masks obj.attribute with the new value.
1203 self.foo = 'original'
1204 test = self.Case('test')
1205 test.patch(self, 'foo', 'patched')
1206 self.assertEqual('patched', self.foo)
1208 def test_patch_restored_after_run(self):
1209 # TestCase.patch masks obj.attribute with the new value, but restores
1210 # the original value after the test is finished.
1211 self.foo = 'original'
1212 test = self.Case('test')
1213 test.patch(self, 'foo', 'patched')
1215 self.assertEqual('original', self.foo)
1217 def test_successive_patches_apply(self):
1218 # TestCase.patch can be called multiple times per test. Each time you
1219 # call it, it overrides the original value.
1220 self.foo = 'original'
1221 test = self.Case('test')
1222 test.patch(self, 'foo', 'patched')
1223 test.patch(self, 'foo', 'second')
1224 self.assertEqual('second', self.foo)
1226 def test_successive_patches_restored_after_run(self):
1227 # TestCase.patch restores the original value, no matter how many times
1229 self.foo = 'original'
1230 test = self.Case('test')
1231 test.patch(self, 'foo', 'patched')
1232 test.patch(self, 'foo', 'second')
1234 self.assertEqual('original', self.foo)
1236 def test_patch_nonexistent_attribute(self):
1237 # TestCase.patch can be used to patch a non-existent attribute.
1238 test = self.Case('test')
1239 test.patch(self, 'doesntexist', 'patched')
1240 self.assertEqual('patched', self.doesntexist)
1242 def test_restore_nonexistent_attribute(self):
1243 # TestCase.patch can be used to patch a non-existent attribute, after
1244 # the test run, the attribute is then removed from the object.
1245 test = self.Case('test')
1246 test.patch(self, 'doesntexist', 'patched')
1249 value = getattr(self, 'doesntexist', marker)
1250 self.assertIs(marker, value)
1253 class TestTestCaseSuper(TestCase):
1255 run_test_with = FullStackRunTest
1257 def test_setup_uses_super(self):
1258 class OtherBaseCase(unittest.TestCase):
1259 setup_called = False
1261 self.setup_called = True
1262 super(OtherBaseCase, self).setUp()
1263 class OurCase(TestCase, OtherBaseCase):
1269 self.assertTrue(test.setup_called)
1271 def test_teardown_uses_super(self):
1272 class OtherBaseCase(unittest.TestCase):
1273 teardown_called = False
1275 self.teardown_called = True
1276 super(OtherBaseCase, self).tearDown()
1277 class OurCase(TestCase, OtherBaseCase):
1283 self.assertTrue(test.teardown_called)
1287 from unittest import TestLoader
1288 return TestLoader().loadTestsFromName(__name__)