OLD | NEW |
| (Empty) |
1 # Copyright (c) 2001-2007 Twisted Matrix Laboratories. | |
2 # See LICENSE for details | |
3 | |
4 import StringIO, warnings | |
5 from pprint import pformat | |
6 | |
7 from twisted.python import reflect, failure | |
8 from twisted.python.deprecate import deprecated, getVersionString | |
9 from twisted.python.versions import Version | |
10 from twisted.python.util import dsu | |
11 from twisted.internet import defer | |
12 from twisted.trial import unittest, runner, reporter | |
13 | |
14 | |
15 class MockEquality(object): | |
16 def __init__(self, name): | |
17 self.name = name | |
18 | |
19 def __repr__(self): | |
20 return "MockEquality(%s)" % (self.name,) | |
21 | |
22 def __eq__(self, other): | |
23 if not hasattr(other, 'name'): | |
24 raise ValueError("%r not comparable to %r" % (other, self)) | |
25 return self.name[0] == other.name[0] | |
26 | |
27 | |
28 class TestAssertions(unittest.TestCase): | |
29 """Tests for TestCase's assertion methods. That is, failUnless*, | |
30 failIf*, assert*. | |
31 | |
32 This is pretty paranoid. Still, a certain paranoia is healthy if you | |
33 are testing a unit testing framework. | |
34 """ | |
35 | |
36 class FailingTest(unittest.TestCase): | |
37 def test_fails(self): | |
38 raise self.failureException() | |
39 | |
40 def testFail(self): | |
41 try: | |
42 self.fail("failed") | |
43 except self.failureException, e: | |
44 if not str(e) == 'failed': | |
45 raise self.failureException("Exception had msg %s instead of %s" | |
46 % str(e), 'failed') | |
47 else: | |
48 raise self.failureException("Call to self.fail() didn't fail test") | |
49 | |
50 def test_failingException_fails(self): | |
51 test = runner.TestLoader().loadClass(TestAssertions.FailingTest) | |
52 io = StringIO.StringIO() | |
53 result = reporter.TestResult() | |
54 test.run(result) | |
55 self.failIf(result.wasSuccessful()) | |
56 self.failUnlessEqual(result.errors, []) | |
57 self.failUnlessEqual(len(result.failures), 1) | |
58 | |
59 def test_failIf(self): | |
60 for notTrue in [0, 0.0, False, None, (), []]: | |
61 self.failIf(notTrue, "failed on %r" % (notTrue,)) | |
62 for true in [1, True, 'cat', [1,2], (3,4)]: | |
63 try: | |
64 self.failIf(true, "failed on %r" % (true,)) | |
65 except self.failureException, e: | |
66 self.failUnlessEqual(str(e), "failed on %r" % (true,)) | |
67 else: | |
68 self.fail("Call to failIf(%r) didn't fail" % (true,)) | |
69 | |
70 def test_failUnless(self): | |
71 for notTrue in [0, 0.0, False, None, (), []]: | |
72 try: | |
73 self.failUnless(notTrue, "failed on %r" % (notTrue,)) | |
74 except self.failureException, e: | |
75 self.failUnlessEqual(str(e), "failed on %r" % (notTrue,)) | |
76 else: | |
77 self.fail("Call to failUnless(%r) didn't fail" % (notTrue,)) | |
78 for true in [1, True, 'cat', [1,2], (3,4)]: | |
79 self.failUnless(true, "failed on %r" % (true,)) | |
80 | |
81 def _testEqualPair(self, first, second): | |
82 x = self.failUnlessEqual(first, second) | |
83 if x != first: | |
84 self.fail("failUnlessEqual should return first parameter") | |
85 | |
86 def _testUnequalPair(self, first, second): | |
87 try: | |
88 self.failUnlessEqual(first, second) | |
89 except self.failureException, e: | |
90 expected = 'not equal:\na = %s\nb = %s\n' % ( | |
91 pformat(first), pformat(second)) | |
92 if str(e) != expected: | |
93 self.fail("Expected: %r; Got: %s" % (expected, str(e))) | |
94 else: | |
95 self.fail("Call to failUnlessEqual(%r, %r) didn't fail" | |
96 % (first, second)) | |
97 | |
98 def test_failUnlessEqual_basic(self): | |
99 self._testEqualPair('cat', 'cat') | |
100 self._testUnequalPair('cat', 'dog') | |
101 self._testEqualPair([1], [1]) | |
102 self._testUnequalPair([1], 'orange') | |
103 | |
104 def test_failUnlessEqual_custom(self): | |
105 x = MockEquality('first') | |
106 y = MockEquality('second') | |
107 z = MockEquality('fecund') | |
108 self._testEqualPair(x, x) | |
109 self._testEqualPair(x, z) | |
110 self._testUnequalPair(x, y) | |
111 self._testUnequalPair(y, z) | |
112 | |
113 def test_failUnlessEqualMessage(self): | |
114 """ | |
115 When a message is passed to L{assertEqual}, it is included in the | |
116 error message. | |
117 """ | |
118 exception = self.assertRaises( | |
119 self.failureException, self.assertEqual, | |
120 'foo', 'bar', 'message') | |
121 self.assertEqual( | |
122 str(exception), | |
123 "message\nnot equal:\na = 'foo'\nb = 'bar'\n") | |
124 | |
125 | |
126 def test_failUnlessEqualNoneMessage(self): | |
127 """ | |
128 If a message is specified as C{None}, it is not included in the error | |
129 message of L{assertEqual}. | |
130 """ | |
131 exception = self.assertRaises( | |
132 self.failureException, self.assertEqual, 'foo', 'bar', None) | |
133 self.assertEqual(str(exception), "not equal:\na = 'foo'\nb = 'bar'\n") | |
134 | |
135 | |
136 def test_failUnlessEqual_incomparable(self): | |
137 apple = MockEquality('apple') | |
138 orange = ['orange'] | |
139 try: | |
140 self.failUnlessEqual(apple, orange) | |
141 except self.failureException: | |
142 self.fail("Fail raised when ValueError ought to have been raised.") | |
143 except ValueError: | |
144 # good. error not swallowed | |
145 pass | |
146 else: | |
147 self.fail("Comparing %r and %r should have raised an exception" | |
148 % (apple, orange)) | |
149 | |
150 def _raiseError(self, error): | |
151 raise error | |
152 | |
153 def test_failUnlessRaises_expected(self): | |
154 x = self.failUnlessRaises(ValueError, self._raiseError, ValueError) | |
155 self.failUnless(isinstance(x, ValueError), | |
156 "Expect failUnlessRaises to return instance of raised " | |
157 "exception.") | |
158 | |
159 def test_failUnlessRaises_unexpected(self): | |
160 try: | |
161 self.failUnlessRaises(ValueError, self._raiseError, TypeError) | |
162 except TypeError: | |
163 self.fail("failUnlessRaises shouldn't re-raise unexpected " | |
164 "exceptions") | |
165 except self.failureException, e: | |
166 # what we expect | |
167 pass | |
168 else: | |
169 self.fail("Expected exception wasn't raised. Should have failed") | |
170 | |
171 def test_failUnlessRaises_noException(self): | |
172 try: | |
173 self.failUnlessRaises(ValueError, lambda : None) | |
174 except self.failureException, e: | |
175 self.failUnlessEqual(str(e), | |
176 'ValueError not raised (None returned)') | |
177 else: | |
178 self.fail("Exception not raised. Should have failed") | |
179 | |
180 def test_failUnlessRaises_failureException(self): | |
181 x = self.failUnlessRaises(self.failureException, self._raiseError, | |
182 self.failureException) | |
183 self.failUnless(isinstance(x, self.failureException), | |
184 "Expected %r instance to be returned" | |
185 % (self.failureException,)) | |
186 try: | |
187 x = self.failUnlessRaises(self.failureException, self._raiseError, | |
188 ValueError) | |
189 except self.failureException, e: | |
190 # what we expect | |
191 pass | |
192 else: | |
193 self.fail("Should have raised exception") | |
194 | |
195 def test_failIfEqual_basic(self): | |
196 x, y, z = [1], [2], [1] | |
197 ret = self.failIfEqual(x, y) | |
198 self.failUnlessEqual(ret, x, | |
199 "failIfEqual should return first parameter") | |
200 self.failUnlessRaises(self.failureException, | |
201 self.failIfEqual, x, x) | |
202 self.failUnlessRaises(self.failureException, | |
203 self.failIfEqual, x, z) | |
204 | |
205 def test_failIfEqual_customEq(self): | |
206 x = MockEquality('first') | |
207 y = MockEquality('second') | |
208 z = MockEquality('fecund') | |
209 ret = self.failIfEqual(x, y) | |
210 self.failUnlessEqual(ret, x, | |
211 "failIfEqual should return first parameter") | |
212 self.failUnlessRaises(self.failureException, | |
213 self.failIfEqual, x, x) | |
214 # test when __ne__ is not defined | |
215 self.failIfEqual(x, z, "__ne__ not defined, so not equal") | |
216 | |
217 def test_failUnlessIdentical(self): | |
218 x, y, z = [1], [1], [2] | |
219 ret = self.failUnlessIdentical(x, x) | |
220 self.failUnlessEqual(ret, x, | |
221 'failUnlessIdentical should return first ' | |
222 'parameter') | |
223 self.failUnlessRaises(self.failureException, | |
224 self.failUnlessIdentical, x, y) | |
225 self.failUnlessRaises(self.failureException, | |
226 self.failUnlessIdentical, x, z) | |
227 | |
228 def test_failUnlessApproximates(self): | |
229 x, y, z = 1.0, 1.1, 1.2 | |
230 self.failUnlessApproximates(x, x, 0.2) | |
231 ret = self.failUnlessApproximates(x, y, 0.2) | |
232 self.failUnlessEqual(ret, x, "failUnlessApproximates should return " | |
233 "first parameter") | |
234 self.failUnlessRaises(self.failureException, | |
235 self.failUnlessApproximates, x, z, 0.1) | |
236 self.failUnlessRaises(self.failureException, | |
237 self.failUnlessApproximates, x, y, 0.1) | |
238 | |
239 def test_failUnlessAlmostEqual(self): | |
240 precision = 5 | |
241 x = 8.000001 | |
242 y = 8.00001 | |
243 z = 8.000002 | |
244 self.failUnlessAlmostEqual(x, x, precision) | |
245 ret = self.failUnlessAlmostEqual(x, z, precision) | |
246 self.failUnlessEqual(ret, x, "failUnlessAlmostEqual should return " | |
247 "first parameter (%r, %r)" % (ret, x)) | |
248 self.failUnlessRaises(self.failureException, | |
249 self.failUnlessAlmostEqual, x, y, precision) | |
250 | |
251 def test_failIfAlmostEqual(self): | |
252 precision = 5 | |
253 x = 8.000001 | |
254 y = 8.00001 | |
255 z = 8.000002 | |
256 ret = self.failIfAlmostEqual(x, y, precision) | |
257 self.failUnlessEqual(ret, x, "failIfAlmostEqual should return " | |
258 "first parameter (%r, %r)" % (ret, x)) | |
259 self.failUnlessRaises(self.failureException, | |
260 self.failIfAlmostEqual, x, x, precision) | |
261 self.failUnlessRaises(self.failureException, | |
262 self.failIfAlmostEqual, x, z, precision) | |
263 | |
264 def test_failUnlessSubstring(self): | |
265 x = "cat" | |
266 y = "the dog sat" | |
267 z = "the cat sat" | |
268 self.failUnlessSubstring(x, x) | |
269 ret = self.failUnlessSubstring(x, z) | |
270 self.failUnlessEqual(ret, x, 'should return first parameter') | |
271 self.failUnlessRaises(self.failureException, | |
272 self.failUnlessSubstring, x, y) | |
273 self.failUnlessRaises(self.failureException, | |
274 self.failUnlessSubstring, z, x) | |
275 | |
276 def test_failIfSubstring(self): | |
277 x = "cat" | |
278 y = "the dog sat" | |
279 z = "the cat sat" | |
280 self.failIfSubstring(z, x) | |
281 ret = self.failIfSubstring(x, y) | |
282 self.failUnlessEqual(ret, x, 'should return first parameter') | |
283 self.failUnlessRaises(self.failureException, | |
284 self.failIfSubstring, x, x) | |
285 self.failUnlessRaises(self.failureException, | |
286 self.failIfSubstring, x, z) | |
287 | |
288 def test_assertFailure(self): | |
289 d = defer.maybeDeferred(lambda: 1/0) | |
290 return self.assertFailure(d, ZeroDivisionError) | |
291 | |
292 def test_assertFailure_wrongException(self): | |
293 d = defer.maybeDeferred(lambda: 1/0) | |
294 self.assertFailure(d, OverflowError) | |
295 d.addCallbacks(lambda x: self.fail('Should have failed'), | |
296 lambda x: x.trap(self.failureException)) | |
297 return d | |
298 | |
299 def test_assertFailure_noException(self): | |
300 d = defer.succeed(None) | |
301 self.assertFailure(d, ZeroDivisionError) | |
302 d.addCallbacks(lambda x: self.fail('Should have failed'), | |
303 lambda x: x.trap(self.failureException)) | |
304 return d | |
305 | |
306 def test_assertFailure_moreInfo(self): | |
307 """In the case of assertFailure failing, check that we get lots of | |
308 information about the exception that was raised. | |
309 """ | |
310 try: | |
311 1/0 | |
312 except ZeroDivisionError: | |
313 f = failure.Failure() | |
314 d = defer.fail(f) | |
315 d = self.assertFailure(d, RuntimeError) | |
316 d.addErrback(self._checkInfo, f) | |
317 return d | |
318 | |
319 def _checkInfo(self, assertionFailure, f): | |
320 assert assertionFailure.check(self.failureException) | |
321 output = assertionFailure.getErrorMessage() | |
322 self.assertIn(f.getErrorMessage(), output) | |
323 self.assertIn(f.getBriefTraceback(), output) | |
324 | |
325 def test_assertFailure_masked(self): | |
326 """A single wrong assertFailure should fail the whole test. | |
327 """ | |
328 class ExampleFailure(Exception): | |
329 pass | |
330 | |
331 class TC(unittest.TestCase): | |
332 failureException = ExampleFailure | |
333 def test_assertFailure(self): | |
334 d = defer.maybeDeferred(lambda: 1/0) | |
335 self.assertFailure(d, OverflowError) | |
336 self.assertFailure(d, ZeroDivisionError) | |
337 return d | |
338 | |
339 test = TC('test_assertFailure') | |
340 result = reporter.TestResult() | |
341 test.run(result) | |
342 self.assertEqual(1, len(result.failures)) | |
343 | |
344 | |
345 def test_assertWarns(self): | |
346 """ | |
347 Test basic assertWarns report. | |
348 """ | |
349 def deprecated(a): | |
350 warnings.warn("Woo deprecated", category=DeprecationWarning) | |
351 return a | |
352 r = self.assertWarns(DeprecationWarning, "Woo deprecated", __file__, | |
353 deprecated, 123) | |
354 self.assertEquals(r, 123) | |
355 | |
356 | |
357 def test_assertWarnsRegistryClean(self): | |
358 """ | |
359 Test that assertWarns cleans the warning registry, so the warning is | |
360 not swallowed the second time. | |
361 """ | |
362 def deprecated(a): | |
363 warnings.warn("Woo deprecated", category=DeprecationWarning) | |
364 return a | |
365 r1 = self.assertWarns(DeprecationWarning, "Woo deprecated", __file__, | |
366 deprecated, 123) | |
367 self.assertEquals(r1, 123) | |
368 # The warning should be raised again | |
369 r2 = self.assertWarns(DeprecationWarning, "Woo deprecated", __file__, | |
370 deprecated, 321) | |
371 self.assertEquals(r2, 321) | |
372 | |
373 | |
374 def test_assertWarnsError(self): | |
375 """ | |
376 Test assertWarns failure when no warning is generated. | |
377 """ | |
378 def normal(a): | |
379 return a | |
380 self.assertRaises(self.failureException, | |
381 self.assertWarns, DeprecationWarning, "Woo deprecated", __file__, | |
382 normal, 123) | |
383 | |
384 | |
385 def test_assertWarnsWrongCategory(self): | |
386 """ | |
387 Test assertWarns failure when the category is wrong. | |
388 """ | |
389 def deprecated(a): | |
390 warnings.warn("Foo deprecated", category=DeprecationWarning) | |
391 return a | |
392 self.assertRaises(self.failureException, | |
393 self.assertWarns, UserWarning, "Foo deprecated", __file__, | |
394 deprecated, 123) | |
395 | |
396 | |
397 def test_assertWarnsWrongMessage(self): | |
398 """ | |
399 Test assertWarns failure when the message is wrong. | |
400 """ | |
401 def deprecated(a): | |
402 warnings.warn("Foo deprecated", category=DeprecationWarning) | |
403 return a | |
404 self.assertRaises(self.failureException, | |
405 self.assertWarns, DeprecationWarning, "Bar deprecated", __file__, | |
406 deprecated, 123) | |
407 | |
408 | |
409 def test_assertWarnsOnClass(self): | |
410 """ | |
411 Test asserWarns works when creating a class instance. | |
412 """ | |
413 class Warn: | |
414 def __init__(self): | |
415 warnings.warn("Do not call me", category=RuntimeWarning) | |
416 r = self.assertWarns(RuntimeWarning, "Do not call me", __file__, | |
417 Warn) | |
418 self.assertTrue(isinstance(r, Warn)) | |
419 r = self.assertWarns(RuntimeWarning, "Do not call me", __file__, | |
420 Warn) | |
421 self.assertTrue(isinstance(r, Warn)) | |
422 | |
423 | |
424 def test_assertWarnsOnMethod(self): | |
425 """ | |
426 Test assertWarns works when used on an instance method. | |
427 """ | |
428 class Warn: | |
429 def deprecated(self, a): | |
430 warnings.warn("Bar deprecated", category=DeprecationWarning) | |
431 return a | |
432 w = Warn() | |
433 r = self.assertWarns(DeprecationWarning, "Bar deprecated", __file__, | |
434 w.deprecated, 321) | |
435 self.assertEquals(r, 321) | |
436 r = self.assertWarns(DeprecationWarning, "Bar deprecated", __file__, | |
437 w.deprecated, 321) | |
438 self.assertEquals(r, 321) | |
439 | |
440 | |
441 def test_assertWarnsOnCall(self): | |
442 """ | |
443 Test assertWarns works on instance with C{__call__} method. | |
444 """ | |
445 class Warn: | |
446 def __call__(self, a): | |
447 warnings.warn("Egg deprecated", category=DeprecationWarning) | |
448 return a | |
449 w = Warn() | |
450 r = self.assertWarns(DeprecationWarning, "Egg deprecated", __file__, | |
451 w, 321) | |
452 self.assertEquals(r, 321) | |
453 r = self.assertWarns(DeprecationWarning, "Egg deprecated", __file__, | |
454 w, 321) | |
455 self.assertEquals(r, 321) | |
456 | |
457 | |
458 def test_assertWarnsFilter(self): | |
459 """ | |
460 Test assertWarns on a warning filterd by default. | |
461 """ | |
462 def deprecated(a): | |
463 warnings.warn("Woo deprecated", category=PendingDeprecationWarning) | |
464 return a | |
465 r = self.assertWarns(PendingDeprecationWarning, "Woo deprecated", | |
466 __file__, deprecated, 123) | |
467 self.assertEquals(r, 123) | |
468 | |
469 | |
470 def test_assertWarnsMultipleWarnings(self): | |
471 """ | |
472 Check that assertWarns is able to handle multiple warnings produced by | |
473 the same function. | |
474 """ | |
475 i = [0] | |
476 def deprecated(a): | |
477 # the stacklevel is important here, because as the function is | |
478 # recursive, the warnings produced have a different stack, but we | |
479 # want to be sure that only the first warning is tested against | |
480 warnings.warn("Woo deprecated", | |
481 category=PendingDeprecationWarning, | |
482 stacklevel=2) | |
483 i[0] += 1 | |
484 if i[0] < 3: | |
485 return deprecated(a) | |
486 else: | |
487 return a | |
488 r = self.assertWarns(PendingDeprecationWarning, "Woo deprecated", | |
489 unittest.__file__, deprecated, 123) | |
490 self.assertEquals(r, 123) | |
491 | |
492 | |
493 def test_assertWarnsDifferentWarnings(self): | |
494 """ | |
495 For now, assertWarns is unable to handle multiple different warnings, | |
496 so it should raise an exception if it's the case. | |
497 """ | |
498 def deprecated(a): | |
499 warnings.warn("Woo deprecated", category=DeprecationWarning) | |
500 warnings.warn("Another one", category=PendingDeprecationWarning) | |
501 e = self.assertRaises(self.failureException, | |
502 self.assertWarns, DeprecationWarning, "Woo deprecated", | |
503 __file__, deprecated, 123) | |
504 self.assertEquals(str(e), "Can't handle different warnings") | |
505 | |
506 | |
507 def test_assertIsInstance(self): | |
508 """ | |
509 Test a true condition of assertIsInstance. | |
510 """ | |
511 A = type('A', (object,), {}) | |
512 a = A() | |
513 self.assertIsInstance(a, A) | |
514 | |
515 def test_assertIsInstanceMultipleClasses(self): | |
516 """ | |
517 Test a true condition of assertIsInstance with multiple classes. | |
518 """ | |
519 A = type('A', (object,), {}) | |
520 B = type('B', (object,), {}) | |
521 a = A() | |
522 self.assertIsInstance(a, (A, B)) | |
523 | |
524 def test_assertIsInstanceError(self): | |
525 """ | |
526 Test an error with assertIsInstance. | |
527 """ | |
528 A = type('A', (object,), {}) | |
529 B = type('B', (object,), {}) | |
530 a = A() | |
531 self.assertRaises(self.failureException, self.assertIsInstance, a, B) | |
532 | |
533 def test_assertIsInstanceErrorMultipleClasses(self): | |
534 """ | |
535 Test an error with assertIsInstance and multiple classes. | |
536 """ | |
537 A = type('A', (object,), {}) | |
538 B = type('B', (object,), {}) | |
539 C = type('C', (object,), {}) | |
540 a = A() | |
541 self.assertRaises(self.failureException, self.assertIsInstance, a, (B, C
)) | |
542 | |
543 def test_assertNotIsInstance(self): | |
544 """ | |
545 Test a true condition of assertNotIsInstance. | |
546 """ | |
547 A = type('A', (object,), {}) | |
548 B = type('B', (object,), {}) | |
549 a = A() | |
550 self.assertNotIsInstance(a, B) | |
551 | |
552 def test_assertNotIsInstanceMultipleClasses(self): | |
553 """ | |
554 Test a true condition of assertNotIsInstance and multiple classes. | |
555 """ | |
556 A = type('A', (object,), {}) | |
557 B = type('B', (object,), {}) | |
558 C = type('C', (object,), {}) | |
559 a = A() | |
560 self.assertNotIsInstance(a, (B, C)) | |
561 | |
562 def test_assertNotIsInstanceError(self): | |
563 """ | |
564 Test an error with assertNotIsInstance. | |
565 """ | |
566 A = type('A', (object,), {}) | |
567 a = A() | |
568 self.assertRaises(self.failureException, self.assertNotIsInstance, a, A) | |
569 | |
570 def test_assertNotIsInstanceErrorMultipleClasses(self): | |
571 """ | |
572 Test an error with assertNotIsInstance and multiple classes. | |
573 """ | |
574 A = type('A', (object,), {}) | |
575 B = type('B', (object,), {}) | |
576 a = A() | |
577 self.assertRaises(self.failureException, self.assertNotIsInstance, a, (A
, B)) | |
578 | |
579 | |
580 | |
581 class TestAssertionNames(unittest.TestCase): | |
582 """Tests for consistency of naming within TestCase assertion methods | |
583 """ | |
584 def _getAsserts(self): | |
585 dct = {} | |
586 reflect.accumulateMethods(self, dct, 'assert') | |
587 return [ dct[k] for k in dct if not k.startswith('Not') and k != '_' ] | |
588 | |
589 def _name(self, x): | |
590 return x.__name__ | |
591 | |
592 def test_failUnless_matches_assert(self): | |
593 asserts = self._getAsserts() | |
594 failUnlesses = reflect.prefixedMethods(self, 'failUnless') | |
595 self.failUnlessEqual(dsu(asserts, self._name), | |
596 dsu(failUnlesses, self._name)) | |
597 | |
598 def test_failIf_matches_assertNot(self): | |
599 asserts = reflect.prefixedMethods(unittest.TestCase, 'assertNot') | |
600 failIfs = reflect.prefixedMethods(unittest.TestCase, 'failIf') | |
601 self.failUnlessEqual(dsu(asserts, self._name), | |
602 dsu(failIfs, self._name)) | |
603 | |
604 def test_equalSpelling(self): | |
605 for name, value in vars(self).items(): | |
606 if not callable(value): | |
607 continue | |
608 if name.endswith('Equal'): | |
609 self.failUnless(hasattr(self, name+'s'), | |
610 "%s but no %ss" % (name, name)) | |
611 self.failUnlessEqual(value, getattr(self, name+'s')) | |
612 if name.endswith('Equals'): | |
613 self.failUnless(hasattr(self, name[:-1]), | |
614 "%s but no %s" % (name, name[:-1])) | |
615 self.failUnlessEqual(value, getattr(self, name[:-1])) | |
616 | |
617 | |
618 class TestCallDeprecated(unittest.TestCase): | |
619 """ | |
620 Test the L{TestCase.callDeprecated} method. | |
621 """ | |
622 | |
623 version = Version('Twisted', 8, 0, 0) | |
624 | |
625 def oldMethod(self, x): | |
626 """ | |
627 Deprecated method for testing. | |
628 """ | |
629 return x | |
630 oldMethod = deprecated(version)(oldMethod) | |
631 | |
632 | |
633 def test_callDeprecatedSuppressesWarning(self): | |
634 """ | |
635 callDeprecated calls a deprecated callable, suppressing the | |
636 deprecation warning. | |
637 """ | |
638 warningsShown = [] | |
639 def warnExplicit(*args): | |
640 warningsShown.append(args) | |
641 self.patch(warnings, 'warn_explicit', warnExplicit) | |
642 self.callDeprecated(self.version, self.oldMethod, 'foo') | |
643 self.assertEqual([], warningsShown, "No warnings should be shown") | |
644 | |
645 | |
646 def test_callDeprecatedCallsFunction(self): | |
647 """ | |
648 L{callDeprecated} actually calls the callable passed to it. | |
649 """ | |
650 result = self.callDeprecated(self.version, self.oldMethod, 'foo') | |
651 self.assertEqual('foo', result) | |
652 | |
653 | |
654 def test_failsWithoutDeprecation(self): | |
655 """ | |
656 callDeprecated raises a test failure if the callable is not | |
657 deprecated. | |
658 """ | |
659 def notDeprecated(): | |
660 pass | |
661 exception = self.assertRaises( | |
662 self.failureException, | |
663 self.callDeprecated, self.version, notDeprecated) | |
664 self.assertEqual( | |
665 "%r is not deprecated." % notDeprecated, str(exception)) | |
666 | |
667 | |
668 def test_failsWithIncorrectDeprecation(self): | |
669 """ | |
670 callDeprecated raises a test failure if the callable was deprecated | |
671 at a different version to the one expected. | |
672 """ | |
673 differentVersion = Version('Foo', 1, 2, 3) | |
674 exception = self.assertRaises( | |
675 self.failureException, | |
676 self.callDeprecated, | |
677 differentVersion, self.oldMethod, 'foo') | |
678 self.assertIn(getVersionString(self.version), str(exception)) | |
679 self.assertIn(getVersionString(differentVersion), str(exception)) | |
680 | |
681 | |
682 def test_nestedDeprecation(self): | |
683 """ | |
684 L{callDeprecated} ignores all deprecations apart from the first. | |
685 | |
686 Multiple warnings are generated when a deprecated function calls | |
687 another deprecated function. The first warning is the one generated by | |
688 the explicitly called function. That's the warning that we care about. | |
689 """ | |
690 differentVersion = Version('Foo', 1, 2, 3) | |
691 | |
692 def nestedDeprecation(*args): | |
693 return self.oldMethod(*args) | |
694 nestedDeprecation = deprecated(differentVersion)(nestedDeprecation) | |
695 | |
696 self.callDeprecated(differentVersion, nestedDeprecation, 24) | |
OLD | NEW |