1 # Copyright (c) 2008-2012 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.content import TracebackContent
27 from testtools.matchers import (
34 from testtools.testcase import Nullary
35 from testtools.testresult.doubles import (
40 from testtools.tests.helpers import (
46 exec('from __future__ import with_statement')
50 from testtools.tests.test_with_with import *
53 class TestPlaceHolder(TestCase):
55 run_test_with = FullStackRunTest
57 def makePlaceHolder(self, test_id="foo", short_description=None):
58 return PlaceHolder(test_id, short_description)
60 def test_id_comes_from_constructor(self):
61 # The id() of a PlaceHolder is whatever you pass into the constructor.
62 test = PlaceHolder("test id")
63 self.assertEqual("test id", test.id())
65 def test_shortDescription_is_id(self):
66 # The shortDescription() of a PlaceHolder is the id, by default.
67 test = PlaceHolder("test id")
68 self.assertEqual(test.id(), test.shortDescription())
70 def test_shortDescription_specified(self):
71 # If a shortDescription is provided to the constructor, then
72 # shortDescription() returns that instead.
73 test = PlaceHolder("test id", "description")
74 self.assertEqual("description", test.shortDescription())
76 def test_repr_just_id(self):
77 # repr(placeholder) shows you how the object was constructed.
78 test = PlaceHolder("test id")
80 "<testtools.testcase.PlaceHolder('addSuccess', %s, {})>" % repr(
81 test.id()), repr(test))
83 def test_repr_with_description(self):
84 # repr(placeholder) shows you how the object was constructed.
85 test = PlaceHolder("test id", "description")
87 "<testtools.testcase.PlaceHolder('addSuccess', %r, {}, %r)>" % (
88 test.id(), test.shortDescription()), repr(test))
90 def test_repr_custom_outcome(self):
91 test = PlaceHolder("test id", outcome='addSkip')
93 "<testtools.testcase.PlaceHolder('addSkip', %r, {})>" % (
94 test.id()), repr(test))
96 def test_counts_as_one_test(self):
97 # A placeholder test counts as one test.
98 test = self.makePlaceHolder()
99 self.assertEqual(1, test.countTestCases())
101 def test_str_is_id(self):
102 # str(placeholder) is always the id(). We are not barbarians.
103 test = self.makePlaceHolder()
104 self.assertEqual(test.id(), str(test))
106 def test_runs_as_success(self):
107 # When run, a PlaceHolder test records a success.
108 test = self.makePlaceHolder()
110 test.run(LoggingResult(log))
112 [('startTest', test), ('addSuccess', test), ('stopTest', test)],
115 def test_supplies_details(self):
116 details = {'quux':None}
117 test = PlaceHolder('foo', details=details)
118 result = ExtendedTestResult()
121 [('startTest', test),
122 ('addSuccess', test, details),
126 def test_call_is_run(self):
127 # A PlaceHolder can be called, in which case it behaves like run.
128 test = self.makePlaceHolder()
130 test.run(LoggingResult(run_log))
132 test(LoggingResult(call_log))
133 self.assertEqual(run_log, call_log)
135 def test_runs_without_result(self):
136 # A PlaceHolder can be run without a result, in which case there's no
137 # way to actually get at the result.
138 self.makePlaceHolder().run()
140 def test_debug(self):
141 # A PlaceHolder can be debugged.
142 self.makePlaceHolder().debug()
145 class TestErrorHolder(TestCase):
146 # Note that these tests exist because ErrorHolder exists - it could be
147 # deprecated and dropped at this point.
149 run_test_with = FullStackRunTest
151 def makeException(self):
153 raise RuntimeError("danger danger")
155 return sys.exc_info()
157 def makePlaceHolder(self, test_id="foo", error=None,
158 short_description=None):
160 error = self.makeException()
161 return ErrorHolder(test_id, error, short_description)
163 def test_id_comes_from_constructor(self):
164 # The id() of a PlaceHolder is whatever you pass into the constructor.
165 test = ErrorHolder("test id", self.makeException())
166 self.assertEqual("test id", test.id())
168 def test_shortDescription_is_id(self):
169 # The shortDescription() of a PlaceHolder is the id, by default.
170 test = ErrorHolder("test id", self.makeException())
171 self.assertEqual(test.id(), test.shortDescription())
173 def test_shortDescription_specified(self):
174 # If a shortDescription is provided to the constructor, then
175 # shortDescription() returns that instead.
176 test = ErrorHolder("test id", self.makeException(), "description")
177 self.assertEqual("description", test.shortDescription())
179 def test_counts_as_one_test(self):
180 # A placeholder test counts as one test.
181 test = self.makePlaceHolder()
182 self.assertEqual(1, test.countTestCases())
184 def test_str_is_id(self):
185 # str(placeholder) is always the id(). We are not barbarians.
186 test = self.makePlaceHolder()
187 self.assertEqual(test.id(), str(test))
189 def test_runs_as_error(self):
190 # When run, an ErrorHolder test records an error.
191 error = self.makeException()
192 test = self.makePlaceHolder(error=error)
193 result = ExtendedTestResult()
197 [('startTest', test),
198 ('addError', test, test._details),
199 ('stopTest', test)], log)
201 def test_call_is_run(self):
202 # A PlaceHolder can be called, in which case it behaves like run.
203 test = self.makePlaceHolder()
205 test.run(LoggingResult(run_log))
207 test(LoggingResult(call_log))
208 self.assertEqual(run_log, call_log)
210 def test_runs_without_result(self):
211 # A PlaceHolder can be run without a result, in which case there's no
212 # way to actually get at the result.
213 self.makePlaceHolder().run()
215 def test_debug(self):
216 # A PlaceHolder can be debugged.
217 self.makePlaceHolder().debug()
220 class TestEquality(TestCase):
221 """Test ``TestCase``'s equality implementation."""
223 run_test_with = FullStackRunTest
225 def test_identicalIsEqual(self):
226 # TestCase's are equal if they are identical.
227 self.assertEqual(self, self)
229 def test_nonIdenticalInUnequal(self):
230 # TestCase's are not equal if they are not identical.
231 self.assertNotEqual(TestCase(methodName='run'),
232 TestCase(methodName='skip'))
235 class TestAssertions(TestCase):
236 """Test assertions in TestCase."""
238 run_test_with = FullStackRunTest
240 def raiseError(self, exceptionFactory, *args, **kwargs):
241 raise exceptionFactory(*args, **kwargs)
243 def test_formatTypes_single(self):
244 # Given a single class, _formatTypes returns the name.
247 self.assertEqual('Foo', self._formatTypes(Foo))
249 def test_formatTypes_multiple(self):
250 # Given multiple types, _formatTypes returns the names joined by
256 self.assertEqual('Foo, Bar', self._formatTypes([Foo, Bar]))
258 def test_assertRaises(self):
259 # assertRaises asserts that a callable raises a particular exception.
260 self.assertRaises(RuntimeError, self.raiseError, RuntimeError)
262 def test_assertRaises_fails_when_no_error_raised(self):
263 # assertRaises raises self.failureException when it's passed a
264 # callable that raises no error.
267 "<function ...<lambda> at ...> returned ('orange', 42)",
268 self.assertRaises, RuntimeError, lambda: ret)
270 def test_assertRaises_fails_when_different_error_raised(self):
271 # assertRaises re-raises an exception that it didn't expect.
272 self.assertThat(lambda: self.assertRaises(RuntimeError,
273 self.raiseError, ZeroDivisionError),
274 Raises(MatchesException(ZeroDivisionError)))
276 def test_assertRaises_returns_the_raised_exception(self):
277 # assertRaises returns the exception object that was raised. This is
278 # useful for testing that exceptions have the right message.
280 # This contraption stores the raised exception, so we can compare it
281 # to the return value of assertRaises.
282 raisedExceptions = []
285 raise RuntimeError('Deliberate error')
287 raisedExceptions.append(sys.exc_info()[1])
290 exception = self.assertRaises(RuntimeError, raiseError)
291 self.assertEqual(1, len(raisedExceptions))
293 exception is raisedExceptions[0],
294 "%r is not %r" % (exception, raisedExceptions[0]))
296 def test_assertRaises_with_multiple_exceptions(self):
297 # assertRaises((ExceptionOne, ExceptionTwo), function) asserts that
298 # function raises one of ExceptionTwo or ExceptionOne.
299 expectedExceptions = (RuntimeError, ZeroDivisionError)
301 expectedExceptions, self.raiseError, expectedExceptions[0])
303 expectedExceptions, self.raiseError, expectedExceptions[1])
305 def test_assertRaises_with_multiple_exceptions_failure_mode(self):
306 # If assertRaises is called expecting one of a group of exceptions and
307 # a callable that doesn't raise an exception, then fail with an
308 # appropriate error message.
309 expectedExceptions = (RuntimeError, ZeroDivisionError)
311 self.failureException,
312 self.assertRaises, expectedExceptions, lambda: None)
313 self.assertFails('<function ...<lambda> at ...> returned None',
314 self.assertRaises, expectedExceptions, lambda: None)
316 def test_assertRaises_function_repr_in_exception(self):
317 # When assertRaises fails, it includes the repr of the invoked
318 # function in the error message, so it's easy to locate the problem.
320 """An arbitrary function."""
323 lambda: self.assertRaises(Exception, foo),
325 MatchesException(self.failureException, '.*%r.*' % (foo,))))
327 def assertFails(self, message, function, *args, **kwargs):
328 """Assert that function raises a failure with the given message."""
329 failure = self.assertRaises(
330 self.failureException, function, *args, **kwargs)
331 self.assertThat(failure, DocTestMatches(message, ELLIPSIS))
333 def test_assertIn_success(self):
334 # assertIn(needle, haystack) asserts that 'needle' is in 'haystack'.
335 self.assertIn(3, range(10))
336 self.assertIn('foo', 'foo bar baz')
337 self.assertIn('foo', 'foo bar baz'.split())
339 def test_assertIn_failure(self):
340 # assertIn(needle, haystack) fails the test when 'needle' is not in
342 self.assertFails('3 not in [0, 1, 2]', self.assertIn, 3, [0, 1, 2])
344 '%r not in %r' % ('qux', 'foo bar baz'),
345 self.assertIn, 'qux', 'foo bar baz')
347 def test_assertNotIn_success(self):
348 # assertNotIn(needle, haystack) asserts that 'needle' is not in
350 self.assertNotIn(3, [0, 1, 2])
351 self.assertNotIn('qux', 'foo bar baz')
353 def test_assertNotIn_failure(self):
354 # assertNotIn(needle, haystack) fails the test when 'needle' is in
356 self.assertFails('[1, 2, 3] matches Contains(3)', self.assertNotIn,
359 "'foo bar baz' matches Contains('foo')",
360 self.assertNotIn, 'foo', 'foo bar baz')
362 def test_assertIsInstance(self):
363 # assertIsInstance asserts that an object is an instance of a class.
366 """Simple class for testing assertIsInstance."""
369 self.assertIsInstance(foo, Foo)
371 def test_assertIsInstance_multiple_classes(self):
372 # assertIsInstance asserts that an object is an instance of one of a
376 """Simple class for testing assertIsInstance."""
379 """Another simple class for testing assertIsInstance."""
382 self.assertIsInstance(foo, (Foo, Bar))
383 self.assertIsInstance(Bar(), (Foo, Bar))
385 def test_assertIsInstance_failure(self):
386 # assertIsInstance(obj, klass) fails the test when obj is not an
390 """Simple class for testing assertIsInstance."""
393 "'42' is not an instance of %s" % self._formatTypes(Foo),
394 self.assertIsInstance, 42, Foo)
396 def test_assertIsInstance_failure_multiple_classes(self):
397 # assertIsInstance(obj, (klass1, klass2)) fails the test when obj is
398 # not an instance of klass1 or klass2.
401 """Simple class for testing assertIsInstance."""
404 """Another simple class for testing assertIsInstance."""
407 "'42' is not an instance of any of (%s)" % self._formatTypes([Foo, Bar]),
408 self.assertIsInstance, 42, (Foo, Bar))
410 def test_assertIsInstance_overridden_message(self):
411 # assertIsInstance(obj, klass, msg) permits a custom message.
412 self.assertFails("'42' is not an instance of str: foo",
413 self.assertIsInstance, 42, str, "foo")
415 def test_assertIs(self):
416 # assertIs asserts that an object is identical to another object.
417 self.assertIs(None, None)
419 self.assertIs(some_list, some_list)
420 some_object = object()
421 self.assertIs(some_object, some_object)
423 def test_assertIs_fails(self):
424 # assertIs raises assertion errors if one object is not identical to
426 self.assertFails('None is not 42', self.assertIs, None, 42)
427 self.assertFails('[42] is not [42]', self.assertIs, [42], [42])
429 def test_assertIs_fails_with_message(self):
430 # assertIs raises assertion errors if one object is not identical to
431 # another, and includes a user-supplied message, if it's provided.
433 'None is not 42: foo bar', self.assertIs, None, 42, 'foo bar')
435 def test_assertIsNot(self):
436 # assertIsNot asserts that an object is not identical to another
438 self.assertIsNot(None, 42)
439 self.assertIsNot([42], [42])
440 self.assertIsNot(object(), object())
442 def test_assertIsNot_fails(self):
443 # assertIsNot raises assertion errors if one object is identical to
445 self.assertFails('None matches Is(None)', self.assertIsNot, None, None)
448 '[42] matches Is([42])', self.assertIsNot, some_list, some_list)
450 def test_assertIsNot_fails_with_message(self):
451 # assertIsNot raises assertion errors if one object is identical to
452 # another, and includes a user-supplied message if it's provided.
454 'None matches Is(None): foo bar', self.assertIsNot, None, None,
457 def test_assertThat_matches_clean(self):
458 class Matcher(object):
459 def match(self, foo):
461 self.assertThat("foo", Matcher())
463 def test_assertThat_mismatch_raises_description(self):
465 class Mismatch(object):
466 def __init__(self, thing):
469 calls.append(('describe_diff', self.thing))
470 return "object is not a thing"
471 def get_details(self):
473 class Matcher(object):
474 def match(self, thing):
475 calls.append(('match', thing))
476 return Mismatch(thing)
478 calls.append(('__str__',))
479 return "a description"
480 class Test(TestCase):
482 self.assertThat("foo", Matcher())
483 result = Test("test").run()
486 ('describe_diff', "foo"),
488 self.assertFalse(result.wasSuccessful())
490 def test_assertThat_output(self):
492 matcher = Equals('bar')
493 expected = matcher.match(matchee).describe()
494 self.assertFails(expected, self.assertThat, matchee, matcher)
496 def test_assertThat_message_is_annotated(self):
498 matcher = Equals('bar')
499 expected = Annotate('woo', matcher).match(matchee).describe()
500 self.assertFails(expected, self.assertThat, matchee, matcher, 'woo')
502 def test_assertThat_verbose_output(self):
504 matcher = Equals('bar')
506 'Match failed. Matchee: %r\n'
508 'Difference: %s\n' % (
511 matcher.match(matchee).describe(),
514 expected, self.assertThat, matchee, matcher, verbose=True)
516 def get_error_string(self, e):
517 """Get the string showing how 'e' would be formatted in test output.
519 This is a little bit hacky, since it's designed to give consistent
520 output regardless of Python version.
522 In testtools, TestResult._exc_info_to_unicode is the point of dispatch
523 between various different implementations of methods that format
524 exceptions, so that's what we have to call. However, that method cares
525 about stack traces and formats the exception class. We don't care
526 about either of these, so we take its output and parse it a little.
528 error = TracebackContent((e.__class__, e, None), self).as_text()
529 # We aren't at all interested in the traceback.
530 if error.startswith('Traceback (most recent call last):\n'):
531 lines = error.splitlines(True)[1:]
532 for i, line in enumerate(lines):
533 if not line.startswith(' '):
535 error = ''.join(lines[i:])
536 # We aren't interested in how the exception type is formatted.
537 exc_class, error = error.split(': ', 1)
540 def test_assertThat_verbose_unicode(self):
541 # When assertThat is given matchees or matchers that contain non-ASCII
542 # unicode strings, we can still provide a meaningful error.
544 matcher = Equals(_u('a'))
546 'Match failed. Matchee: %s\n'
548 'Difference: %s\n\n' % (
549 repr(matchee).replace("\\xa7", matchee),
551 matcher.match(matchee).describe(),
553 e = self.assertRaises(
554 self.failureException, self.assertThat, matchee, matcher,
556 self.assertEqual(expected, self.get_error_string(e))
558 def test_assertEqual_nice_formatting(self):
559 message = "These things ought not be equal."
560 a = ['apple', 'banana', 'cherry']
561 b = {'Thatcher': 'One who mends roofs of straw',
562 'Major': 'A military officer, ranked below colonel',
563 'Blair': 'To shout loudly',
564 'Brown': 'The colour of healthy human faeces'}
565 expected_error = '\n'.join([
567 'reference = %s' % pformat(a),
568 'actual = %s' % pformat(b),
571 self.assertFails(expected_error, self.assertEqual, a, b, message)
572 self.assertFails(expected_error, self.assertEquals, a, b, message)
573 self.assertFails(expected_error, self.failUnlessEqual, a, b, message)
575 def test_assertEqual_formatting_no_message(self):
578 expected_error = "'cat' != 'dog'"
579 self.assertFails(expected_error, self.assertEqual, a, b)
580 self.assertFails(expected_error, self.assertEquals, a, b)
581 self.assertFails(expected_error, self.failUnlessEqual, a, b)
583 def test_assertEqual_non_ascii_str_with_newlines(self):
584 message = _u("Be careful mixing unicode and bytes")
586 b = "Just a longish string so the more verbose output form is used."
587 expected_error = '\n'.join([
593 'actual = %r' % (b,),
596 self.assertFails(expected_error, self.assertEqual, a, b, message)
598 def test_assertIsNone(self):
599 self.assertIsNone(None)
601 expected_error = 'None is not 0'
602 self.assertFails(expected_error, self.assertIsNone, 0)
604 def test_assertIsNotNone(self):
605 self.assertIsNotNone(0)
606 self.assertIsNotNone("0")
608 expected_error = 'None matches Is(None)'
609 self.assertFails(expected_error, self.assertIsNotNone, None)
612 class TestAddCleanup(TestCase):
613 """Tests for TestCase.addCleanup."""
615 run_test_with = FullStackRunTest
617 class LoggingTest(TestCase):
618 """A test that logs calls to setUp, runTest and tearDown."""
622 self._calls = ['setUp']
624 def brokenSetUp(self):
625 # A tearDown that deliberately fails.
626 self._calls = ['brokenSetUp']
627 raise RuntimeError('Deliberate Failure')
630 self._calls.append('runTest')
632 def brokenTest(self):
633 raise RuntimeError('Deliberate broken test')
636 self._calls.append('tearDown')
637 TestCase.tearDown(self)
641 self._result_calls = []
642 self.test = TestAddCleanup.LoggingTest('runTest')
643 self.logging_result = LoggingResult(self._result_calls)
645 def assertErrorLogEqual(self, messages):
646 self.assertEqual(messages, [call[0] for call in self._result_calls])
648 def assertTestLogEqual(self, messages):
649 """Assert that the call log equals 'messages'."""
650 case = self._result_calls[0][1]
651 self.assertEqual(messages, case._calls)
653 def logAppender(self, message):
654 """A cleanup that appends 'message' to the tests log.
656 Cleanups are callables that are added to a test by addCleanup. To
657 verify that our cleanups run in the right order, we add strings to a
658 list that acts as a log. This method returns a cleanup that will add
659 the given message to that log when run.
661 self.test._calls.append(message)
663 def test_fixture(self):
664 # A normal run of self.test logs 'setUp', 'runTest' and 'tearDown'.
665 # This test doesn't test addCleanup itself, it just sanity checks the
667 self.test.run(self.logging_result)
668 self.assertTestLogEqual(['setUp', 'runTest', 'tearDown'])
670 def test_cleanup_run_before_tearDown(self):
671 # Cleanup functions added with 'addCleanup' are called before tearDown
673 self.test.addCleanup(self.logAppender, 'cleanup')
674 self.test.run(self.logging_result)
675 self.assertTestLogEqual(['setUp', 'runTest', 'tearDown', 'cleanup'])
677 def test_add_cleanup_called_if_setUp_fails(self):
678 # Cleanup functions added with 'addCleanup' are called even if setUp
679 # fails. Note that tearDown has a different behavior: it is only
680 # called when setUp succeeds.
681 self.test.setUp = self.test.brokenSetUp
682 self.test.addCleanup(self.logAppender, 'cleanup')
683 self.test.run(self.logging_result)
684 self.assertTestLogEqual(['brokenSetUp', 'cleanup'])
686 def test_addCleanup_called_in_reverse_order(self):
687 # Cleanup functions added with 'addCleanup' are called in reverse
690 # One of the main uses of addCleanup is to dynamically create
691 # resources that need some sort of explicit tearDown. Often one
692 # resource will be created in terms of another, e.g.,
693 # self.first = self.makeFirst()
694 # self.second = self.makeSecond(self.first)
696 # When this happens, we generally want to clean up the second resource
697 # before the first one, since the second depends on the first.
698 self.test.addCleanup(self.logAppender, 'first')
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_tearDown_runs_after_cleanup_failure(self):
705 # tearDown runs even if a cleanup function fails.
706 self.test.addCleanup(lambda: 1/0)
707 self.test.run(self.logging_result)
708 self.assertTestLogEqual(['setUp', 'runTest', 'tearDown'])
710 def test_cleanups_continue_running_after_error(self):
711 # All cleanups are always run, even if one or two of them fail.
712 self.test.addCleanup(self.logAppender, 'first')
713 self.test.addCleanup(lambda: 1/0)
714 self.test.addCleanup(self.logAppender, 'second')
715 self.test.run(self.logging_result)
716 self.assertTestLogEqual(
717 ['setUp', 'runTest', 'tearDown', 'second', 'first'])
719 def test_error_in_cleanups_are_captured(self):
720 # If a cleanup raises an error, we want to record it and fail the the
721 # test, even though we go on to run other cleanups.
722 self.test.addCleanup(lambda: 1/0)
723 self.test.run(self.logging_result)
724 self.assertErrorLogEqual(['startTest', 'addError', 'stopTest'])
726 def test_keyboard_interrupt_not_caught(self):
727 # If a cleanup raises KeyboardInterrupt, it gets reraised.
728 def raiseKeyboardInterrupt():
729 raise KeyboardInterrupt()
730 self.test.addCleanup(raiseKeyboardInterrupt)
731 self.assertThat(lambda:self.test.run(self.logging_result),
732 Raises(MatchesException(KeyboardInterrupt)))
734 def test_all_errors_from_MultipleExceptions_reported(self):
735 # When a MultipleExceptions exception is caught, all the errors are
741 exc_info1 = sys.exc_info()
745 exc_info2 = sys.exc_info()
746 raise MultipleExceptions(exc_info1, exc_info2)
747 self.test.addCleanup(raiseMany)
748 self.logging_result = ExtendedTestResult()
749 self.test.run(self.logging_result)
750 self.assertEqual(['startTest', 'addError', 'stopTest'],
751 [event[0] for event in self.logging_result._events])
752 self.assertEqual(set(['traceback', 'traceback-1']),
753 set(self.logging_result._events[1][2].keys()))
755 def test_multipleCleanupErrorsReported(self):
756 # Errors from all failing cleanups are reported as separate backtraces.
757 self.test.addCleanup(lambda: 1/0)
758 self.test.addCleanup(lambda: 1/0)
759 self.logging_result = ExtendedTestResult()
760 self.test.run(self.logging_result)
761 self.assertEqual(['startTest', 'addError', 'stopTest'],
762 [event[0] for event in self.logging_result._events])
763 self.assertEqual(set(['traceback', 'traceback-1']),
764 set(self.logging_result._events[1][2].keys()))
766 def test_multipleErrorsCoreAndCleanupReported(self):
767 # Errors from all failing cleanups are reported, with stopTest,
768 # startTest inserted.
769 self.test = TestAddCleanup.LoggingTest('brokenTest')
770 self.test.addCleanup(lambda: 1/0)
771 self.test.addCleanup(lambda: 1/0)
772 self.logging_result = ExtendedTestResult()
773 self.test.run(self.logging_result)
774 self.assertEqual(['startTest', 'addError', 'stopTest'],
775 [event[0] for event in self.logging_result._events])
776 self.assertEqual(set(['traceback', 'traceback-1', 'traceback-2']),
777 set(self.logging_result._events[1][2].keys()))
780 class TestWithDetails(TestCase):
782 run_test_with = FullStackRunTest
784 def assertDetailsProvided(self, case, expected_outcome, expected_keys):
785 """Assert that when case is run, details are provided to the result.
787 :param case: A TestCase to run.
788 :param expected_outcome: The call that should be made.
789 :param expected_keys: The keys to look for.
791 result = ExtendedTestResult()
793 case = result._events[0][1]
796 (expected_outcome, case),
799 self.assertEqual(3, len(result._events))
800 self.assertEqual(expected[0], result._events[0])
801 self.assertEqual(expected[1], result._events[1][0:2])
802 # Checking the TB is right is rather tricky. doctest line matching
803 # would help, but 'meh'.
804 self.assertEqual(sorted(expected_keys),
805 sorted(result._events[1][2].keys()))
806 self.assertEqual(expected[-1], result._events[-1])
808 def get_content(self):
809 return content.Content(
810 content.ContentType("text", "foo"), lambda: [_b('foo')])
813 class TestExpectedFailure(TestWithDetails):
814 """Tests for expected failures and unexpected successess."""
816 run_test_with = FullStackRunTest
818 def make_unexpected_case(self):
819 class Case(TestCase):
821 raise testcase._UnexpectedSuccess
825 def test_raising__UnexpectedSuccess_py27(self):
826 case = self.make_unexpected_case()
827 result = Python27TestResult()
829 case = result._events[0][1]
832 ('addUnexpectedSuccess', case),
836 def test_raising__UnexpectedSuccess_extended(self):
837 case = self.make_unexpected_case()
838 result = ExtendedTestResult()
840 case = result._events[0][1]
843 ('addUnexpectedSuccess', case, {}),
847 def make_xfail_case_xfails(self):
848 content = self.get_content()
849 class Case(TestCase):
851 self.addDetail("foo", content)
852 self.expectFailure("we are sad", self.assertEqual,
857 def make_xfail_case_succeeds(self):
858 content = self.get_content()
859 class Case(TestCase):
861 self.addDetail("foo", content)
862 self.expectFailure("we are sad", self.assertEqual,
867 def test_expectFailure_KnownFailure_extended(self):
868 case = self.make_xfail_case_xfails()
869 self.assertDetailsProvided(case, "addExpectedFailure",
870 ["foo", "traceback", "reason"])
872 def test_expectFailure_KnownFailure_unexpected_success(self):
873 case = self.make_xfail_case_succeeds()
874 self.assertDetailsProvided(case, "addUnexpectedSuccess",
878 class TestUniqueFactories(TestCase):
879 """Tests for getUniqueString and getUniqueInteger."""
881 run_test_with = FullStackRunTest
883 def test_getUniqueInteger(self):
884 # getUniqueInteger returns an integer that increments each time you
886 one = self.getUniqueInteger()
887 self.assertEqual(1, one)
888 two = self.getUniqueInteger()
889 self.assertEqual(2, two)
891 def test_getUniqueString(self):
892 # getUniqueString returns the current test id followed by a unique
894 name_one = self.getUniqueString()
895 self.assertEqual('%s-%d' % (self.id(), 1), name_one)
896 name_two = self.getUniqueString()
897 self.assertEqual('%s-%d' % (self.id(), 2), name_two)
899 def test_getUniqueString_prefix(self):
900 # If getUniqueString is given an argument, it uses that argument as
901 # the prefix of the unique string, rather than the test id.
902 name_one = self.getUniqueString('foo')
903 self.assertThat(name_one, Equals('foo-1'))
904 name_two = self.getUniqueString('bar')
905 self.assertThat(name_two, Equals('bar-2'))
908 class TestCloneTestWithNewId(TestCase):
909 """Tests for clone_test_with_new_id."""
911 run_test_with = FullStackRunTest
913 def test_clone_test_with_new_id(self):
914 class FooTestCase(TestCase):
917 test = FooTestCase('test_foo')
919 newName = self.getUniqueString()
920 newTest = clone_test_with_new_id(test, newName)
921 self.assertEqual(newName, newTest.id())
922 self.assertEqual(oldName, test.id(),
923 "the original test instance should be unchanged.")
925 def test_cloned_testcase_does_not_share_details(self):
926 """A cloned TestCase does not share the details dict."""
927 class Test(TestCase):
930 'foo', content.Content('text/plain', lambda: 'foo'))
931 orig_test = Test('test_foo')
932 cloned_test = clone_test_with_new_id(orig_test, self.getUniqueString())
933 orig_test.run(unittest.TestResult())
934 self.assertEqual('foo', orig_test.getDetails()['foo'].iter_bytes())
935 self.assertEqual(None, cloned_test.getDetails().get('foo'))
938 class TestDetailsProvided(TestWithDetails):
940 run_test_with = FullStackRunTest
942 def test_addDetail(self):
943 mycontent = self.get_content()
944 self.addDetail("foo", mycontent)
945 details = self.getDetails()
946 self.assertEqual({"foo": mycontent}, details)
948 def test_addError(self):
949 class Case(TestCase):
951 this.addDetail("foo", self.get_content())
953 self.assertDetailsProvided(Case("test"), "addError",
954 ["foo", "traceback"])
956 def test_addFailure(self):
957 class Case(TestCase):
959 this.addDetail("foo", self.get_content())
961 self.assertDetailsProvided(Case("test"), "addFailure",
962 ["foo", "traceback"])
964 def test_addSkip(self):
965 class Case(TestCase):
967 this.addDetail("foo", self.get_content())
969 self.assertDetailsProvided(Case("test"), "addSkip",
972 def test_addSucccess(self):
973 class Case(TestCase):
975 this.addDetail("foo", self.get_content())
976 self.assertDetailsProvided(Case("test"), "addSuccess",
979 def test_addUnexpectedSuccess(self):
980 class Case(TestCase):
982 this.addDetail("foo", self.get_content())
983 raise testcase._UnexpectedSuccess()
984 self.assertDetailsProvided(Case("test"), "addUnexpectedSuccess",
987 def test_addDetails_from_Mismatch(self):
988 content = self.get_content()
989 class Mismatch(object):
992 def get_details(self):
993 return {"foo": content}
994 class Matcher(object):
995 def match(self, thing):
998 return "a description"
999 class Case(TestCase):
1001 self.assertThat("foo", Matcher())
1002 self.assertDetailsProvided(Case("test"), "addFailure",
1003 ["foo", "traceback"])
1005 def test_multiple_addDetails_from_Mismatch(self):
1006 content = self.get_content()
1007 class Mismatch(object):
1010 def get_details(self):
1011 return {"foo": content, "bar": content}
1012 class Matcher(object):
1013 def match(self, thing):
1016 return "a description"
1017 class Case(TestCase):
1019 self.assertThat("foo", Matcher())
1020 self.assertDetailsProvided(Case("test"), "addFailure",
1021 ["bar", "foo", "traceback"])
1023 def test_addDetails_with_same_name_as_key_from_get_details(self):
1024 content = self.get_content()
1025 class Mismatch(object):
1028 def get_details(self):
1029 return {"foo": content}
1030 class Matcher(object):
1031 def match(self, thing):
1034 return "a description"
1035 class Case(TestCase):
1037 self.addDetail("foo", content)
1038 self.assertThat("foo", Matcher())
1039 self.assertDetailsProvided(Case("test"), "addFailure",
1040 ["foo", "foo-1", "traceback"])
1043 class TestSetupTearDown(TestCase):
1045 run_test_with = FullStackRunTest
1047 def test_setUpNotCalled(self):
1048 class DoesnotcallsetUp(TestCase):
1051 def test_method(self):
1053 result = unittest.TestResult()
1054 DoesnotcallsetUp('test_method').run(result)
1055 self.assertEqual(1, len(result.errors))
1057 def test_tearDownNotCalled(self):
1058 class DoesnotcalltearDown(TestCase):
1059 def test_method(self):
1063 result = unittest.TestResult()
1064 DoesnotcalltearDown('test_method').run(result)
1065 self.assertEqual(1, len(result.errors))
1068 class TestSkipping(TestCase):
1069 """Tests for skipping of tests functionality."""
1071 run_test_with = FullStackRunTest
1073 def test_skip_causes_skipException(self):
1074 self.assertThat(lambda:self.skip("Skip this test"),
1075 Raises(MatchesException(self.skipException)))
1077 def test_can_use_skipTest(self):
1078 self.assertThat(lambda:self.skipTest("Skip this test"),
1079 Raises(MatchesException(self.skipException)))
1081 def test_skip_without_reason_works(self):
1082 class Test(TestCase):
1084 raise self.skipException()
1086 result = ExtendedTestResult()
1088 self.assertEqual('addSkip', result._events[1][0])
1089 self.assertEqual('no reason given.',
1090 result._events[1][2]['reason'].as_text())
1092 def test_skipException_in_setup_calls_result_addSkip(self):
1093 class TestThatRaisesInSetUp(TestCase):
1095 TestCase.setUp(self)
1096 self.skip("skipping this test")
1097 def test_that_passes(self):
1100 result = LoggingResult(calls)
1101 test = TestThatRaisesInSetUp("test_that_passes")
1103 case = result._events[0][1]
1104 self.assertEqual([('startTest', case),
1105 ('addSkip', case, "skipping this test"), ('stopTest', case)],
1108 def test_skipException_in_test_method_calls_result_addSkip(self):
1109 class SkippingTest(TestCase):
1110 def test_that_raises_skipException(self):
1111 self.skip("skipping this test")
1112 result = Python27TestResult()
1113 test = SkippingTest("test_that_raises_skipException")
1115 case = result._events[0][1]
1116 self.assertEqual([('startTest', case),
1117 ('addSkip', case, "skipping this test"), ('stopTest', case)],
1120 def test_skip__in_setup_with_old_result_object_calls_addSuccess(self):
1121 class SkippingTest(TestCase):
1123 TestCase.setUp(self)
1124 raise self.skipException("skipping this test")
1125 def test_that_raises_skipException(self):
1127 result = Python26TestResult()
1128 test = SkippingTest("test_that_raises_skipException")
1130 self.assertEqual('addSuccess', result._events[1][0])
1132 def test_skip_with_old_result_object_calls_addError(self):
1133 class SkippingTest(TestCase):
1134 def test_that_raises_skipException(self):
1135 raise self.skipException("skipping this test")
1136 result = Python26TestResult()
1137 test = SkippingTest("test_that_raises_skipException")
1139 self.assertEqual('addSuccess', result._events[1][0])
1141 def test_skip_decorator(self):
1142 class SkippingTest(TestCase):
1143 @skip("skipping this test")
1144 def test_that_is_decorated_with_skip(self):
1146 result = Python26TestResult()
1147 test = SkippingTest("test_that_is_decorated_with_skip")
1149 self.assertEqual('addSuccess', result._events[1][0])
1151 def test_skipIf_decorator(self):
1152 class SkippingTest(TestCase):
1153 @skipIf(True, "skipping this test")
1154 def test_that_is_decorated_with_skipIf(self):
1156 result = Python26TestResult()
1157 test = SkippingTest("test_that_is_decorated_with_skipIf")
1159 self.assertEqual('addSuccess', result._events[1][0])
1161 def test_skipUnless_decorator(self):
1162 class SkippingTest(TestCase):
1163 @skipUnless(False, "skipping this test")
1164 def test_that_is_decorated_with_skipUnless(self):
1166 result = Python26TestResult()
1167 test = SkippingTest("test_that_is_decorated_with_skipUnless")
1169 self.assertEqual('addSuccess', result._events[1][0])
1172 class TestOnException(TestCase):
1174 run_test_with = FullStackRunTest
1176 def test_default_works(self):
1178 class Case(TestCase):
1180 self.onException(an_exc_info)
1182 case = Case("method")
1184 self.assertThat(events, Equals([True]))
1186 def test_added_handler_works(self):
1188 class Case(TestCase):
1190 self.addOnException(events.append)
1191 self.onException(an_exc_info)
1192 case = Case("method")
1194 self.assertThat(events, Equals([an_exc_info]))
1196 def test_handler_that_raises_is_not_caught(self):
1198 class Case(TestCase):
1200 self.addOnException(events.index)
1201 self.assertThat(lambda: self.onException(an_exc_info),
1202 Raises(MatchesException(ValueError)))
1203 case = Case("method")
1205 self.assertThat(events, Equals([]))
1208 class TestPatchSupport(TestCase):
1210 run_test_with = FullStackRunTest
1212 class Case(TestCase):
1216 def test_patch(self):
1217 # TestCase.patch masks obj.attribute with the new value.
1218 self.foo = 'original'
1219 test = self.Case('test')
1220 test.patch(self, 'foo', 'patched')
1221 self.assertEqual('patched', self.foo)
1223 def test_patch_restored_after_run(self):
1224 # TestCase.patch masks obj.attribute with the new value, but restores
1225 # the original value after the test is finished.
1226 self.foo = 'original'
1227 test = self.Case('test')
1228 test.patch(self, 'foo', 'patched')
1230 self.assertEqual('original', self.foo)
1232 def test_successive_patches_apply(self):
1233 # TestCase.patch can be called multiple times per test. Each time you
1234 # call it, it overrides the original value.
1235 self.foo = 'original'
1236 test = self.Case('test')
1237 test.patch(self, 'foo', 'patched')
1238 test.patch(self, 'foo', 'second')
1239 self.assertEqual('second', self.foo)
1241 def test_successive_patches_restored_after_run(self):
1242 # TestCase.patch restores the original value, no matter how many times
1244 self.foo = 'original'
1245 test = self.Case('test')
1246 test.patch(self, 'foo', 'patched')
1247 test.patch(self, 'foo', 'second')
1249 self.assertEqual('original', self.foo)
1251 def test_patch_nonexistent_attribute(self):
1252 # TestCase.patch can be used to patch a non-existent attribute.
1253 test = self.Case('test')
1254 test.patch(self, 'doesntexist', 'patched')
1255 self.assertEqual('patched', self.doesntexist)
1257 def test_restore_nonexistent_attribute(self):
1258 # TestCase.patch can be used to patch a non-existent attribute, after
1259 # the test run, the attribute is then removed from the object.
1260 test = self.Case('test')
1261 test.patch(self, 'doesntexist', 'patched')
1264 value = getattr(self, 'doesntexist', marker)
1265 self.assertIs(marker, value)
1268 class TestTestCaseSuper(TestCase):
1270 run_test_with = FullStackRunTest
1272 def test_setup_uses_super(self):
1273 class OtherBaseCase(unittest.TestCase):
1274 setup_called = False
1276 self.setup_called = True
1277 super(OtherBaseCase, self).setUp()
1278 class OurCase(TestCase, OtherBaseCase):
1284 self.assertTrue(test.setup_called)
1286 def test_teardown_uses_super(self):
1287 class OtherBaseCase(unittest.TestCase):
1288 teardown_called = False
1290 self.teardown_called = True
1291 super(OtherBaseCase, self).tearDown()
1292 class OurCase(TestCase, OtherBaseCase):
1298 self.assertTrue(test.teardown_called)
1301 class TestNullary(TestCase):
1303 def test_repr(self):
1304 # The repr() of nullary is the same as the repr() of the wrapped
1308 wrapped = Nullary(foo)
1309 self.assertEqual(repr(wrapped), repr(foo))
1311 def test_called_with_arguments(self):
1312 # The function is called with the arguments given to Nullary's
1315 def foo(*args, **kwargs):
1316 l.append((args, kwargs))
1317 wrapped = Nullary(foo, 1, 2, a="b")
1319 self.assertEqual(l, [((1, 2), {'a': 'b'})])
1321 def test_returns_wrapped(self):
1322 # Calling Nullary returns whatever the function returns.
1324 wrapped = Nullary(lambda: ret)
1325 self.assertIs(ret, wrapped())
1327 def test_raises(self):
1328 # If the function raises, so does Nullary when called.
1329 wrapped = Nullary(lambda: 1/0)
1330 self.assertRaises(ZeroDivisionError, wrapped)
1334 from unittest import TestLoader
1335 return TestLoader().loadTestsFromName(__name__)