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 _b
23 from testtools.matchers import (
30 from testtools.testresult.doubles import (
35 from testtools.tests.helpers import (
41 exec('from __future__ import with_statement')
45 from testtools.tests.test_with_with import *
48 class TestPlaceHolder(TestCase):
50 run_test_with = FullStackRunTest
52 def makePlaceHolder(self, test_id="foo", short_description=None):
53 return PlaceHolder(test_id, short_description)
55 def test_id_comes_from_constructor(self):
56 # The id() of a PlaceHolder is whatever you pass into the constructor.
57 test = PlaceHolder("test id")
58 self.assertEqual("test id", test.id())
60 def test_shortDescription_is_id(self):
61 # The shortDescription() of a PlaceHolder is the id, by default.
62 test = PlaceHolder("test id")
63 self.assertEqual(test.id(), test.shortDescription())
65 def test_shortDescription_specified(self):
66 # If a shortDescription is provided to the constructor, then
67 # shortDescription() returns that instead.
68 test = PlaceHolder("test id", "description")
69 self.assertEqual("description", test.shortDescription())
71 def test_repr_just_id(self):
72 # repr(placeholder) shows you how the object was constructed.
73 test = PlaceHolder("test id")
75 "<testtools.testcase.PlaceHolder(%s)>" % repr(test.id()),
78 def test_repr_with_description(self):
79 # repr(placeholder) shows you how the object was constructed.
80 test = PlaceHolder("test id", "description")
82 "<testtools.testcase.PlaceHolder(%r, %r)>" % (
83 test.id(), test.shortDescription()),
86 def test_counts_as_one_test(self):
87 # A placeholder test counts as one test.
88 test = self.makePlaceHolder()
89 self.assertEqual(1, test.countTestCases())
91 def test_str_is_id(self):
92 # str(placeholder) is always the id(). We are not barbarians.
93 test = self.makePlaceHolder()
94 self.assertEqual(test.id(), str(test))
96 def test_runs_as_success(self):
97 # When run, a PlaceHolder test records a success.
98 test = self.makePlaceHolder()
100 test.run(LoggingResult(log))
102 [('startTest', test), ('addSuccess', test), ('stopTest', test)],
105 def test_call_is_run(self):
106 # A PlaceHolder can be called, in which case it behaves like run.
107 test = self.makePlaceHolder()
109 test.run(LoggingResult(run_log))
111 test(LoggingResult(call_log))
112 self.assertEqual(run_log, call_log)
114 def test_runs_without_result(self):
115 # A PlaceHolder can be run without a result, in which case there's no
116 # way to actually get at the result.
117 self.makePlaceHolder().run()
119 def test_debug(self):
120 # A PlaceHolder can be debugged.
121 self.makePlaceHolder().debug()
124 class TestErrorHolder(TestCase):
126 run_test_with = FullStackRunTest
128 def makeException(self):
130 raise RuntimeError("danger danger")
132 return sys.exc_info()
134 def makePlaceHolder(self, test_id="foo", error=None,
135 short_description=None):
137 error = self.makeException()
138 return ErrorHolder(test_id, error, short_description)
140 def test_id_comes_from_constructor(self):
141 # The id() of a PlaceHolder is whatever you pass into the constructor.
142 test = ErrorHolder("test id", self.makeException())
143 self.assertEqual("test id", test.id())
145 def test_shortDescription_is_id(self):
146 # The shortDescription() of a PlaceHolder is the id, by default.
147 test = ErrorHolder("test id", self.makeException())
148 self.assertEqual(test.id(), test.shortDescription())
150 def test_shortDescription_specified(self):
151 # If a shortDescription is provided to the constructor, then
152 # shortDescription() returns that instead.
153 test = ErrorHolder("test id", self.makeException(), "description")
154 self.assertEqual("description", test.shortDescription())
156 def test_repr_just_id(self):
157 # repr(placeholder) shows you how the object was constructed.
158 error = self.makeException()
159 test = ErrorHolder("test id", error)
161 "<testtools.testcase.ErrorHolder(%r, %r)>" % (test.id(), error),
164 def test_repr_with_description(self):
165 # repr(placeholder) shows you how the object was constructed.
166 error = self.makeException()
167 test = ErrorHolder("test id", error, "description")
169 "<testtools.testcase.ErrorHolder(%r, %r, %r)>" % (
170 test.id(), error, test.shortDescription()),
173 def test_counts_as_one_test(self):
174 # A placeholder test counts as one test.
175 test = self.makePlaceHolder()
176 self.assertEqual(1, test.countTestCases())
178 def test_str_is_id(self):
179 # str(placeholder) is always the id(). We are not barbarians.
180 test = self.makePlaceHolder()
181 self.assertEqual(test.id(), str(test))
183 def test_runs_as_error(self):
184 # When run, a PlaceHolder test records a success.
185 error = self.makeException()
186 test = self.makePlaceHolder(error=error)
188 test.run(LoggingResult(log))
190 [('startTest', test),
191 ('addError', test, error),
192 ('stopTest', test)], log)
194 def test_call_is_run(self):
195 # A PlaceHolder can be called, in which case it behaves like run.
196 test = self.makePlaceHolder()
198 test.run(LoggingResult(run_log))
200 test(LoggingResult(call_log))
201 self.assertEqual(run_log, call_log)
203 def test_runs_without_result(self):
204 # A PlaceHolder can be run without a result, in which case there's no
205 # way to actually get at the result.
206 self.makePlaceHolder().run()
208 def test_debug(self):
209 # A PlaceHolder can be debugged.
210 self.makePlaceHolder().debug()
213 class TestEquality(TestCase):
214 """Test ``TestCase``'s equality implementation."""
216 run_test_with = FullStackRunTest
218 def test_identicalIsEqual(self):
219 # TestCase's are equal if they are identical.
220 self.assertEqual(self, self)
222 def test_nonIdenticalInUnequal(self):
223 # TestCase's are not equal if they are not identical.
224 self.assertNotEqual(TestCase(methodName='run'),
225 TestCase(methodName='skip'))
228 class TestAssertions(TestCase):
229 """Test assertions in TestCase."""
231 run_test_with = FullStackRunTest
233 def raiseError(self, exceptionFactory, *args, **kwargs):
234 raise exceptionFactory(*args, **kwargs)
236 def test_formatTypes_single(self):
237 # Given a single class, _formatTypes returns the name.
240 self.assertEqual('Foo', self._formatTypes(Foo))
242 def test_formatTypes_multiple(self):
243 # Given multiple types, _formatTypes returns the names joined by
249 self.assertEqual('Foo, Bar', self._formatTypes([Foo, Bar]))
251 def test_assertRaises(self):
252 # assertRaises asserts that a callable raises a particular exception.
253 self.assertRaises(RuntimeError, self.raiseError, RuntimeError)
255 def test_assertRaises_fails_when_no_error_raised(self):
256 # assertRaises raises self.failureException when it's passed a
257 # callable that raises no error.
259 self.assertFails("<function <lambda> at ...> returned ('orange', 42)",
260 self.assertRaises, RuntimeError, lambda: ret)
262 def test_assertRaises_fails_when_different_error_raised(self):
263 # assertRaises re-raises an exception that it didn't expect.
264 self.assertThat(lambda: self.assertRaises(RuntimeError,
265 self.raiseError, ZeroDivisionError),
266 Raises(MatchesException(ZeroDivisionError)))
268 def test_assertRaises_returns_the_raised_exception(self):
269 # assertRaises returns the exception object that was raised. This is
270 # useful for testing that exceptions have the right message.
272 # This contraption stores the raised exception, so we can compare it
273 # to the return value of assertRaises.
274 raisedExceptions = []
277 raise RuntimeError('Deliberate error')
279 raisedExceptions.append(sys.exc_info()[1])
282 exception = self.assertRaises(RuntimeError, raiseError)
283 self.assertEqual(1, len(raisedExceptions))
285 exception is raisedExceptions[0],
286 "%r is not %r" % (exception, raisedExceptions[0]))
288 def test_assertRaises_with_multiple_exceptions(self):
289 # assertRaises((ExceptionOne, ExceptionTwo), function) asserts that
290 # function raises one of ExceptionTwo or ExceptionOne.
291 expectedExceptions = (RuntimeError, ZeroDivisionError)
293 expectedExceptions, self.raiseError, expectedExceptions[0])
295 expectedExceptions, self.raiseError, expectedExceptions[1])
297 def test_assertRaises_with_multiple_exceptions_failure_mode(self):
298 # If assertRaises is called expecting one of a group of exceptions and
299 # a callable that doesn't raise an exception, then fail with an
300 # appropriate error message.
301 expectedExceptions = (RuntimeError, ZeroDivisionError)
302 failure = self.assertRaises(
303 self.failureException,
304 self.assertRaises, expectedExceptions, lambda: None)
305 self.assertFails('<function <lambda> at ...> returned None',
306 self.assertRaises, expectedExceptions, lambda: None)
308 def assertFails(self, message, function, *args, **kwargs):
309 """Assert that function raises a failure with the given message."""
310 failure = self.assertRaises(
311 self.failureException, function, *args, **kwargs)
312 self.assertThat(failure, DocTestMatches(message, ELLIPSIS))
314 def test_assertIn_success(self):
315 # assertIn(needle, haystack) asserts that 'needle' is in 'haystack'.
316 self.assertIn(3, range(10))
317 self.assertIn('foo', 'foo bar baz')
318 self.assertIn('foo', 'foo bar baz'.split())
320 def test_assertIn_failure(self):
321 # assertIn(needle, haystack) fails the test when 'needle' is not in
323 self.assertFails('3 not in [0, 1, 2]', self.assertIn, 3, [0, 1, 2])
325 '%r not in %r' % ('qux', 'foo bar baz'),
326 self.assertIn, 'qux', 'foo bar baz')
328 def test_assertNotIn_success(self):
329 # assertNotIn(needle, haystack) asserts that 'needle' is not in
331 self.assertNotIn(3, [0, 1, 2])
332 self.assertNotIn('qux', 'foo bar baz')
334 def test_assertNotIn_failure(self):
335 # assertNotIn(needle, haystack) fails the test when 'needle' is in
337 self.assertFails('[1, 2, 3] matches Contains(3)', self.assertNotIn,
340 "'foo bar baz' matches Contains('foo')",
341 self.assertNotIn, 'foo', 'foo bar baz')
343 def test_assertIsInstance(self):
344 # assertIsInstance asserts that an object is an instance of a class.
347 """Simple class for testing assertIsInstance."""
350 self.assertIsInstance(foo, Foo)
352 def test_assertIsInstance_multiple_classes(self):
353 # assertIsInstance asserts that an object is an instance of one of a
357 """Simple class for testing assertIsInstance."""
360 """Another simple class for testing assertIsInstance."""
363 self.assertIsInstance(foo, (Foo, Bar))
364 self.assertIsInstance(Bar(), (Foo, Bar))
366 def test_assertIsInstance_failure(self):
367 # assertIsInstance(obj, klass) fails the test when obj is not an
371 """Simple class for testing assertIsInstance."""
374 "'42' is not an instance of %s" % self._formatTypes(Foo),
375 self.assertIsInstance, 42, Foo)
377 def test_assertIsInstance_failure_multiple_classes(self):
378 # assertIsInstance(obj, (klass1, klass2)) fails the test when obj is
379 # not an instance of klass1 or klass2.
382 """Simple class for testing assertIsInstance."""
385 """Another simple class for testing assertIsInstance."""
388 "'42' is not an instance of any of (%s)" % self._formatTypes([Foo, Bar]),
389 self.assertIsInstance, 42, (Foo, Bar))
391 def test_assertIsInstance_overridden_message(self):
392 # assertIsInstance(obj, klass, msg) permits a custom message.
393 self.assertFails("'42' is not an instance of str: foo",
394 self.assertIsInstance, 42, str, "foo")
396 def test_assertIs(self):
397 # assertIs asserts that an object is identical to another object.
398 self.assertIs(None, None)
400 self.assertIs(some_list, some_list)
401 some_object = object()
402 self.assertIs(some_object, some_object)
404 def test_assertIs_fails(self):
405 # assertIs raises assertion errors if one object is not identical to
407 self.assertFails('None is not 42', self.assertIs, None, 42)
408 self.assertFails('[42] is not [42]', self.assertIs, [42], [42])
410 def test_assertIs_fails_with_message(self):
411 # assertIs raises assertion errors if one object is not identical to
412 # another, and includes a user-supplied message, if it's provided.
414 'None is not 42: foo bar', self.assertIs, None, 42, 'foo bar')
416 def test_assertIsNot(self):
417 # assertIsNot asserts that an object is not identical to another
419 self.assertIsNot(None, 42)
420 self.assertIsNot([42], [42])
421 self.assertIsNot(object(), object())
423 def test_assertIsNot_fails(self):
424 # assertIsNot raises assertion errors if one object is identical to
426 self.assertFails('None matches Is(None)', self.assertIsNot, None, None)
429 '[42] matches Is([42])', self.assertIsNot, some_list, some_list)
431 def test_assertIsNot_fails_with_message(self):
432 # assertIsNot raises assertion errors if one object is identical to
433 # another, and includes a user-supplied message if it's provided.
435 'None matches Is(None): foo bar', self.assertIsNot, None, None,
438 def test_assertThat_matches_clean(self):
439 class Matcher(object):
440 def match(self, foo):
442 self.assertThat("foo", Matcher())
444 def test_assertThat_mismatch_raises_description(self):
446 class Mismatch(object):
447 def __init__(self, thing):
450 calls.append(('describe_diff', self.thing))
451 return "object is not a thing"
452 def get_details(self):
454 class Matcher(object):
455 def match(self, thing):
456 calls.append(('match', thing))
457 return Mismatch(thing)
459 calls.append(('__str__',))
460 return "a description"
461 class Test(TestCase):
463 self.assertThat("foo", Matcher())
464 result = Test("test").run()
467 ('describe_diff', "foo"),
469 self.assertFalse(result.wasSuccessful())
471 def test_assertThat_output(self):
473 matcher = Equals('bar')
474 expected = matcher.match(matchee).describe()
475 self.assertFails(expected, self.assertThat, matchee, matcher)
477 def test_assertThat_message_is_annotated(self):
479 matcher = Equals('bar')
480 expected = Annotate('woo', matcher).match(matchee).describe()
481 self.assertFails(expected, self.assertThat, matchee, matcher, 'woo')
483 def test_assertThat_verbose_output(self):
485 matcher = Equals('bar')
487 'Match failed. Matchee: "%s"\n'
489 'Difference: %s\n' % (
492 matcher.match(matchee).describe(),
495 expected, self.assertThat, matchee, matcher, verbose=True)
497 def test_assertEqual_nice_formatting(self):
498 message = "These things ought not be equal."
499 a = ['apple', 'banana', 'cherry']
500 b = {'Thatcher': 'One who mends roofs of straw',
501 'Major': 'A military officer, ranked below colonel',
502 'Blair': 'To shout loudly',
503 'Brown': 'The colour of healthy human faeces'}
504 expected_error = '\n'.join([
506 'reference = %s' % pformat(a),
507 'actual = %s' % pformat(b),
510 self.assertFails(expected_error, self.assertEqual, a, b, message)
511 self.assertFails(expected_error, self.assertEquals, a, b, message)
512 self.assertFails(expected_error, self.failUnlessEqual, a, b, message)
514 def test_assertEqual_formatting_no_message(self):
517 expected_error = "'cat' != 'dog'"
518 self.assertFails(expected_error, self.assertEqual, a, b)
519 self.assertFails(expected_error, self.assertEquals, a, b)
520 self.assertFails(expected_error, self.failUnlessEqual, a, b)
522 def test_assertIsNone(self):
523 self.assertIsNone(None)
525 expected_error = 'None is not 0'
526 self.assertFails(expected_error, self.assertIsNone, 0)
528 def test_assertIsNotNone(self):
529 self.assertIsNotNone(0)
530 self.assertIsNotNone("0")
532 expected_error = 'None matches Is(None)'
533 self.assertFails(expected_error, self.assertIsNotNone, None)
536 class TestAddCleanup(TestCase):
537 """Tests for TestCase.addCleanup."""
539 run_test_with = FullStackRunTest
541 class LoggingTest(TestCase):
542 """A test that logs calls to setUp, runTest and tearDown."""
546 self._calls = ['setUp']
548 def brokenSetUp(self):
549 # A tearDown that deliberately fails.
550 self._calls = ['brokenSetUp']
551 raise RuntimeError('Deliberate Failure')
554 self._calls.append('runTest')
556 def brokenTest(self):
557 raise RuntimeError('Deliberate broken test')
560 self._calls.append('tearDown')
561 TestCase.tearDown(self)
565 self._result_calls = []
566 self.test = TestAddCleanup.LoggingTest('runTest')
567 self.logging_result = LoggingResult(self._result_calls)
569 def assertErrorLogEqual(self, messages):
570 self.assertEqual(messages, [call[0] for call in self._result_calls])
572 def assertTestLogEqual(self, messages):
573 """Assert that the call log equals 'messages'."""
574 case = self._result_calls[0][1]
575 self.assertEqual(messages, case._calls)
577 def logAppender(self, message):
578 """A cleanup that appends 'message' to the tests log.
580 Cleanups are callables that are added to a test by addCleanup. To
581 verify that our cleanups run in the right order, we add strings to a
582 list that acts as a log. This method returns a cleanup that will add
583 the given message to that log when run.
585 self.test._calls.append(message)
587 def test_fixture(self):
588 # A normal run of self.test logs 'setUp', 'runTest' and 'tearDown'.
589 # This test doesn't test addCleanup itself, it just sanity checks the
591 self.test.run(self.logging_result)
592 self.assertTestLogEqual(['setUp', 'runTest', 'tearDown'])
594 def test_cleanup_run_before_tearDown(self):
595 # Cleanup functions added with 'addCleanup' are called before tearDown
597 self.test.addCleanup(self.logAppender, 'cleanup')
598 self.test.run(self.logging_result)
599 self.assertTestLogEqual(['setUp', 'runTest', 'tearDown', 'cleanup'])
601 def test_add_cleanup_called_if_setUp_fails(self):
602 # Cleanup functions added with 'addCleanup' are called even if setUp
603 # fails. Note that tearDown has a different behavior: it is only
604 # called when setUp succeeds.
605 self.test.setUp = self.test.brokenSetUp
606 self.test.addCleanup(self.logAppender, 'cleanup')
607 self.test.run(self.logging_result)
608 self.assertTestLogEqual(['brokenSetUp', 'cleanup'])
610 def test_addCleanup_called_in_reverse_order(self):
611 # Cleanup functions added with 'addCleanup' are called in reverse
614 # One of the main uses of addCleanup is to dynamically create
615 # resources that need some sort of explicit tearDown. Often one
616 # resource will be created in terms of another, e.g.,
617 # self.first = self.makeFirst()
618 # self.second = self.makeSecond(self.first)
620 # When this happens, we generally want to clean up the second resource
621 # before the first one, since the second depends on the first.
622 self.test.addCleanup(self.logAppender, 'first')
623 self.test.addCleanup(self.logAppender, 'second')
624 self.test.run(self.logging_result)
625 self.assertTestLogEqual(
626 ['setUp', 'runTest', 'tearDown', 'second', 'first'])
628 def test_tearDown_runs_after_cleanup_failure(self):
629 # tearDown runs even if a cleanup function fails.
630 self.test.addCleanup(lambda: 1/0)
631 self.test.run(self.logging_result)
632 self.assertTestLogEqual(['setUp', 'runTest', 'tearDown'])
634 def test_cleanups_continue_running_after_error(self):
635 # All cleanups are always run, even if one or two of them fail.
636 self.test.addCleanup(self.logAppender, 'first')
637 self.test.addCleanup(lambda: 1/0)
638 self.test.addCleanup(self.logAppender, 'second')
639 self.test.run(self.logging_result)
640 self.assertTestLogEqual(
641 ['setUp', 'runTest', 'tearDown', 'second', 'first'])
643 def test_error_in_cleanups_are_captured(self):
644 # If a cleanup raises an error, we want to record it and fail the the
645 # test, even though we go on to run other cleanups.
646 self.test.addCleanup(lambda: 1/0)
647 self.test.run(self.logging_result)
648 self.assertErrorLogEqual(['startTest', 'addError', 'stopTest'])
650 def test_keyboard_interrupt_not_caught(self):
651 # If a cleanup raises KeyboardInterrupt, it gets reraised.
652 def raiseKeyboardInterrupt():
653 raise KeyboardInterrupt()
654 self.test.addCleanup(raiseKeyboardInterrupt)
655 self.assertThat(lambda:self.test.run(self.logging_result),
656 Raises(MatchesException(KeyboardInterrupt)))
658 def test_all_errors_from_MultipleExceptions_reported(self):
659 # When a MultipleExceptions exception is caught, all the errors are
665 exc_info1 = sys.exc_info()
669 exc_info2 = sys.exc_info()
670 raise MultipleExceptions(exc_info1, exc_info2)
671 self.test.addCleanup(raiseMany)
672 self.logging_result = ExtendedTestResult()
673 self.test.run(self.logging_result)
674 self.assertEqual(['startTest', 'addError', 'stopTest'],
675 [event[0] for event in self.logging_result._events])
676 self.assertEqual(set(['traceback', 'traceback-1']),
677 set(self.logging_result._events[1][2].keys()))
679 def test_multipleCleanupErrorsReported(self):
680 # Errors from all failing cleanups are reported as separate backtraces.
681 self.test.addCleanup(lambda: 1/0)
682 self.test.addCleanup(lambda: 1/0)
683 self.logging_result = ExtendedTestResult()
684 self.test.run(self.logging_result)
685 self.assertEqual(['startTest', 'addError', 'stopTest'],
686 [event[0] for event in self.logging_result._events])
687 self.assertEqual(set(['traceback', 'traceback-1']),
688 set(self.logging_result._events[1][2].keys()))
690 def test_multipleErrorsCoreAndCleanupReported(self):
691 # Errors from all failing cleanups are reported, with stopTest,
692 # startTest inserted.
693 self.test = TestAddCleanup.LoggingTest('brokenTest')
694 self.test.addCleanup(lambda: 1/0)
695 self.test.addCleanup(lambda: 1/0)
696 self.logging_result = ExtendedTestResult()
697 self.test.run(self.logging_result)
698 self.assertEqual(['startTest', 'addError', 'stopTest'],
699 [event[0] for event in self.logging_result._events])
700 self.assertEqual(set(['traceback', 'traceback-1', 'traceback-2']),
701 set(self.logging_result._events[1][2].keys()))
704 class TestWithDetails(TestCase):
706 run_test_with = FullStackRunTest
708 def assertDetailsProvided(self, case, expected_outcome, expected_keys):
709 """Assert that when case is run, details are provided to the result.
711 :param case: A TestCase to run.
712 :param expected_outcome: The call that should be made.
713 :param expected_keys: The keys to look for.
715 result = ExtendedTestResult()
717 case = result._events[0][1]
720 (expected_outcome, case),
723 self.assertEqual(3, len(result._events))
724 self.assertEqual(expected[0], result._events[0])
725 self.assertEqual(expected[1], result._events[1][0:2])
726 # Checking the TB is right is rather tricky. doctest line matching
727 # would help, but 'meh'.
728 self.assertEqual(sorted(expected_keys),
729 sorted(result._events[1][2].keys()))
730 self.assertEqual(expected[-1], result._events[-1])
732 def get_content(self):
733 return content.Content(
734 content.ContentType("text", "foo"), lambda: [_b('foo')])
737 class TestExpectedFailure(TestWithDetails):
738 """Tests for expected failures and unexpected successess."""
740 run_test_with = FullStackRunTest
742 def make_unexpected_case(self):
743 class Case(TestCase):
745 raise testcase._UnexpectedSuccess
749 def test_raising__UnexpectedSuccess_py27(self):
750 case = self.make_unexpected_case()
751 result = Python27TestResult()
753 case = result._events[0][1]
756 ('addUnexpectedSuccess', case),
760 def test_raising__UnexpectedSuccess_extended(self):
761 case = self.make_unexpected_case()
762 result = ExtendedTestResult()
764 case = result._events[0][1]
767 ('addUnexpectedSuccess', case, {}),
771 def make_xfail_case_xfails(self):
772 content = self.get_content()
773 class Case(TestCase):
775 self.addDetail("foo", content)
776 self.expectFailure("we are sad", self.assertEqual,
781 def make_xfail_case_succeeds(self):
782 content = self.get_content()
783 class Case(TestCase):
785 self.addDetail("foo", content)
786 self.expectFailure("we are sad", self.assertEqual,
791 def test_expectFailure_KnownFailure_extended(self):
792 case = self.make_xfail_case_xfails()
793 self.assertDetailsProvided(case, "addExpectedFailure",
794 ["foo", "traceback", "reason"])
796 def test_expectFailure_KnownFailure_unexpected_success(self):
797 case = self.make_xfail_case_succeeds()
798 self.assertDetailsProvided(case, "addUnexpectedSuccess",
802 class TestUniqueFactories(TestCase):
803 """Tests for getUniqueString and getUniqueInteger."""
805 run_test_with = FullStackRunTest
807 def test_getUniqueInteger(self):
808 # getUniqueInteger returns an integer that increments each time you
810 one = self.getUniqueInteger()
811 self.assertEqual(1, one)
812 two = self.getUniqueInteger()
813 self.assertEqual(2, two)
815 def test_getUniqueString(self):
816 # getUniqueString returns the current test id followed by a unique
818 name_one = self.getUniqueString()
819 self.assertEqual('%s-%d' % (self.id(), 1), name_one)
820 name_two = self.getUniqueString()
821 self.assertEqual('%s-%d' % (self.id(), 2), name_two)
823 def test_getUniqueString_prefix(self):
824 # If getUniqueString is given an argument, it uses that argument as
825 # the prefix of the unique string, rather than the test id.
826 name_one = self.getUniqueString('foo')
827 self.assertThat(name_one, Equals('foo-1'))
828 name_two = self.getUniqueString('bar')
829 self.assertThat(name_two, Equals('bar-2'))
832 class TestCloneTestWithNewId(TestCase):
833 """Tests for clone_test_with_new_id."""
835 run_test_with = FullStackRunTest
837 def test_clone_test_with_new_id(self):
838 class FooTestCase(TestCase):
841 test = FooTestCase('test_foo')
843 newName = self.getUniqueString()
844 newTest = clone_test_with_new_id(test, newName)
845 self.assertEqual(newName, newTest.id())
846 self.assertEqual(oldName, test.id(),
847 "the original test instance should be unchanged.")
849 def test_cloned_testcase_does_not_share_details(self):
850 """A cloned TestCase does not share the details dict."""
851 class Test(TestCase):
854 'foo', content.Content('text/plain', lambda: 'foo'))
855 orig_test = Test('test_foo')
856 cloned_test = clone_test_with_new_id(orig_test, self.getUniqueString())
857 orig_test.run(unittest.TestResult())
858 self.assertEqual('foo', orig_test.getDetails()['foo'].iter_bytes())
859 self.assertEqual(None, cloned_test.getDetails().get('foo'))
862 class TestDetailsProvided(TestWithDetails):
864 run_test_with = FullStackRunTest
866 def test_addDetail(self):
867 mycontent = self.get_content()
868 self.addDetail("foo", mycontent)
869 details = self.getDetails()
870 self.assertEqual({"foo": mycontent}, details)
872 def test_addError(self):
873 class Case(TestCase):
875 this.addDetail("foo", self.get_content())
877 self.assertDetailsProvided(Case("test"), "addError",
878 ["foo", "traceback"])
880 def test_addFailure(self):
881 class Case(TestCase):
883 this.addDetail("foo", self.get_content())
885 self.assertDetailsProvided(Case("test"), "addFailure",
886 ["foo", "traceback"])
888 def test_addSkip(self):
889 class Case(TestCase):
891 this.addDetail("foo", self.get_content())
893 self.assertDetailsProvided(Case("test"), "addSkip",
896 def test_addSucccess(self):
897 class Case(TestCase):
899 this.addDetail("foo", self.get_content())
900 self.assertDetailsProvided(Case("test"), "addSuccess",
903 def test_addUnexpectedSuccess(self):
904 class Case(TestCase):
906 this.addDetail("foo", self.get_content())
907 raise testcase._UnexpectedSuccess()
908 self.assertDetailsProvided(Case("test"), "addUnexpectedSuccess",
911 def test_addDetails_from_Mismatch(self):
912 content = self.get_content()
913 class Mismatch(object):
916 def get_details(self):
917 return {"foo": content}
918 class Matcher(object):
919 def match(self, thing):
922 return "a description"
923 class Case(TestCase):
925 self.assertThat("foo", Matcher())
926 self.assertDetailsProvided(Case("test"), "addFailure",
927 ["foo", "traceback"])
929 def test_multiple_addDetails_from_Mismatch(self):
930 content = self.get_content()
931 class Mismatch(object):
934 def get_details(self):
935 return {"foo": content, "bar": content}
936 class Matcher(object):
937 def match(self, thing):
940 return "a description"
941 class Case(TestCase):
943 self.assertThat("foo", Matcher())
944 self.assertDetailsProvided(Case("test"), "addFailure",
945 ["bar", "foo", "traceback"])
947 def test_addDetails_with_same_name_as_key_from_get_details(self):
948 content = self.get_content()
949 class Mismatch(object):
952 def get_details(self):
953 return {"foo": content}
954 class Matcher(object):
955 def match(self, thing):
958 return "a description"
959 class Case(TestCase):
961 self.addDetail("foo", content)
962 self.assertThat("foo", Matcher())
963 self.assertDetailsProvided(Case("test"), "addFailure",
964 ["foo", "foo-1", "traceback"])
967 class TestSetupTearDown(TestCase):
969 run_test_with = FullStackRunTest
971 def test_setUpNotCalled(self):
972 class DoesnotcallsetUp(TestCase):
975 def test_method(self):
977 result = unittest.TestResult()
978 DoesnotcallsetUp('test_method').run(result)
979 self.assertEqual(1, len(result.errors))
981 def test_tearDownNotCalled(self):
982 class DoesnotcalltearDown(TestCase):
983 def test_method(self):
987 result = unittest.TestResult()
988 DoesnotcalltearDown('test_method').run(result)
989 self.assertEqual(1, len(result.errors))
992 class TestSkipping(TestCase):
993 """Tests for skipping of tests functionality."""
995 run_test_with = FullStackRunTest
997 def test_skip_causes_skipException(self):
998 self.assertThat(lambda:self.skip("Skip this test"),
999 Raises(MatchesException(self.skipException)))
1001 def test_can_use_skipTest(self):
1002 self.assertThat(lambda:self.skipTest("Skip this test"),
1003 Raises(MatchesException(self.skipException)))
1005 def test_skip_without_reason_works(self):
1006 class Test(TestCase):
1008 raise self.skipException()
1010 result = ExtendedTestResult()
1012 self.assertEqual('addSkip', result._events[1][0])
1013 self.assertEqual('no reason given.',
1014 ''.join(result._events[1][2]['reason'].iter_text()))
1016 def test_skipException_in_setup_calls_result_addSkip(self):
1017 class TestThatRaisesInSetUp(TestCase):
1019 TestCase.setUp(self)
1020 self.skip("skipping this test")
1021 def test_that_passes(self):
1024 result = LoggingResult(calls)
1025 test = TestThatRaisesInSetUp("test_that_passes")
1027 case = result._events[0][1]
1028 self.assertEqual([('startTest', case),
1029 ('addSkip', case, "skipping this test"), ('stopTest', case)],
1032 def test_skipException_in_test_method_calls_result_addSkip(self):
1033 class SkippingTest(TestCase):
1034 def test_that_raises_skipException(self):
1035 self.skip("skipping this test")
1036 result = Python27TestResult()
1037 test = SkippingTest("test_that_raises_skipException")
1039 case = result._events[0][1]
1040 self.assertEqual([('startTest', case),
1041 ('addSkip', case, "skipping this test"), ('stopTest', case)],
1044 def test_skip__in_setup_with_old_result_object_calls_addSuccess(self):
1045 class SkippingTest(TestCase):
1047 TestCase.setUp(self)
1048 raise self.skipException("skipping this test")
1049 def test_that_raises_skipException(self):
1051 result = Python26TestResult()
1052 test = SkippingTest("test_that_raises_skipException")
1054 self.assertEqual('addSuccess', result._events[1][0])
1056 def test_skip_with_old_result_object_calls_addError(self):
1057 class SkippingTest(TestCase):
1058 def test_that_raises_skipException(self):
1059 raise self.skipException("skipping this test")
1060 result = Python26TestResult()
1061 test = SkippingTest("test_that_raises_skipException")
1063 self.assertEqual('addSuccess', result._events[1][0])
1065 def test_skip_decorator(self):
1066 class SkippingTest(TestCase):
1067 @skip("skipping this test")
1068 def test_that_is_decorated_with_skip(self):
1070 result = Python26TestResult()
1071 test = SkippingTest("test_that_is_decorated_with_skip")
1073 self.assertEqual('addSuccess', result._events[1][0])
1075 def test_skipIf_decorator(self):
1076 class SkippingTest(TestCase):
1077 @skipIf(True, "skipping this test")
1078 def test_that_is_decorated_with_skipIf(self):
1080 result = Python26TestResult()
1081 test = SkippingTest("test_that_is_decorated_with_skipIf")
1083 self.assertEqual('addSuccess', result._events[1][0])
1085 def test_skipUnless_decorator(self):
1086 class SkippingTest(TestCase):
1087 @skipUnless(False, "skipping this test")
1088 def test_that_is_decorated_with_skipUnless(self):
1090 result = Python26TestResult()
1091 test = SkippingTest("test_that_is_decorated_with_skipUnless")
1093 self.assertEqual('addSuccess', result._events[1][0])
1096 class TestOnException(TestCase):
1098 run_test_with = FullStackRunTest
1100 def test_default_works(self):
1102 class Case(TestCase):
1104 self.onException(an_exc_info)
1106 case = Case("method")
1108 self.assertThat(events, Equals([True]))
1110 def test_added_handler_works(self):
1112 class Case(TestCase):
1114 self.addOnException(events.append)
1115 self.onException(an_exc_info)
1116 case = Case("method")
1118 self.assertThat(events, Equals([an_exc_info]))
1120 def test_handler_that_raises_is_not_caught(self):
1122 class Case(TestCase):
1124 self.addOnException(events.index)
1125 self.assertThat(lambda: self.onException(an_exc_info),
1126 Raises(MatchesException(ValueError)))
1127 case = Case("method")
1129 self.assertThat(events, Equals([]))
1132 class TestPatchSupport(TestCase):
1134 run_test_with = FullStackRunTest
1136 class Case(TestCase):
1140 def test_patch(self):
1141 # TestCase.patch masks obj.attribute with the new value.
1142 self.foo = 'original'
1143 test = self.Case('test')
1144 test.patch(self, 'foo', 'patched')
1145 self.assertEqual('patched', self.foo)
1147 def test_patch_restored_after_run(self):
1148 # TestCase.patch masks obj.attribute with the new value, but restores
1149 # the original value after the test is finished.
1150 self.foo = 'original'
1151 test = self.Case('test')
1152 test.patch(self, 'foo', 'patched')
1154 self.assertEqual('original', self.foo)
1156 def test_successive_patches_apply(self):
1157 # TestCase.patch can be called multiple times per test. Each time you
1158 # call it, it overrides the original value.
1159 self.foo = 'original'
1160 test = self.Case('test')
1161 test.patch(self, 'foo', 'patched')
1162 test.patch(self, 'foo', 'second')
1163 self.assertEqual('second', self.foo)
1165 def test_successive_patches_restored_after_run(self):
1166 # TestCase.patch restores the original value, no matter how many times
1168 self.foo = 'original'
1169 test = self.Case('test')
1170 test.patch(self, 'foo', 'patched')
1171 test.patch(self, 'foo', 'second')
1173 self.assertEqual('original', self.foo)
1175 def test_patch_nonexistent_attribute(self):
1176 # TestCase.patch can be used to patch a non-existent attribute.
1177 test = self.Case('test')
1178 test.patch(self, 'doesntexist', 'patched')
1179 self.assertEqual('patched', self.doesntexist)
1181 def test_restore_nonexistent_attribute(self):
1182 # TestCase.patch can be used to patch a non-existent attribute, after
1183 # the test run, the attribute is then removed from the object.
1184 test = self.Case('test')
1185 test.patch(self, 'doesntexist', 'patched')
1188 value = getattr(self, 'doesntexist', marker)
1189 self.assertIs(marker, value)
1192 class TestTestCaseSuper(TestCase):
1194 run_test_with = FullStackRunTest
1196 def test_setup_uses_super(self):
1197 class OtherBaseCase(unittest.TestCase):
1198 setup_called = False
1200 self.setup_called = True
1201 super(OtherBaseCase, self).setUp()
1202 class OurCase(TestCase, OtherBaseCase):
1208 self.assertTrue(test.setup_called)
1210 def test_teardown_uses_super(self):
1211 class OtherBaseCase(unittest.TestCase):
1212 teardown_called = False
1214 self.teardown_called = True
1215 super(OtherBaseCase, self).tearDown()
1216 class OurCase(TestCase, OtherBaseCase):
1222 self.assertTrue(test.teardown_called)
1226 from unittest import TestLoader
1227 return TestLoader().loadTestsFromName(__name__)