s4-python: Install external included packages only if they're not present on the...
[tridge/samba.git] / lib / testtools / testtools / tests / test_testtools.py
1 # Copyright (c) 2008 Jonathan M. Lange. See LICENSE for details.
2
3 """Tests for extensions to the base test library."""
4
5 import sys
6 import unittest
7
8 from testtools import (
9     TestCase,
10     clone_test_with_new_id,
11     content,
12     skip,
13     skipIf,
14     skipUnless,
15     testcase,
16     )
17 from testtools.matchers import (
18     Equals,
19     )
20 from testtools.tests.helpers import (
21     an_exc_info,
22     LoggingResult,
23     Python26TestResult,
24     Python27TestResult,
25     ExtendedTestResult,
26     )
27
28
29 class TestEquality(TestCase):
30     """Test `TestCase`'s equality implementation."""
31
32     def test_identicalIsEqual(self):
33         # TestCase's are equal if they are identical.
34         self.assertEqual(self, self)
35
36     def test_nonIdenticalInUnequal(self):
37         # TestCase's are not equal if they are not identical.
38         self.assertNotEqual(TestCase(methodName='run'),
39             TestCase(methodName='skip'))
40
41
42 class TestAssertions(TestCase):
43     """Test assertions in TestCase."""
44
45     def raiseError(self, exceptionFactory, *args, **kwargs):
46         raise exceptionFactory(*args, **kwargs)
47
48     def test_formatTypes_single(self):
49         # Given a single class, _formatTypes returns the name.
50         class Foo:
51             pass
52         self.assertEqual('Foo', self._formatTypes(Foo))
53
54     def test_formatTypes_multiple(self):
55         # Given multiple types, _formatTypes returns the names joined by
56         # commas.
57         class Foo:
58             pass
59         class Bar:
60             pass
61         self.assertEqual('Foo, Bar', self._formatTypes([Foo, Bar]))
62
63     def test_assertRaises(self):
64         # assertRaises asserts that a callable raises a particular exception.
65         self.assertRaises(RuntimeError, self.raiseError, RuntimeError)
66
67     def test_assertRaises_fails_when_no_error_raised(self):
68         # assertRaises raises self.failureException when it's passed a
69         # callable that raises no error.
70         ret = ('orange', 42)
71         try:
72             self.assertRaises(RuntimeError, lambda: ret)
73         except self.failureException:
74             # We expected assertRaises to raise this exception.
75             e = sys.exc_info()[1]
76             self.assertEqual(
77                 '%s not raised, %r returned instead.'
78                 % (self._formatTypes(RuntimeError), ret), str(e))
79         else:
80             self.fail('Expected assertRaises to fail, but it did not.')
81
82     def test_assertRaises_fails_when_different_error_raised(self):
83         # assertRaises re-raises an exception that it didn't expect.
84         self.assertRaises(
85             ZeroDivisionError,
86             self.assertRaises,
87                 RuntimeError, self.raiseError, ZeroDivisionError)
88
89     def test_assertRaises_returns_the_raised_exception(self):
90         # assertRaises returns the exception object that was raised. This is
91         # useful for testing that exceptions have the right message.
92
93         # This contraption stores the raised exception, so we can compare it
94         # to the return value of assertRaises.
95         raisedExceptions = []
96         def raiseError():
97             try:
98                 raise RuntimeError('Deliberate error')
99             except RuntimeError:
100                 raisedExceptions.append(sys.exc_info()[1])
101                 raise
102
103         exception = self.assertRaises(RuntimeError, raiseError)
104         self.assertEqual(1, len(raisedExceptions))
105         self.assertTrue(
106             exception is raisedExceptions[0],
107             "%r is not %r" % (exception, raisedExceptions[0]))
108
109     def test_assertRaises_with_multiple_exceptions(self):
110         # assertRaises((ExceptionOne, ExceptionTwo), function) asserts that
111         # function raises one of ExceptionTwo or ExceptionOne.
112         expectedExceptions = (RuntimeError, ZeroDivisionError)
113         self.assertRaises(
114             expectedExceptions, self.raiseError, expectedExceptions[0])
115         self.assertRaises(
116             expectedExceptions, self.raiseError, expectedExceptions[1])
117
118     def test_assertRaises_with_multiple_exceptions_failure_mode(self):
119         # If assertRaises is called expecting one of a group of exceptions and
120         # a callable that doesn't raise an exception, then fail with an
121         # appropriate error message.
122         expectedExceptions = (RuntimeError, ZeroDivisionError)
123         failure = self.assertRaises(
124             self.failureException,
125             self.assertRaises, expectedExceptions, lambda: None)
126         self.assertEqual(
127             '%s not raised, None returned instead.'
128             % self._formatTypes(expectedExceptions), str(failure))
129
130     def assertFails(self, message, function, *args, **kwargs):
131         """Assert that function raises a failure with the given message."""
132         failure = self.assertRaises(
133             self.failureException, function, *args, **kwargs)
134         self.assertEqual(message, str(failure))
135
136     def test_assertIn_success(self):
137         # assertIn(needle, haystack) asserts that 'needle' is in 'haystack'.
138         self.assertIn(3, range(10))
139         self.assertIn('foo', 'foo bar baz')
140         self.assertIn('foo', 'foo bar baz'.split())
141
142     def test_assertIn_failure(self):
143         # assertIn(needle, haystack) fails the test when 'needle' is not in
144         # 'haystack'.
145         self.assertFails('3 not in [0, 1, 2]', self.assertIn, 3, [0, 1, 2])
146         self.assertFails(
147             '%r not in %r' % ('qux', 'foo bar baz'),
148             self.assertIn, 'qux', 'foo bar baz')
149
150     def test_assertNotIn_success(self):
151         # assertNotIn(needle, haystack) asserts that 'needle' is not in
152         # 'haystack'.
153         self.assertNotIn(3, [0, 1, 2])
154         self.assertNotIn('qux', 'foo bar baz')
155
156     def test_assertNotIn_failure(self):
157         # assertNotIn(needle, haystack) fails the test when 'needle' is in
158         # 'haystack'.
159         self.assertFails('3 in [1, 2, 3]', self.assertNotIn, 3, [1, 2, 3])
160         self.assertFails(
161             '%r in %r' % ('foo', 'foo bar baz'),
162             self.assertNotIn, 'foo', 'foo bar baz')
163
164     def test_assertIsInstance(self):
165         # assertIsInstance asserts that an object is an instance of a class.
166
167         class Foo:
168             """Simple class for testing assertIsInstance."""
169
170         foo = Foo()
171         self.assertIsInstance(foo, Foo)
172
173     def test_assertIsInstance_multiple_classes(self):
174         # assertIsInstance asserts that an object is an instance of one of a
175         # group of classes.
176
177         class Foo:
178             """Simple class for testing assertIsInstance."""
179
180         class Bar:
181             """Another simple class for testing assertIsInstance."""
182
183         foo = Foo()
184         self.assertIsInstance(foo, (Foo, Bar))
185         self.assertIsInstance(Bar(), (Foo, Bar))
186
187     def test_assertIsInstance_failure(self):
188         # assertIsInstance(obj, klass) fails the test when obj is not an
189         # instance of klass.
190
191         class Foo:
192             """Simple class for testing assertIsInstance."""
193
194         self.assertFails(
195             '42 is not an instance of %s' % self._formatTypes(Foo),
196             self.assertIsInstance, 42, Foo)
197
198     def test_assertIsInstance_failure_multiple_classes(self):
199         # assertIsInstance(obj, (klass1, klass2)) fails the test when obj is
200         # not an instance of klass1 or klass2.
201
202         class Foo:
203             """Simple class for testing assertIsInstance."""
204
205         class Bar:
206             """Another simple class for testing assertIsInstance."""
207
208         self.assertFails(
209             '42 is not an instance of %s' % self._formatTypes([Foo, Bar]),
210             self.assertIsInstance, 42, (Foo, Bar))
211
212     def test_assertIs(self):
213         # assertIs asserts that an object is identical to another object.
214         self.assertIs(None, None)
215         some_list = [42]
216         self.assertIs(some_list, some_list)
217         some_object = object()
218         self.assertIs(some_object, some_object)
219
220     def test_assertIs_fails(self):
221         # assertIs raises assertion errors if one object is not identical to
222         # another.
223         self.assertFails('None is not 42', self.assertIs, None, 42)
224         self.assertFails('[42] is not [42]', self.assertIs, [42], [42])
225
226     def test_assertIs_fails_with_message(self):
227         # assertIs raises assertion errors if one object is not identical to
228         # another, and includes a user-supplied message, if it's provided.
229         self.assertFails(
230             'None is not 42: foo bar', self.assertIs, None, 42, 'foo bar')
231
232     def test_assertIsNot(self):
233         # assertIsNot asserts that an object is not identical to another
234         # object.
235         self.assertIsNot(None, 42)
236         self.assertIsNot([42], [42])
237         self.assertIsNot(object(), object())
238
239     def test_assertIsNot_fails(self):
240         # assertIsNot raises assertion errors if one object is identical to
241         # another.
242         self.assertFails('None is None', self.assertIsNot, None, None)
243         some_list = [42]
244         self.assertFails(
245             '[42] is [42]', self.assertIsNot, some_list, some_list)
246
247     def test_assertIsNot_fails_with_message(self):
248         # assertIsNot raises assertion errors if one object is identical to
249         # another, and includes a user-supplied message if it's provided.
250         self.assertFails(
251             'None is None: foo bar', self.assertIsNot, None, None, "foo bar")
252
253     def test_assertThat_matches_clean(self):
254         class Matcher:
255             def match(self, foo):
256                 return None
257         self.assertThat("foo", Matcher())
258
259     def test_assertThat_mismatch_raises_description(self):
260         calls = []
261         class Mismatch:
262             def __init__(self, thing):
263                 self.thing = thing
264             def describe(self):
265                 calls.append(('describe_diff', self.thing))
266                 return "object is not a thing"
267         class Matcher:
268             def match(self, thing):
269                 calls.append(('match', thing))
270                 return Mismatch(thing)
271             def __str__(self):
272                 calls.append(('__str__',))
273                 return "a description"
274         class Test(TestCase):
275             def test(self):
276                 self.assertThat("foo", Matcher())
277         result = Test("test").run()
278         self.assertEqual([
279             ('match', "foo"),
280             ('describe_diff', "foo"),
281             ('__str__',),
282             ], calls)
283         self.assertFalse(result.wasSuccessful())
284
285
286 class TestAddCleanup(TestCase):
287     """Tests for TestCase.addCleanup."""
288
289     class LoggingTest(TestCase):
290         """A test that logs calls to setUp, runTest and tearDown."""
291
292         def setUp(self):
293             TestCase.setUp(self)
294             self._calls = ['setUp']
295
296         def brokenSetUp(self):
297             # A tearDown that deliberately fails.
298             self._calls = ['brokenSetUp']
299             raise RuntimeError('Deliberate Failure')
300
301         def runTest(self):
302             self._calls.append('runTest')
303
304         def tearDown(self):
305             self._calls.append('tearDown')
306             TestCase.tearDown(self)
307
308     def setUp(self):
309         TestCase.setUp(self)
310         self._result_calls = []
311         self.test = TestAddCleanup.LoggingTest('runTest')
312         self.logging_result = LoggingResult(self._result_calls)
313
314     def assertErrorLogEqual(self, messages):
315         self.assertEqual(messages, [call[0] for call in self._result_calls])
316
317     def assertTestLogEqual(self, messages):
318         """Assert that the call log equals 'messages'."""
319         case = self._result_calls[0][1]
320         self.assertEqual(messages, case._calls)
321
322     def logAppender(self, message):
323         """A cleanup that appends 'message' to the tests log.
324
325         Cleanups are callables that are added to a test by addCleanup. To
326         verify that our cleanups run in the right order, we add strings to a
327         list that acts as a log. This method returns a cleanup that will add
328         the given message to that log when run.
329         """
330         self.test._calls.append(message)
331
332     def test_fixture(self):
333         # A normal run of self.test logs 'setUp', 'runTest' and 'tearDown'.
334         # This test doesn't test addCleanup itself, it just sanity checks the
335         # fixture.
336         self.test.run(self.logging_result)
337         self.assertTestLogEqual(['setUp', 'runTest', 'tearDown'])
338
339     def test_cleanup_run_before_tearDown(self):
340         # Cleanup functions added with 'addCleanup' are called before tearDown
341         # runs.
342         self.test.addCleanup(self.logAppender, 'cleanup')
343         self.test.run(self.logging_result)
344         self.assertTestLogEqual(['setUp', 'runTest', 'tearDown', 'cleanup'])
345
346     def test_add_cleanup_called_if_setUp_fails(self):
347         # Cleanup functions added with 'addCleanup' are called even if setUp
348         # fails. Note that tearDown has a different behavior: it is only
349         # called when setUp succeeds.
350         self.test.setUp = self.test.brokenSetUp
351         self.test.addCleanup(self.logAppender, 'cleanup')
352         self.test.run(self.logging_result)
353         self.assertTestLogEqual(['brokenSetUp', 'cleanup'])
354
355     def test_addCleanup_called_in_reverse_order(self):
356         # Cleanup functions added with 'addCleanup' are called in reverse
357         # order.
358         #
359         # One of the main uses of addCleanup is to dynamically create
360         # resources that need some sort of explicit tearDown. Often one
361         # resource will be created in terms of another, e.g.,
362         #     self.first = self.makeFirst()
363         #     self.second = self.makeSecond(self.first)
364         #
365         # When this happens, we generally want to clean up the second resource
366         # before the first one, since the second depends on the first.
367         self.test.addCleanup(self.logAppender, 'first')
368         self.test.addCleanup(self.logAppender, 'second')
369         self.test.run(self.logging_result)
370         self.assertTestLogEqual(
371             ['setUp', 'runTest', 'tearDown', 'second', 'first'])
372
373     def test_tearDown_runs_after_cleanup_failure(self):
374         # tearDown runs even if a cleanup function fails.
375         self.test.addCleanup(lambda: 1/0)
376         self.test.run(self.logging_result)
377         self.assertTestLogEqual(['setUp', 'runTest', 'tearDown'])
378
379     def test_cleanups_continue_running_after_error(self):
380         # All cleanups are always run, even if one or two of them fail.
381         self.test.addCleanup(self.logAppender, 'first')
382         self.test.addCleanup(lambda: 1/0)
383         self.test.addCleanup(self.logAppender, 'second')
384         self.test.run(self.logging_result)
385         self.assertTestLogEqual(
386             ['setUp', 'runTest', 'tearDown', 'second', 'first'])
387
388     def test_error_in_cleanups_are_captured(self):
389         # If a cleanup raises an error, we want to record it and fail the the
390         # test, even though we go on to run other cleanups.
391         self.test.addCleanup(lambda: 1/0)
392         self.test.run(self.logging_result)
393         self.assertErrorLogEqual(['startTest', 'addError', 'stopTest'])
394
395     def test_keyboard_interrupt_not_caught(self):
396         # If a cleanup raises KeyboardInterrupt, it gets reraised.
397         def raiseKeyboardInterrupt():
398             raise KeyboardInterrupt()
399         self.test.addCleanup(raiseKeyboardInterrupt)
400         self.assertRaises(
401             KeyboardInterrupt, self.test.run, self.logging_result)
402
403     def test_multipleErrorsReported(self):
404         # Errors from all failing cleanups are reported.
405         self.test.addCleanup(lambda: 1/0)
406         self.test.addCleanup(lambda: 1/0)
407         self.test.run(self.logging_result)
408         self.assertErrorLogEqual(
409             ['startTest', 'addError', 'addError', 'stopTest'])
410
411
412 class TestWithDetails(TestCase):
413
414     def assertDetailsProvided(self, case, expected_outcome, expected_keys):
415         """Assert that when case is run, details are provided to the result.
416
417         :param case: A TestCase to run.
418         :param expected_outcome: The call that should be made.
419         :param expected_keys: The keys to look for.
420         """
421         result = ExtendedTestResult()
422         case.run(result)
423         case = result._events[0][1]
424         expected = [
425             ('startTest', case),
426             (expected_outcome, case),
427             ('stopTest', case),
428             ]
429         self.assertEqual(3, len(result._events))
430         self.assertEqual(expected[0], result._events[0])
431         self.assertEqual(expected[1], result._events[1][0:2])
432         # Checking the TB is right is rather tricky. doctest line matching
433         # would help, but 'meh'.
434         self.assertEqual(sorted(expected_keys),
435             sorted(result._events[1][2].keys()))
436         self.assertEqual(expected[-1], result._events[-1])
437
438     def get_content(self):
439         return content.Content(
440             content.ContentType("text", "foo"), lambda: ['foo'])
441
442
443 class TestExpectedFailure(TestWithDetails):
444     """Tests for expected failures and unexpected successess."""
445
446     def make_unexpected_case(self):
447         class Case(TestCase):
448             def test(self):
449                 raise testcase._UnexpectedSuccess
450         case = Case('test')
451         return case
452
453     def test_raising__UnexpectedSuccess_py27(self):
454         case = self.make_unexpected_case()
455         result = Python27TestResult()
456         case.run(result)
457         case = result._events[0][1]
458         self.assertEqual([
459             ('startTest', case),
460             ('addUnexpectedSuccess', case),
461             ('stopTest', case),
462             ], result._events)
463
464     def test_raising__UnexpectedSuccess_extended(self):
465         case = self.make_unexpected_case()
466         result = ExtendedTestResult()
467         case.run(result)
468         case = result._events[0][1]
469         self.assertEqual([
470             ('startTest', case),
471             ('addUnexpectedSuccess', case, {}),
472             ('stopTest', case),
473             ], result._events)
474
475     def make_xfail_case_xfails(self):
476         content = self.get_content()
477         class Case(TestCase):
478             def test(self):
479                 self.addDetail("foo", content)
480                 self.expectFailure("we are sad", self.assertEqual,
481                     1, 0)
482         case = Case('test')
483         return case
484
485     def make_xfail_case_succeeds(self):
486         content = self.get_content()
487         class Case(TestCase):
488             def test(self):
489                 self.addDetail("foo", content)
490                 self.expectFailure("we are sad", self.assertEqual,
491                     1, 1)
492         case = Case('test')
493         return case
494
495     def test_expectFailure_KnownFailure_extended(self):
496         case = self.make_xfail_case_xfails()
497         self.assertDetailsProvided(case, "addExpectedFailure",
498             ["foo", "traceback", "reason"])
499
500     def test_expectFailure_KnownFailure_unexpected_success(self):
501         case = self.make_xfail_case_succeeds()
502         self.assertDetailsProvided(case, "addUnexpectedSuccess",
503             ["foo", "reason"])
504
505
506 class TestUniqueFactories(TestCase):
507     """Tests for getUniqueString and getUniqueInteger."""
508
509     def test_getUniqueInteger(self):
510         # getUniqueInteger returns an integer that increments each time you
511         # call it.
512         one = self.getUniqueInteger()
513         self.assertEqual(1, one)
514         two = self.getUniqueInteger()
515         self.assertEqual(2, two)
516
517     def test_getUniqueString(self):
518         # getUniqueString returns the current test id followed by a unique
519         # integer.
520         name_one = self.getUniqueString()
521         self.assertEqual('%s-%d' % (self.id(), 1), name_one)
522         name_two = self.getUniqueString()
523         self.assertEqual('%s-%d' % (self.id(), 2), name_two)
524
525     def test_getUniqueString_prefix(self):
526         # If getUniqueString is given an argument, it uses that argument as
527         # the prefix of the unique string, rather than the test id.
528         name_one = self.getUniqueString('foo')
529         self.assertThat(name_one, Equals('foo-1'))
530         name_two = self.getUniqueString('bar')
531         self.assertThat(name_two, Equals('bar-2'))
532
533
534 class TestCloneTestWithNewId(TestCase):
535     """Tests for clone_test_with_new_id."""
536
537     def test_clone_test_with_new_id(self):
538         class FooTestCase(TestCase):
539             def test_foo(self):
540                 pass
541         test = FooTestCase('test_foo')
542         oldName = test.id()
543         newName = self.getUniqueString()
544         newTest = clone_test_with_new_id(test, newName)
545         self.assertEqual(newName, newTest.id())
546         self.assertEqual(oldName, test.id(),
547             "the original test instance should be unchanged.")
548
549
550 class TestDetailsProvided(TestWithDetails):
551
552     def test_addDetail(self):
553         mycontent = self.get_content()
554         self.addDetail("foo", mycontent)
555         details = self.getDetails()
556         self.assertEqual({"foo": mycontent}, details)
557
558     def test_addError(self):
559         class Case(TestCase):
560             def test(this):
561                 this.addDetail("foo", self.get_content())
562                 1/0
563         self.assertDetailsProvided(Case("test"), "addError",
564             ["foo", "traceback"])
565
566     def test_addFailure(self):
567         class Case(TestCase):
568             def test(this):
569                 this.addDetail("foo", self.get_content())
570                 self.fail('yo')
571         self.assertDetailsProvided(Case("test"), "addFailure",
572             ["foo", "traceback"])
573
574     def test_addSkip(self):
575         class Case(TestCase):
576             def test(this):
577                 this.addDetail("foo", self.get_content())
578                 self.skip('yo')
579         self.assertDetailsProvided(Case("test"), "addSkip",
580             ["foo", "reason"])
581
582     def test_addSucccess(self):
583         class Case(TestCase):
584             def test(this):
585                 this.addDetail("foo", self.get_content())
586         self.assertDetailsProvided(Case("test"), "addSuccess",
587             ["foo"])
588
589     def test_addUnexpectedSuccess(self):
590         class Case(TestCase):
591             def test(this):
592                 this.addDetail("foo", self.get_content())
593                 raise testcase._UnexpectedSuccess()
594         self.assertDetailsProvided(Case("test"), "addUnexpectedSuccess",
595             ["foo"])
596
597
598 class TestSetupTearDown(TestCase):
599
600     def test_setUpNotCalled(self):
601         class DoesnotcallsetUp(TestCase):
602             def setUp(self):
603                 pass
604             def test_method(self):
605                 pass
606         result = unittest.TestResult()
607         DoesnotcallsetUp('test_method').run(result)
608         self.assertEqual(1, len(result.errors))
609
610     def test_tearDownNotCalled(self):
611         class DoesnotcalltearDown(TestCase):
612             def test_method(self):
613                 pass
614             def tearDown(self):
615                 pass
616         result = unittest.TestResult()
617         DoesnotcalltearDown('test_method').run(result)
618         self.assertEqual(1, len(result.errors))
619
620
621 class TestSkipping(TestCase):
622     """Tests for skipping of tests functionality."""
623
624     def test_skip_causes_skipException(self):
625         self.assertRaises(self.skipException, self.skip, "Skip this test")
626
627     def test_skip_without_reason_works(self):
628         class Test(TestCase):
629             def test(self):
630                 raise self.skipException()
631         case = Test("test")
632         result = ExtendedTestResult()
633         case.run(result)
634         self.assertEqual('addSkip', result._events[1][0])
635         self.assertEqual('no reason given.',
636             ''.join(result._events[1][2]['reason'].iter_text()))
637
638     def test_skipException_in_setup_calls_result_addSkip(self):
639         class TestThatRaisesInSetUp(TestCase):
640             def setUp(self):
641                 TestCase.setUp(self)
642                 self.skip("skipping this test")
643             def test_that_passes(self):
644                 pass
645         calls = []
646         result = LoggingResult(calls)
647         test = TestThatRaisesInSetUp("test_that_passes")
648         test.run(result)
649         case = result._events[0][1]
650         self.assertEqual([('startTest', case),
651             ('addSkip', case, "Text attachment: reason\n------------\n"
652              "skipping this test\n------------\n"), ('stopTest', case)],
653             calls)
654
655     def test_skipException_in_test_method_calls_result_addSkip(self):
656         class SkippingTest(TestCase):
657             def test_that_raises_skipException(self):
658                 self.skip("skipping this test")
659         result = Python27TestResult()
660         test = SkippingTest("test_that_raises_skipException")
661         test.run(result)
662         case = result._events[0][1]
663         self.assertEqual([('startTest', case),
664             ('addSkip', case, "Text attachment: reason\n------------\n"
665              "skipping this test\n------------\n"), ('stopTest', case)],
666             result._events)
667
668     def test_skip__in_setup_with_old_result_object_calls_addSuccess(self):
669         class SkippingTest(TestCase):
670             def setUp(self):
671                 TestCase.setUp(self)
672                 raise self.skipException("skipping this test")
673             def test_that_raises_skipException(self):
674                 pass
675         result = Python26TestResult()
676         test = SkippingTest("test_that_raises_skipException")
677         test.run(result)
678         self.assertEqual('addSuccess', result._events[1][0])
679
680     def test_skip_with_old_result_object_calls_addError(self):
681         class SkippingTest(TestCase):
682             def test_that_raises_skipException(self):
683                 raise self.skipException("skipping this test")
684         result = Python26TestResult()
685         test = SkippingTest("test_that_raises_skipException")
686         test.run(result)
687         self.assertEqual('addSuccess', result._events[1][0])
688
689     def test_skip_decorator(self):
690         class SkippingTest(TestCase):
691             @skip("skipping this test")
692             def test_that_is_decorated_with_skip(self):
693                 self.fail()
694         result = Python26TestResult()
695         test = SkippingTest("test_that_is_decorated_with_skip")
696         test.run(result)
697         self.assertEqual('addSuccess', result._events[1][0])
698
699     def test_skipIf_decorator(self):
700         class SkippingTest(TestCase):
701             @skipIf(True, "skipping this test")
702             def test_that_is_decorated_with_skipIf(self):
703                 self.fail()
704         result = Python26TestResult()
705         test = SkippingTest("test_that_is_decorated_with_skipIf")
706         test.run(result)
707         self.assertEqual('addSuccess', result._events[1][0])
708
709     def test_skipUnless_decorator(self):
710         class SkippingTest(TestCase):
711             @skipUnless(False, "skipping this test")
712             def test_that_is_decorated_with_skipUnless(self):
713                 self.fail()
714         result = Python26TestResult()
715         test = SkippingTest("test_that_is_decorated_with_skipUnless")
716         test.run(result)
717         self.assertEqual('addSuccess', result._events[1][0])
718
719
720 class TestOnException(TestCase):
721
722     def test_default_works(self):
723         events = []
724         class Case(TestCase):
725             def method(self):
726                 self.onException(an_exc_info)
727                 events.append(True)
728         case = Case("method")
729         case.run()
730         self.assertThat(events, Equals([True]))
731
732     def test_added_handler_works(self):
733         events = []
734         class Case(TestCase):
735             def method(self):
736                 self.addOnException(events.append)
737                 self.onException(an_exc_info)
738         case = Case("method")
739         case.run()
740         self.assertThat(events, Equals([an_exc_info]))
741
742     def test_handler_that_raises_is_not_caught(self):
743         events = []
744         class Case(TestCase):
745             def method(self):
746                 self.addOnException(events.index)
747                 self.assertRaises(ValueError, self.onException, an_exc_info)
748         case = Case("method")
749         case.run()
750         self.assertThat(events, Equals([]))
751
752
753 def test_suite():
754     from unittest import TestLoader
755     return TestLoader().loadTestsFromName(__name__)