1 # Copyright (c) 2001-2011 Twisted Matrix Laboratories.
2 # See LICENSE for details
5 Tests for assertions provided by L{twisted.trial.unittest.TestCase}.
9 from pprint import pformat
11 from twisted.python import reflect, failure
12 from twisted.python.deprecate import deprecated, getVersionString
13 from twisted.python.versions import Version
14 from twisted.internet import defer
15 from twisted.trial import unittest, runner, reporter
17 class MockEquality(object):
18 def __init__(self, name):
22 return "MockEquality(%s)" % (self.name,)
24 def __eq__(self, other):
25 if not hasattr(other, 'name'):
26 raise ValueError("%r not comparable to %r" % (other, self))
27 return self.name[0] == other.name[0]
30 class TestAssertions(unittest.TestCase):
32 Tests for TestCase's assertion methods. That is, failUnless*,
35 Note: As of 11.2, assertEqual is preferred over the failUnlessEqual(s)
36 variants. Tests have been modified to reflect this preference.
38 This is pretty paranoid. Still, a certain paranoia is healthy if you
39 are testing a unit testing framework.
42 class FailingTest(unittest.TestCase):
44 raise self.failureException()
49 except self.failureException, e:
50 if not str(e) == 'failed':
51 raise self.failureException("Exception had msg %s instead of %s"
54 raise self.failureException("Call to self.fail() didn't fail test")
56 def test_failingException_fails(self):
57 test = runner.TestLoader().loadClass(TestAssertions.FailingTest)
58 result = reporter.TestResult()
60 self.failIf(result.wasSuccessful())
61 self.assertEqual(result.errors, [])
62 self.assertEqual(len(result.failures), 1)
64 def test_failIf(self):
65 for notTrue in [0, 0.0, False, None, (), []]:
66 self.failIf(notTrue, "failed on %r" % (notTrue,))
67 for true in [1, True, 'cat', [1,2], (3,4)]:
69 self.failIf(true, "failed on %r" % (true,))
70 except self.failureException, e:
71 self.assertEqual(str(e), "failed on %r" % (true,))
73 self.fail("Call to failIf(%r) didn't fail" % (true,))
75 def test_failUnless(self):
76 for notTrue in [0, 0.0, False, None, (), []]:
78 self.failUnless(notTrue, "failed on %r" % (notTrue,))
79 except self.failureException, e:
80 self.assertEqual(str(e), "failed on %r" % (notTrue,))
82 self.fail("Call to failUnless(%r) didn't fail" % (notTrue,))
83 for true in [1, True, 'cat', [1,2], (3,4)]:
84 self.failUnless(true, "failed on %r" % (true,))
87 def _testEqualPair(self, first, second):
88 x = self.assertEqual(first, second)
90 self.fail("assertEqual should return first parameter")
93 def _testUnequalPair(self, first, second):
95 self.assertEqual(first, second)
96 except self.failureException, e:
97 expected = 'not equal:\na = %s\nb = %s\n' % (
98 pformat(first), pformat(second))
99 if str(e) != expected:
100 self.fail("Expected: %r; Got: %s" % (expected, str(e)))
102 self.fail("Call to assertEqual(%r, %r) didn't fail"
106 def test_assertEqual_basic(self):
107 self._testEqualPair('cat', 'cat')
108 self._testUnequalPair('cat', 'dog')
109 self._testEqualPair([1], [1])
110 self._testUnequalPair([1], 'orange')
113 def test_assertEqual_custom(self):
114 x = MockEquality('first')
115 y = MockEquality('second')
116 z = MockEquality('fecund')
117 self._testEqualPair(x, x)
118 self._testEqualPair(x, z)
119 self._testUnequalPair(x, y)
120 self._testUnequalPair(y, z)
123 def test_assertEqualMessage(self):
125 When a message is passed to L{assertEqual}, it is included in the
128 exception = self.assertRaises(
129 self.failureException, self.assertEqual,
130 'foo', 'bar', 'message')
133 "message\nnot equal:\na = 'foo'\nb = 'bar'\n")
136 def test_assertEqualNoneMessage(self):
138 If a message is specified as C{None}, it is not included in the error
139 message of L{assertEqual}.
141 exception = self.assertRaises(
142 self.failureException, self.assertEqual, 'foo', 'bar', None)
143 self.assertEqual(str(exception), "not equal:\na = 'foo'\nb = 'bar'\n")
146 def test_assertEqual_incomparable(self):
147 apple = MockEquality('apple')
150 self.assertEqual(apple, orange)
151 except self.failureException:
152 self.fail("Fail raised when ValueError ought to have been raised.")
154 # good. error not swallowed
157 self.fail("Comparing %r and %r should have raised an exception"
161 def _raiseError(self, error):
164 def test_failUnlessRaises_expected(self):
165 x = self.failUnlessRaises(ValueError, self._raiseError, ValueError)
166 self.failUnless(isinstance(x, ValueError),
167 "Expect failUnlessRaises to return instance of raised "
170 def test_failUnlessRaises_unexpected(self):
172 self.failUnlessRaises(ValueError, self._raiseError, TypeError)
174 self.fail("failUnlessRaises shouldn't re-raise unexpected "
176 except self.failureException:
180 self.fail("Expected exception wasn't raised. Should have failed")
182 def test_failUnlessRaises_noException(self):
184 self.failUnlessRaises(ValueError, lambda : None)
185 except self.failureException, e:
186 self.assertEqual(str(e),
187 'ValueError not raised (None returned)')
189 self.fail("Exception not raised. Should have failed")
191 def test_failUnlessRaises_failureException(self):
192 x = self.failUnlessRaises(self.failureException, self._raiseError,
193 self.failureException)
194 self.failUnless(isinstance(x, self.failureException),
195 "Expected %r instance to be returned"
196 % (self.failureException,))
198 x = self.failUnlessRaises(self.failureException, self._raiseError,
200 except self.failureException:
204 self.fail("Should have raised exception")
206 def test_failIfEqual_basic(self):
207 x, y, z = [1], [2], [1]
208 ret = self.failIfEqual(x, y)
209 self.assertEqual(ret, x,
210 "failIfEqual should return first parameter")
211 self.failUnlessRaises(self.failureException,
212 self.failIfEqual, x, x)
213 self.failUnlessRaises(self.failureException,
214 self.failIfEqual, x, z)
216 def test_failIfEqual_customEq(self):
217 x = MockEquality('first')
218 y = MockEquality('second')
219 z = MockEquality('fecund')
220 ret = self.failIfEqual(x, y)
221 self.assertEqual(ret, x,
222 "failIfEqual should return first parameter")
223 self.failUnlessRaises(self.failureException,
224 self.failIfEqual, x, x)
225 # test when __ne__ is not defined
226 self.failIfEqual(x, z, "__ne__ not defined, so not equal")
228 def test_failUnlessIdentical(self):
229 x, y, z = [1], [1], [2]
230 ret = self.failUnlessIdentical(x, x)
231 self.assertEqual(ret, x,
232 'failUnlessIdentical should return first '
234 self.failUnlessRaises(self.failureException,
235 self.failUnlessIdentical, x, y)
236 self.failUnlessRaises(self.failureException,
237 self.failUnlessIdentical, x, z)
239 def test_failUnlessApproximates(self):
240 x, y, z = 1.0, 1.1, 1.2
241 self.failUnlessApproximates(x, x, 0.2)
242 ret = self.failUnlessApproximates(x, y, 0.2)
243 self.assertEqual(ret, x, "failUnlessApproximates should return "
245 self.failUnlessRaises(self.failureException,
246 self.failUnlessApproximates, x, z, 0.1)
247 self.failUnlessRaises(self.failureException,
248 self.failUnlessApproximates, x, y, 0.1)
250 def test_failUnlessAlmostEqual(self):
255 self.failUnlessAlmostEqual(x, x, precision)
256 ret = self.failUnlessAlmostEqual(x, z, precision)
257 self.assertEqual(ret, x, "failUnlessAlmostEqual should return "
258 "first parameter (%r, %r)" % (ret, x))
259 self.failUnlessRaises(self.failureException,
260 self.failUnlessAlmostEqual, x, y, precision)
262 def test_failIfAlmostEqual(self):
267 ret = self.failIfAlmostEqual(x, y, precision)
268 self.assertEqual(ret, x, "failIfAlmostEqual should return "
269 "first parameter (%r, %r)" % (ret, x))
270 self.failUnlessRaises(self.failureException,
271 self.failIfAlmostEqual, x, x, precision)
272 self.failUnlessRaises(self.failureException,
273 self.failIfAlmostEqual, x, z, precision)
275 def test_failUnlessSubstring(self):
279 self.failUnlessSubstring(x, x)
280 ret = self.failUnlessSubstring(x, z)
281 self.assertEqual(ret, x, 'should return first parameter')
282 self.failUnlessRaises(self.failureException,
283 self.failUnlessSubstring, x, y)
284 self.failUnlessRaises(self.failureException,
285 self.failUnlessSubstring, z, x)
287 def test_failIfSubstring(self):
291 self.failIfSubstring(z, x)
292 ret = self.failIfSubstring(x, y)
293 self.assertEqual(ret, x, 'should return first parameter')
294 self.failUnlessRaises(self.failureException,
295 self.failIfSubstring, x, x)
296 self.failUnlessRaises(self.failureException,
297 self.failIfSubstring, x, z)
299 def test_assertFailure(self):
300 d = defer.maybeDeferred(lambda: 1/0)
301 return self.assertFailure(d, ZeroDivisionError)
303 def test_assertFailure_wrongException(self):
304 d = defer.maybeDeferred(lambda: 1/0)
305 self.assertFailure(d, OverflowError)
306 d.addCallbacks(lambda x: self.fail('Should have failed'),
307 lambda x: x.trap(self.failureException))
310 def test_assertFailure_noException(self):
311 d = defer.succeed(None)
312 self.assertFailure(d, ZeroDivisionError)
313 d.addCallbacks(lambda x: self.fail('Should have failed'),
314 lambda x: x.trap(self.failureException))
317 def test_assertFailure_moreInfo(self):
319 In the case of assertFailure failing, check that we get lots of
320 information about the exception that was raised.
324 except ZeroDivisionError:
325 f = failure.Failure()
327 d = self.assertFailure(d, RuntimeError)
328 d.addErrback(self._checkInfo, f)
331 def _checkInfo(self, assertionFailure, f):
332 assert assertionFailure.check(self.failureException)
333 output = assertionFailure.getErrorMessage()
334 self.assertIn(f.getErrorMessage(), output)
335 self.assertIn(f.getBriefTraceback(), output)
337 def test_assertFailure_masked(self):
339 A single wrong assertFailure should fail the whole test.
341 class ExampleFailure(Exception):
344 class TC(unittest.TestCase):
345 failureException = ExampleFailure
346 def test_assertFailure(self):
347 d = defer.maybeDeferred(lambda: 1/0)
348 self.assertFailure(d, OverflowError)
349 self.assertFailure(d, ZeroDivisionError)
352 test = TC('test_assertFailure')
353 result = reporter.TestResult()
355 self.assertEqual(1, len(result.failures))
358 def test_assertWarns(self):
360 Test basic assertWarns report.
363 warnings.warn("Woo deprecated", category=DeprecationWarning)
365 r = self.assertWarns(DeprecationWarning, "Woo deprecated", __file__,
367 self.assertEqual(r, 123)
370 def test_assertWarnsRegistryClean(self):
372 Test that assertWarns cleans the warning registry, so the warning is
373 not swallowed the second time.
376 warnings.warn("Woo deprecated", category=DeprecationWarning)
378 r1 = self.assertWarns(DeprecationWarning, "Woo deprecated", __file__,
380 self.assertEqual(r1, 123)
381 # The warning should be raised again
382 r2 = self.assertWarns(DeprecationWarning, "Woo deprecated", __file__,
384 self.assertEqual(r2, 321)
387 def test_assertWarnsError(self):
389 Test assertWarns failure when no warning is generated.
393 self.assertRaises(self.failureException,
394 self.assertWarns, DeprecationWarning, "Woo deprecated", __file__,
398 def test_assertWarnsWrongCategory(self):
400 Test assertWarns failure when the category is wrong.
403 warnings.warn("Foo deprecated", category=DeprecationWarning)
405 self.assertRaises(self.failureException,
406 self.assertWarns, UserWarning, "Foo deprecated", __file__,
410 def test_assertWarnsWrongMessage(self):
412 Test assertWarns failure when the message is wrong.
415 warnings.warn("Foo deprecated", category=DeprecationWarning)
417 self.assertRaises(self.failureException,
418 self.assertWarns, DeprecationWarning, "Bar deprecated", __file__,
422 def test_assertWarnsWrongFile(self):
424 If the warning emitted by a function refers to a different file than is
425 passed to C{assertWarns}, C{failureException} is raised.
428 # stacklevel=2 points at the direct caller of the function. The
429 # way assertRaises is invoked below, the direct caller will be
430 # something somewhere in trial, not something in this file. In
431 # Python 2.5 and earlier, stacklevel of 0 resulted in a warning
432 # pointing to the warnings module itself. Starting in Python 2.6,
433 # stacklevel of 0 and 1 both result in a warning pointing to *this*
434 # file, presumably due to the fact that the warn function is
435 # implemented in C and has no convenient Python
436 # filename/linenumber.
438 "Foo deprecated", category=DeprecationWarning, stacklevel=2)
440 self.failureException,
441 # Since the direct caller isn't in this file, try to assert that
442 # the warning *does* point to this file, so that assertWarns raises
444 self.assertWarns, DeprecationWarning, "Foo deprecated", __file__,
447 def test_assertWarnsOnClass(self):
449 Test assertWarns works when creating a class instance.
453 warnings.warn("Do not call me", category=RuntimeWarning)
454 r = self.assertWarns(RuntimeWarning, "Do not call me", __file__,
456 self.assertTrue(isinstance(r, Warn))
457 r = self.assertWarns(RuntimeWarning, "Do not call me", __file__,
459 self.assertTrue(isinstance(r, Warn))
462 def test_assertWarnsOnMethod(self):
464 Test assertWarns works when used on an instance method.
467 def deprecated(self, a):
468 warnings.warn("Bar deprecated", category=DeprecationWarning)
471 r = self.assertWarns(DeprecationWarning, "Bar deprecated", __file__,
473 self.assertEqual(r, 321)
474 r = self.assertWarns(DeprecationWarning, "Bar deprecated", __file__,
476 self.assertEqual(r, 321)
479 def test_assertWarnsOnCall(self):
481 Test assertWarns works on instance with C{__call__} method.
484 def __call__(self, a):
485 warnings.warn("Egg deprecated", category=DeprecationWarning)
488 r = self.assertWarns(DeprecationWarning, "Egg deprecated", __file__,
490 self.assertEqual(r, 321)
491 r = self.assertWarns(DeprecationWarning, "Egg deprecated", __file__,
493 self.assertEqual(r, 321)
496 def test_assertWarnsFilter(self):
498 Test assertWarns on a warning filterd by default.
501 warnings.warn("Woo deprecated", category=PendingDeprecationWarning)
503 r = self.assertWarns(PendingDeprecationWarning, "Woo deprecated",
504 __file__, deprecated, 123)
505 self.assertEqual(r, 123)
508 def test_assertWarnsMultipleWarnings(self):
510 C{assertWarns} does not raise an exception if the function it is passed
511 triggers the same warning more than once.
514 warnings.warn("Woo deprecated", category=PendingDeprecationWarning)
519 PendingDeprecationWarning, "Woo deprecated", __file__, f)
522 def test_assertWarnsDifferentWarnings(self):
524 For now, assertWarns is unable to handle multiple different warnings,
525 so it should raise an exception if it's the case.
528 warnings.warn("Woo deprecated", category=DeprecationWarning)
529 warnings.warn("Another one", category=PendingDeprecationWarning)
530 e = self.assertRaises(self.failureException,
531 self.assertWarns, DeprecationWarning, "Woo deprecated",
532 __file__, deprecated, 123)
533 self.assertEqual(str(e), "Can't handle different warnings")
536 def test_assertWarnsAfterUnassertedWarning(self):
538 Warnings emitted before L{TestCase.assertWarns} is called do not get
539 flushed and do not alter the behavior of L{TestCase.assertWarns}.
541 class TheWarning(Warning):
545 warnings.warn(message, category=TheWarning)
547 self.assertWarns(TheWarning, "bar", __file__, f, "bar")
548 [warning] = self.flushWarnings([f])
549 self.assertEqual(warning['message'], "foo")
552 def test_assertIsInstance(self):
554 Test a true condition of assertIsInstance.
556 A = type('A', (object,), {})
558 self.assertIsInstance(a, A)
560 def test_assertIsInstanceMultipleClasses(self):
562 Test a true condition of assertIsInstance with multiple classes.
564 A = type('A', (object,), {})
565 B = type('B', (object,), {})
567 self.assertIsInstance(a, (A, B))
569 def test_assertIsInstanceError(self):
571 Test an error with assertIsInstance.
573 A = type('A', (object,), {})
574 B = type('B', (object,), {})
576 self.assertRaises(self.failureException, self.assertIsInstance, a, B)
578 def test_assertIsInstanceErrorMultipleClasses(self):
580 Test an error with assertIsInstance and multiple classes.
582 A = type('A', (object,), {})
583 B = type('B', (object,), {})
584 C = type('C', (object,), {})
586 self.assertRaises(self.failureException, self.assertIsInstance, a, (B, C))
589 def test_assertIsInstanceCustomMessage(self):
591 If L{TestCase.assertIsInstance} is passed a custom message as its 3rd
592 argument, the message is included in the failure exception raised when
595 exc = self.assertRaises(
596 self.failureException,
597 self.assertIsInstance, 3, str, "Silly assertion")
598 self.assertIn("Silly assertion", str(exc))
601 def test_assertNotIsInstance(self):
603 Test a true condition of assertNotIsInstance.
605 A = type('A', (object,), {})
606 B = type('B', (object,), {})
608 self.assertNotIsInstance(a, B)
610 def test_assertNotIsInstanceMultipleClasses(self):
612 Test a true condition of assertNotIsInstance and multiple classes.
614 A = type('A', (object,), {})
615 B = type('B', (object,), {})
616 C = type('C', (object,), {})
618 self.assertNotIsInstance(a, (B, C))
620 def test_assertNotIsInstanceError(self):
622 Test an error with assertNotIsInstance.
624 A = type('A', (object,), {})
626 error = self.assertRaises(self.failureException,
627 self.assertNotIsInstance, a, A)
628 self.assertEqual(str(error), "%r is an instance of %s" % (a, A))
631 def test_assertNotIsInstanceErrorMultipleClasses(self):
633 Test an error with assertNotIsInstance and multiple classes.
635 A = type('A', (object,), {})
636 B = type('B', (object,), {})
638 self.assertRaises(self.failureException, self.assertNotIsInstance, a, (A, B))
641 def test_assertDictEqual(self):
643 L{twisted.trial.unittest.TestCase} supports the C{assertDictEqual}
644 method inherited from the standard library in Python 2.7.
646 self.assertDictEqual({'a': 1}, {'a': 1})
647 if getattr(unittest.TestCase, 'assertDictEqual', None) is None:
648 test_assertDictEqual.skip = (
649 "assertDictEqual is not available on this version of Python")
653 class TestAssertionNames(unittest.TestCase):
655 Tests for consistency of naming within TestCase assertion methods
657 def _getAsserts(self):
659 reflect.accumulateMethods(self, dct, 'assert')
660 return [ dct[k] for k in dct if not k.startswith('Not') and k != '_' ]
666 def test_failUnlessMatchesAssert(self):
668 The C{failUnless*} test methods are a subset of the C{assert*} test
669 methods. This is intended to ensure that methods using the
670 I{failUnless} naming scheme are not added without corresponding methods
671 using the I{assert} naming scheme. The I{assert} naming scheme is
672 preferred, and new I{assert}-prefixed methods may be added without
673 corresponding I{failUnless}-prefixed methods.
675 asserts = set(self._getAsserts())
676 failUnlesses = set(reflect.prefixedMethods(self, 'failUnless'))
678 failUnlesses, asserts.intersection(failUnlesses))
681 def test_failIf_matches_assertNot(self):
682 asserts = reflect.prefixedMethods(unittest.TestCase, 'assertNot')
683 failIfs = reflect.prefixedMethods(unittest.TestCase, 'failIf')
684 self.assertEqual(sorted(asserts, key=self._name),
685 sorted(failIfs, key=self._name))
687 def test_equalSpelling(self):
688 for name, value in vars(self).items():
689 if not callable(value):
691 if name.endswith('Equal'):
692 self.failUnless(hasattr(self, name+'s'),
693 "%s but no %ss" % (name, name))
694 self.assertEqual(value, getattr(self, name+'s'))
695 if name.endswith('Equals'):
696 self.failUnless(hasattr(self, name[:-1]),
697 "%s but no %s" % (name, name[:-1]))
698 self.assertEqual(value, getattr(self, name[:-1]))
701 class TestCallDeprecated(unittest.TestCase):
703 Test use of the L{TestCase.callDeprecated} method with version objects.
706 version = Version('Twisted', 8, 0, 0)
708 def test_callDeprecatedSuppressesWarning(self):
710 callDeprecated calls a deprecated callable, suppressing the
713 self.callDeprecated(self.version, oldMethod, 'foo')
715 self.flushWarnings(), [], "No warnings should be shown")
718 def test_callDeprecatedCallsFunction(self):
720 L{callDeprecated} actually calls the callable passed to it, and
723 result = self.callDeprecated(self.version, oldMethod, 'foo')
724 self.assertEqual('foo', result)
727 def test_failsWithoutDeprecation(self):
729 L{callDeprecated} raises a test failure if the callable is not
734 exception = self.assertRaises(
735 self.failureException,
736 self.callDeprecated, self.version, notDeprecated)
738 "%r is not deprecated." % notDeprecated, str(exception))
741 def test_failsWithIncorrectDeprecation(self):
743 callDeprecated raises a test failure if the callable was deprecated
744 at a different version to the one expected.
746 differentVersion = Version('Foo', 1, 2, 3)
747 exception = self.assertRaises(
748 self.failureException,
750 differentVersion, oldMethod, 'foo')
751 self.assertIn(getVersionString(self.version), str(exception))
752 self.assertIn(getVersionString(differentVersion), str(exception))
755 def test_nestedDeprecation(self):
757 L{callDeprecated} ignores all deprecations apart from the first.
759 Multiple warnings are generated when a deprecated function calls
760 another deprecated function. The first warning is the one generated by
761 the explicitly called function. That's the warning that we care about.
763 differentVersion = Version('Foo', 1, 2, 3)
765 def nestedDeprecation(*args):
766 return oldMethod(*args)
767 nestedDeprecation = deprecated(differentVersion)(nestedDeprecation)
769 self.callDeprecated(differentVersion, nestedDeprecation, 24)
771 # The oldMethod deprecation should have been emitted too, not captured
772 # by callDeprecated. Flush it now to make sure it did happen and to
773 # prevent it from showing up on stdout.
774 warningsShown = self.flushWarnings()
775 self.assertEqual(len(warningsShown), 1)
778 def test_callDeprecationWithMessage(self):
780 L{callDeprecated} can take a message argument used to check the warning
783 self.callDeprecated((self.version, "newMethod"),
784 oldMethodReplaced, 1)
787 def test_callDeprecationWithWrongMessage(self):
789 If the message passed to L{callDeprecated} doesn't match,
790 L{callDeprecated} raises a test failure.
792 exception = self.assertRaises(
793 self.failureException,
795 (self.version, "something.wrong"),
796 oldMethodReplaced, 1)
797 self.assertIn(getVersionString(self.version), str(exception))
798 self.assertIn("please use newMethod instead", str(exception))
803 @deprecated(TestCallDeprecated.version)
806 Deprecated method for testing.
811 @deprecated(TestCallDeprecated.version, replacement="newMethod")
812 def oldMethodReplaced(x):
814 Another deprecated method, which has been deprecated in favor of the
815 mythical 'newMethod'.