1
# Copyright (c) 2001-2010 Twisted Matrix Laboratories.
2
# See LICENSE for details
5
Tests for assertions provided by L{twisted.trial.unittest.TestCase}.
8
import warnings, StringIO
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.python.util import dsu
15
from twisted.internet import defer
16
from twisted.trial import unittest, runner, reporter
18
class MockEquality(object):
19
def __init__(self, name):
23
return "MockEquality(%s)" % (self.name,)
25
def __eq__(self, other):
26
if not hasattr(other, 'name'):
27
raise ValueError("%r not comparable to %r" % (other, self))
28
return self.name[0] == other.name[0]
31
class TestAssertions(unittest.TestCase):
33
Tests for TestCase's assertion methods. That is, failUnless*,
36
This is pretty paranoid. Still, a certain paranoia is healthy if you
37
are testing a unit testing framework.
40
class FailingTest(unittest.TestCase):
42
raise self.failureException()
47
except self.failureException, e:
48
if not str(e) == 'failed':
49
raise self.failureException("Exception had msg %s instead of %s"
52
raise self.failureException("Call to self.fail() didn't fail test")
54
def test_failingException_fails(self):
55
test = runner.TestLoader().loadClass(TestAssertions.FailingTest)
56
io = StringIO.StringIO()
57
result = reporter.TestResult()
59
self.failIf(result.wasSuccessful())
60
self.failUnlessEqual(result.errors, [])
61
self.failUnlessEqual(len(result.failures), 1)
63
def test_failIf(self):
64
for notTrue in [0, 0.0, False, None, (), []]:
65
self.failIf(notTrue, "failed on %r" % (notTrue,))
66
for true in [1, True, 'cat', [1,2], (3,4)]:
68
self.failIf(true, "failed on %r" % (true,))
69
except self.failureException, e:
70
self.failUnlessEqual(str(e), "failed on %r" % (true,))
72
self.fail("Call to failIf(%r) didn't fail" % (true,))
74
def test_failUnless(self):
75
for notTrue in [0, 0.0, False, None, (), []]:
77
self.failUnless(notTrue, "failed on %r" % (notTrue,))
78
except self.failureException, e:
79
self.failUnlessEqual(str(e), "failed on %r" % (notTrue,))
81
self.fail("Call to failUnless(%r) didn't fail" % (notTrue,))
82
for true in [1, True, 'cat', [1,2], (3,4)]:
83
self.failUnless(true, "failed on %r" % (true,))
85
def _testEqualPair(self, first, second):
86
x = self.failUnlessEqual(first, second)
88
self.fail("failUnlessEqual should return first parameter")
90
def _testUnequalPair(self, first, second):
92
self.failUnlessEqual(first, second)
93
except self.failureException, e:
94
expected = 'not equal:\na = %s\nb = %s\n' % (
95
pformat(first), pformat(second))
96
if str(e) != expected:
97
self.fail("Expected: %r; Got: %s" % (expected, str(e)))
99
self.fail("Call to failUnlessEqual(%r, %r) didn't fail"
102
def test_failUnlessEqual_basic(self):
103
self._testEqualPair('cat', 'cat')
104
self._testUnequalPair('cat', 'dog')
105
self._testEqualPair([1], [1])
106
self._testUnequalPair([1], 'orange')
108
def test_failUnlessEqual_custom(self):
109
x = MockEquality('first')
110
y = MockEquality('second')
111
z = MockEquality('fecund')
112
self._testEqualPair(x, x)
113
self._testEqualPair(x, z)
114
self._testUnequalPair(x, y)
115
self._testUnequalPair(y, z)
117
def test_failUnlessEqualMessage(self):
119
When a message is passed to L{assertEqual}, it is included in the
122
exception = self.assertRaises(
123
self.failureException, self.assertEqual,
124
'foo', 'bar', 'message')
127
"message\nnot equal:\na = 'foo'\nb = 'bar'\n")
130
def test_failUnlessEqualNoneMessage(self):
132
If a message is specified as C{None}, it is not included in the error
133
message of L{assertEqual}.
135
exception = self.assertRaises(
136
self.failureException, self.assertEqual, 'foo', 'bar', None)
137
self.assertEqual(str(exception), "not equal:\na = 'foo'\nb = 'bar'\n")
140
def test_failUnlessEqual_incomparable(self):
141
apple = MockEquality('apple')
144
self.failUnlessEqual(apple, orange)
145
except self.failureException:
146
self.fail("Fail raised when ValueError ought to have been raised.")
148
# good. error not swallowed
151
self.fail("Comparing %r and %r should have raised an exception"
154
def _raiseError(self, error):
157
def test_failUnlessRaises_expected(self):
158
x = self.failUnlessRaises(ValueError, self._raiseError, ValueError)
159
self.failUnless(isinstance(x, ValueError),
160
"Expect failUnlessRaises to return instance of raised "
163
def test_failUnlessRaises_unexpected(self):
165
self.failUnlessRaises(ValueError, self._raiseError, TypeError)
167
self.fail("failUnlessRaises shouldn't re-raise unexpected "
169
except self.failureException, e:
173
self.fail("Expected exception wasn't raised. Should have failed")
175
def test_failUnlessRaises_noException(self):
177
self.failUnlessRaises(ValueError, lambda : None)
178
except self.failureException, e:
179
self.failUnlessEqual(str(e),
180
'ValueError not raised (None returned)')
182
self.fail("Exception not raised. Should have failed")
184
def test_failUnlessRaises_failureException(self):
185
x = self.failUnlessRaises(self.failureException, self._raiseError,
186
self.failureException)
187
self.failUnless(isinstance(x, self.failureException),
188
"Expected %r instance to be returned"
189
% (self.failureException,))
191
x = self.failUnlessRaises(self.failureException, self._raiseError,
193
except self.failureException, e:
197
self.fail("Should have raised exception")
199
def test_failIfEqual_basic(self):
200
x, y, z = [1], [2], [1]
201
ret = self.failIfEqual(x, y)
202
self.failUnlessEqual(ret, x,
203
"failIfEqual should return first parameter")
204
self.failUnlessRaises(self.failureException,
205
self.failIfEqual, x, x)
206
self.failUnlessRaises(self.failureException,
207
self.failIfEqual, x, z)
209
def test_failIfEqual_customEq(self):
210
x = MockEquality('first')
211
y = MockEquality('second')
212
z = MockEquality('fecund')
213
ret = self.failIfEqual(x, y)
214
self.failUnlessEqual(ret, x,
215
"failIfEqual should return first parameter")
216
self.failUnlessRaises(self.failureException,
217
self.failIfEqual, x, x)
218
# test when __ne__ is not defined
219
self.failIfEqual(x, z, "__ne__ not defined, so not equal")
221
def test_failUnlessIdentical(self):
222
x, y, z = [1], [1], [2]
223
ret = self.failUnlessIdentical(x, x)
224
self.failUnlessEqual(ret, x,
225
'failUnlessIdentical should return first '
227
self.failUnlessRaises(self.failureException,
228
self.failUnlessIdentical, x, y)
229
self.failUnlessRaises(self.failureException,
230
self.failUnlessIdentical, x, z)
232
def test_failUnlessApproximates(self):
233
x, y, z = 1.0, 1.1, 1.2
234
self.failUnlessApproximates(x, x, 0.2)
235
ret = self.failUnlessApproximates(x, y, 0.2)
236
self.failUnlessEqual(ret, x, "failUnlessApproximates should return "
238
self.failUnlessRaises(self.failureException,
239
self.failUnlessApproximates, x, z, 0.1)
240
self.failUnlessRaises(self.failureException,
241
self.failUnlessApproximates, x, y, 0.1)
243
def test_failUnlessAlmostEqual(self):
248
self.failUnlessAlmostEqual(x, x, precision)
249
ret = self.failUnlessAlmostEqual(x, z, precision)
250
self.failUnlessEqual(ret, x, "failUnlessAlmostEqual should return "
251
"first parameter (%r, %r)" % (ret, x))
252
self.failUnlessRaises(self.failureException,
253
self.failUnlessAlmostEqual, x, y, precision)
255
def test_failIfAlmostEqual(self):
260
ret = self.failIfAlmostEqual(x, y, precision)
261
self.failUnlessEqual(ret, x, "failIfAlmostEqual should return "
262
"first parameter (%r, %r)" % (ret, x))
263
self.failUnlessRaises(self.failureException,
264
self.failIfAlmostEqual, x, x, precision)
265
self.failUnlessRaises(self.failureException,
266
self.failIfAlmostEqual, x, z, precision)
268
def test_failUnlessSubstring(self):
272
self.failUnlessSubstring(x, x)
273
ret = self.failUnlessSubstring(x, z)
274
self.failUnlessEqual(ret, x, 'should return first parameter')
275
self.failUnlessRaises(self.failureException,
276
self.failUnlessSubstring, x, y)
277
self.failUnlessRaises(self.failureException,
278
self.failUnlessSubstring, z, x)
280
def test_failIfSubstring(self):
284
self.failIfSubstring(z, x)
285
ret = self.failIfSubstring(x, y)
286
self.failUnlessEqual(ret, x, 'should return first parameter')
287
self.failUnlessRaises(self.failureException,
288
self.failIfSubstring, x, x)
289
self.failUnlessRaises(self.failureException,
290
self.failIfSubstring, x, z)
292
def test_assertFailure(self):
293
d = defer.maybeDeferred(lambda: 1/0)
294
return self.assertFailure(d, ZeroDivisionError)
296
def test_assertFailure_wrongException(self):
297
d = defer.maybeDeferred(lambda: 1/0)
298
self.assertFailure(d, OverflowError)
299
d.addCallbacks(lambda x: self.fail('Should have failed'),
300
lambda x: x.trap(self.failureException))
303
def test_assertFailure_noException(self):
304
d = defer.succeed(None)
305
self.assertFailure(d, ZeroDivisionError)
306
d.addCallbacks(lambda x: self.fail('Should have failed'),
307
lambda x: x.trap(self.failureException))
310
def test_assertFailure_moreInfo(self):
312
In the case of assertFailure failing, check that we get lots of
313
information about the exception that was raised.
317
except ZeroDivisionError:
318
f = failure.Failure()
320
d = self.assertFailure(d, RuntimeError)
321
d.addErrback(self._checkInfo, f)
324
def _checkInfo(self, assertionFailure, f):
325
assert assertionFailure.check(self.failureException)
326
output = assertionFailure.getErrorMessage()
327
self.assertIn(f.getErrorMessage(), output)
328
self.assertIn(f.getBriefTraceback(), output)
330
def test_assertFailure_masked(self):
332
A single wrong assertFailure should fail the whole test.
334
class ExampleFailure(Exception):
337
class TC(unittest.TestCase):
338
failureException = ExampleFailure
339
def test_assertFailure(self):
340
d = defer.maybeDeferred(lambda: 1/0)
341
self.assertFailure(d, OverflowError)
342
self.assertFailure(d, ZeroDivisionError)
345
test = TC('test_assertFailure')
346
result = reporter.TestResult()
348
self.assertEqual(1, len(result.failures))
351
def test_assertWarns(self):
353
Test basic assertWarns report.
356
warnings.warn("Woo deprecated", category=DeprecationWarning)
358
r = self.assertWarns(DeprecationWarning, "Woo deprecated", __file__,
360
self.assertEquals(r, 123)
363
def test_assertWarnsRegistryClean(self):
365
Test that assertWarns cleans the warning registry, so the warning is
366
not swallowed the second time.
369
warnings.warn("Woo deprecated", category=DeprecationWarning)
371
r1 = self.assertWarns(DeprecationWarning, "Woo deprecated", __file__,
373
self.assertEquals(r1, 123)
374
# The warning should be raised again
375
r2 = self.assertWarns(DeprecationWarning, "Woo deprecated", __file__,
377
self.assertEquals(r2, 321)
380
def test_assertWarnsError(self):
382
Test assertWarns failure when no warning is generated.
386
self.assertRaises(self.failureException,
387
self.assertWarns, DeprecationWarning, "Woo deprecated", __file__,
391
def test_assertWarnsWrongCategory(self):
393
Test assertWarns failure when the category is wrong.
396
warnings.warn("Foo deprecated", category=DeprecationWarning)
398
self.assertRaises(self.failureException,
399
self.assertWarns, UserWarning, "Foo deprecated", __file__,
403
def test_assertWarnsWrongMessage(self):
405
Test assertWarns failure when the message is wrong.
408
warnings.warn("Foo deprecated", category=DeprecationWarning)
410
self.assertRaises(self.failureException,
411
self.assertWarns, DeprecationWarning, "Bar deprecated", __file__,
415
def test_assertWarnsWrongFile(self):
417
If the warning emitted by a function refers to a different file than is
418
passed to C{assertWarns}, C{failureException} is raised.
421
# stacklevel=2 points at the direct caller of the function. The
422
# way assertRaises is invoked below, the direct caller will be
423
# something somewhere in trial, not something in this file. In
424
# Python 2.5 and earlier, stacklevel of 0 resulted in a warning
425
# pointing to the warnings module itself. Starting in Python 2.6,
426
# stacklevel of 0 and 1 both result in a warning pointing to *this*
427
# file, presumably due to the fact that the warn function is
428
# implemented in C and has no convenient Python
429
# filename/linenumber.
431
"Foo deprecated", category=DeprecationWarning, stacklevel=2)
433
self.failureException,
434
# Since the direct caller isn't in this file, try to assert that
435
# the warning *does* point to this file, so that assertWarns raises
437
self.assertWarns, DeprecationWarning, "Foo deprecated", __file__,
440
def test_assertWarnsOnClass(self):
442
Test assertWarns works when creating a class instance.
446
warnings.warn("Do not call me", category=RuntimeWarning)
447
r = self.assertWarns(RuntimeWarning, "Do not call me", __file__,
449
self.assertTrue(isinstance(r, Warn))
450
r = self.assertWarns(RuntimeWarning, "Do not call me", __file__,
452
self.assertTrue(isinstance(r, Warn))
455
def test_assertWarnsOnMethod(self):
457
Test assertWarns works when used on an instance method.
460
def deprecated(self, a):
461
warnings.warn("Bar deprecated", category=DeprecationWarning)
464
r = self.assertWarns(DeprecationWarning, "Bar deprecated", __file__,
466
self.assertEquals(r, 321)
467
r = self.assertWarns(DeprecationWarning, "Bar deprecated", __file__,
469
self.assertEquals(r, 321)
472
def test_assertWarnsOnCall(self):
474
Test assertWarns works on instance with C{__call__} method.
477
def __call__(self, a):
478
warnings.warn("Egg deprecated", category=DeprecationWarning)
481
r = self.assertWarns(DeprecationWarning, "Egg deprecated", __file__,
483
self.assertEquals(r, 321)
484
r = self.assertWarns(DeprecationWarning, "Egg deprecated", __file__,
486
self.assertEquals(r, 321)
489
def test_assertWarnsFilter(self):
491
Test assertWarns on a warning filterd by default.
494
warnings.warn("Woo deprecated", category=PendingDeprecationWarning)
496
r = self.assertWarns(PendingDeprecationWarning, "Woo deprecated",
497
__file__, deprecated, 123)
498
self.assertEquals(r, 123)
501
def test_assertWarnsMultipleWarnings(self):
503
C{assertWarns} does not raise an exception if the function it is passed
504
triggers the same warning more than once.
507
warnings.warn("Woo deprecated", category=PendingDeprecationWarning)
512
PendingDeprecationWarning, "Woo deprecated", __file__, f)
515
def test_assertWarnsDifferentWarnings(self):
517
For now, assertWarns is unable to handle multiple different warnings,
518
so it should raise an exception if it's the case.
521
warnings.warn("Woo deprecated", category=DeprecationWarning)
522
warnings.warn("Another one", category=PendingDeprecationWarning)
523
e = self.assertRaises(self.failureException,
524
self.assertWarns, DeprecationWarning, "Woo deprecated",
525
__file__, deprecated, 123)
526
self.assertEquals(str(e), "Can't handle different warnings")
529
def test_assertWarnsAfterUnassertedWarning(self):
531
Warnings emitted before L{TestCase.assertWarns} is called do not get
532
flushed and do not alter the behavior of L{TestCase.assertWarns}.
534
class TheWarning(Warning):
538
warnings.warn(message, category=TheWarning)
540
self.assertWarns(TheWarning, "bar", __file__, f, "bar")
541
[warning] = self.flushWarnings([f])
542
self.assertEqual(warning['message'], "foo")
545
def test_assertIsInstance(self):
547
Test a true condition of assertIsInstance.
549
A = type('A', (object,), {})
551
self.assertIsInstance(a, A)
553
def test_assertIsInstanceMultipleClasses(self):
555
Test a true condition of assertIsInstance with multiple classes.
557
A = type('A', (object,), {})
558
B = type('B', (object,), {})
560
self.assertIsInstance(a, (A, B))
562
def test_assertIsInstanceError(self):
564
Test an error with assertIsInstance.
566
A = type('A', (object,), {})
567
B = type('B', (object,), {})
569
self.assertRaises(self.failureException, self.assertIsInstance, a, B)
571
def test_assertIsInstanceErrorMultipleClasses(self):
573
Test an error with assertIsInstance and multiple classes.
575
A = type('A', (object,), {})
576
B = type('B', (object,), {})
577
C = type('C', (object,), {})
579
self.assertRaises(self.failureException, self.assertIsInstance, a, (B, C))
581
def test_assertNotIsInstance(self):
583
Test a true condition of assertNotIsInstance.
585
A = type('A', (object,), {})
586
B = type('B', (object,), {})
588
self.assertNotIsInstance(a, B)
590
def test_assertNotIsInstanceMultipleClasses(self):
592
Test a true condition of assertNotIsInstance and multiple classes.
594
A = type('A', (object,), {})
595
B = type('B', (object,), {})
596
C = type('C', (object,), {})
598
self.assertNotIsInstance(a, (B, C))
600
def test_assertNotIsInstanceError(self):
602
Test an error with assertNotIsInstance.
604
A = type('A', (object,), {})
606
error = self.assertRaises(self.failureException,
607
self.assertNotIsInstance, a, A)
608
self.assertEquals(str(error), "%r is an instance of %s" % (a, A))
610
def test_assertNotIsInstanceErrorMultipleClasses(self):
612
Test an error with assertNotIsInstance and multiple classes.
614
A = type('A', (object,), {})
615
B = type('B', (object,), {})
617
self.assertRaises(self.failureException, self.assertNotIsInstance, a, (A, B))
621
class TestAssertionNames(unittest.TestCase):
623
Tests for consistency of naming within TestCase assertion methods
625
def _getAsserts(self):
627
reflect.accumulateMethods(self, dct, 'assert')
628
return [ dct[k] for k in dct if not k.startswith('Not') and k != '_' ]
633
def test_failUnless_matches_assert(self):
634
asserts = self._getAsserts()
635
failUnlesses = reflect.prefixedMethods(self, 'failUnless')
636
self.failUnlessEqual(dsu(asserts, self._name),
637
dsu(failUnlesses, self._name))
639
def test_failIf_matches_assertNot(self):
640
asserts = reflect.prefixedMethods(unittest.TestCase, 'assertNot')
641
failIfs = reflect.prefixedMethods(unittest.TestCase, 'failIf')
642
self.failUnlessEqual(dsu(asserts, self._name),
643
dsu(failIfs, self._name))
645
def test_equalSpelling(self):
646
for name, value in vars(self).items():
647
if not callable(value):
649
if name.endswith('Equal'):
650
self.failUnless(hasattr(self, name+'s'),
651
"%s but no %ss" % (name, name))
652
self.failUnlessEqual(value, getattr(self, name+'s'))
653
if name.endswith('Equals'):
654
self.failUnless(hasattr(self, name[:-1]),
655
"%s but no %s" % (name, name[:-1]))
656
self.failUnlessEqual(value, getattr(self, name[:-1]))
659
class TestCallDeprecated(unittest.TestCase):
661
Test use of the L{TestCase.callDeprecated} method with version objects.
664
version = Version('Twisted', 8, 0, 0)
666
def oldMethod(self, x):
668
Deprecated method for testing.
673
def test_callDeprecatedSuppressesWarning(self):
675
callDeprecated calls a deprecated callable, suppressing the
678
self.callDeprecated(self.version, self.oldMethod, 'foo')
680
self.flushWarnings(), [], "No warnings should be shown")
683
def test_callDeprecatedCallsFunction(self):
685
L{callDeprecated} actually calls the callable passed to it.
687
result = self.callDeprecated(self.version, self.oldMethod, 'foo')
688
self.assertEqual('foo', result)
691
def test_failsWithoutDeprecation(self):
693
callDeprecated raises a test failure if the callable is not
698
exception = self.assertRaises(
699
self.failureException,
700
self.callDeprecated, self.version, notDeprecated)
702
"%r is not deprecated." % notDeprecated, str(exception))
705
def test_failsWithIncorrectDeprecation(self):
707
callDeprecated raises a test failure if the callable was deprecated
708
at a different version to the one expected.
710
differentVersion = Version('Foo', 1, 2, 3)
711
exception = self.assertRaises(
712
self.failureException,
714
differentVersion, self.oldMethod, 'foo')
715
self.assertIn(getVersionString(self.version), str(exception))
716
self.assertIn(getVersionString(differentVersion), str(exception))
719
def test_nestedDeprecation(self):
721
L{callDeprecated} ignores all deprecations apart from the first.
723
Multiple warnings are generated when a deprecated function calls
724
another deprecated function. The first warning is the one generated by
725
the explicitly called function. That's the warning that we care about.
727
differentVersion = Version('Foo', 1, 2, 3)
729
def nestedDeprecation(*args):
730
return self.oldMethod(*args)
731
nestedDeprecation = deprecated(differentVersion)(nestedDeprecation)
733
self.callDeprecated(differentVersion, nestedDeprecation, 24)
735
# The oldMethod deprecation should have been emitted too, not captured
736
# by callDeprecated. Flush it now to make sure it did happen and to
737
# prevent it from showing up on stdout.
738
warningsShown = self.flushWarnings()
739
self.assertEqual(len(warningsShown), 1)
741
TestCallDeprecated.oldMethod = deprecated(TestCallDeprecated.version)(
742
TestCallDeprecated.oldMethod)