• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import io
2import os
3import sys
4import pickle
5import subprocess
6
7import unittest
8from unittest.case import _Outcome
9
10from unittest.test.support import (LoggingResult,
11                                   ResultWithNoStartTestRunStopTestRun)
12
13
14def resultFactory(*_):
15    return unittest.TestResult()
16
17
18def getRunner():
19    return unittest.TextTestRunner(resultclass=resultFactory,
20                                   stream=io.StringIO())
21
22
23def runTests(*cases):
24    suite = unittest.TestSuite()
25    for case in cases:
26        tests = unittest.defaultTestLoader.loadTestsFromTestCase(case)
27        suite.addTests(tests)
28
29    runner = getRunner()
30
31    # creating a nested suite exposes some potential bugs
32    realSuite = unittest.TestSuite()
33    realSuite.addTest(suite)
34    # adding empty suites to the end exposes potential bugs
35    suite.addTest(unittest.TestSuite())
36    realSuite.addTest(unittest.TestSuite())
37    return runner.run(realSuite)
38
39
40def cleanup(ordering, blowUp=False):
41    if not blowUp:
42        ordering.append('cleanup_good')
43    else:
44        ordering.append('cleanup_exc')
45        raise Exception('CleanUpExc')
46
47
48class TestCleanUp(unittest.TestCase):
49    def testCleanUp(self):
50        class TestableTest(unittest.TestCase):
51            def testNothing(self):
52                pass
53
54        test = TestableTest('testNothing')
55        self.assertEqual(test._cleanups, [])
56
57        cleanups = []
58
59        def cleanup1(*args, **kwargs):
60            cleanups.append((1, args, kwargs))
61
62        def cleanup2(*args, **kwargs):
63            cleanups.append((2, args, kwargs))
64
65        test.addCleanup(cleanup1, 1, 2, 3, four='hello', five='goodbye')
66        test.addCleanup(cleanup2)
67
68        self.assertEqual(test._cleanups,
69                         [(cleanup1, (1, 2, 3), dict(four='hello', five='goodbye')),
70                          (cleanup2, (), {})])
71
72        self.assertTrue(test.doCleanups())
73        self.assertEqual(cleanups, [(2, (), {}), (1, (1, 2, 3), dict(four='hello', five='goodbye'))])
74
75    def testCleanUpWithErrors(self):
76        class TestableTest(unittest.TestCase):
77            def testNothing(self):
78                pass
79
80        test = TestableTest('testNothing')
81        outcome = test._outcome = _Outcome()
82
83        CleanUpExc = Exception('foo')
84        exc2 = Exception('bar')
85        def cleanup1():
86            raise CleanUpExc
87
88        def cleanup2():
89            raise exc2
90
91        test.addCleanup(cleanup1)
92        test.addCleanup(cleanup2)
93
94        self.assertFalse(test.doCleanups())
95        self.assertFalse(outcome.success)
96
97        ((_, (Type1, instance1, _)),
98         (_, (Type2, instance2, _))) = reversed(outcome.errors)
99        self.assertEqual((Type1, instance1), (Exception, CleanUpExc))
100        self.assertEqual((Type2, instance2), (Exception, exc2))
101
102    def testCleanupInRun(self):
103        blowUp = False
104        ordering = []
105
106        class TestableTest(unittest.TestCase):
107            def setUp(self):
108                ordering.append('setUp')
109                if blowUp:
110                    raise Exception('foo')
111
112            def testNothing(self):
113                ordering.append('test')
114
115            def tearDown(self):
116                ordering.append('tearDown')
117
118        test = TestableTest('testNothing')
119
120        def cleanup1():
121            ordering.append('cleanup1')
122        def cleanup2():
123            ordering.append('cleanup2')
124        test.addCleanup(cleanup1)
125        test.addCleanup(cleanup2)
126
127        def success(some_test):
128            self.assertEqual(some_test, test)
129            ordering.append('success')
130
131        result = unittest.TestResult()
132        result.addSuccess = success
133
134        test.run(result)
135        self.assertEqual(ordering, ['setUp', 'test', 'tearDown',
136                                    'cleanup2', 'cleanup1', 'success'])
137
138        blowUp = True
139        ordering = []
140        test = TestableTest('testNothing')
141        test.addCleanup(cleanup1)
142        test.run(result)
143        self.assertEqual(ordering, ['setUp', 'cleanup1'])
144
145    def testTestCaseDebugExecutesCleanups(self):
146        ordering = []
147
148        class TestableTest(unittest.TestCase):
149            def setUp(self):
150                ordering.append('setUp')
151                self.addCleanup(cleanup1)
152
153            def testNothing(self):
154                ordering.append('test')
155
156            def tearDown(self):
157                ordering.append('tearDown')
158
159        test = TestableTest('testNothing')
160
161        def cleanup1():
162            ordering.append('cleanup1')
163            test.addCleanup(cleanup2)
164        def cleanup2():
165            ordering.append('cleanup2')
166
167        test.debug()
168        self.assertEqual(ordering, ['setUp', 'test', 'tearDown', 'cleanup1', 'cleanup2'])
169
170
171class TestClassCleanup(unittest.TestCase):
172    def test_addClassCleanUp(self):
173        class TestableTest(unittest.TestCase):
174            def testNothing(self):
175                pass
176        test = TestableTest('testNothing')
177        self.assertEqual(test._class_cleanups, [])
178        class_cleanups = []
179
180        def class_cleanup1(*args, **kwargs):
181            class_cleanups.append((3, args, kwargs))
182
183        def class_cleanup2(*args, **kwargs):
184            class_cleanups.append((4, args, kwargs))
185
186        TestableTest.addClassCleanup(class_cleanup1, 1, 2, 3,
187                                     four='hello', five='goodbye')
188        TestableTest.addClassCleanup(class_cleanup2)
189
190        self.assertEqual(test._class_cleanups,
191                         [(class_cleanup1, (1, 2, 3),
192                           dict(four='hello', five='goodbye')),
193                          (class_cleanup2, (), {})])
194
195        TestableTest.doClassCleanups()
196        self.assertEqual(class_cleanups, [(4, (), {}), (3, (1, 2, 3),
197                                          dict(four='hello', five='goodbye'))])
198
199    def test_run_class_cleanUp(self):
200        ordering = []
201        blowUp = True
202
203        class TestableTest(unittest.TestCase):
204            @classmethod
205            def setUpClass(cls):
206                ordering.append('setUpClass')
207                cls.addClassCleanup(cleanup, ordering)
208                if blowUp:
209                    raise Exception()
210            def testNothing(self):
211                ordering.append('test')
212            @classmethod
213            def tearDownClass(cls):
214                ordering.append('tearDownClass')
215
216        runTests(TestableTest)
217        self.assertEqual(ordering, ['setUpClass', 'cleanup_good'])
218
219        ordering = []
220        blowUp = False
221        runTests(TestableTest)
222        self.assertEqual(ordering,
223                         ['setUpClass', 'test', 'tearDownClass', 'cleanup_good'])
224
225    def test_run_class_cleanUp_without_tearDownClass(self):
226        ordering = []
227        blowUp = True
228
229        class TestableTest(unittest.TestCase):
230            @classmethod
231            def setUpClass(cls):
232                ordering.append('setUpClass')
233                cls.addClassCleanup(cleanup, ordering)
234                if blowUp:
235                    raise Exception()
236            def testNothing(self):
237                ordering.append('test')
238            @classmethod
239            @property
240            def tearDownClass(cls):
241                raise AttributeError
242
243        runTests(TestableTest)
244        self.assertEqual(ordering, ['setUpClass', 'cleanup_good'])
245
246        ordering = []
247        blowUp = False
248        runTests(TestableTest)
249        self.assertEqual(ordering,
250                         ['setUpClass', 'test', 'cleanup_good'])
251
252    def test_debug_executes_classCleanUp(self):
253        ordering = []
254        blowUp = False
255
256        class TestableTest(unittest.TestCase):
257            @classmethod
258            def setUpClass(cls):
259                ordering.append('setUpClass')
260                cls.addClassCleanup(cleanup, ordering, blowUp=blowUp)
261            def testNothing(self):
262                ordering.append('test')
263            @classmethod
264            def tearDownClass(cls):
265                ordering.append('tearDownClass')
266
267        suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest)
268        suite.debug()
269        self.assertEqual(ordering,
270                         ['setUpClass', 'test', 'tearDownClass', 'cleanup_good'])
271
272        ordering = []
273        blowUp = True
274        suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest)
275        with self.assertRaises(Exception) as cm:
276            suite.debug()
277        self.assertEqual(str(cm.exception), 'CleanUpExc')
278        self.assertEqual(ordering,
279                         ['setUpClass', 'test', 'tearDownClass', 'cleanup_exc'])
280
281    def test_debug_executes_classCleanUp_when_teardown_exception(self):
282        ordering = []
283        blowUp = False
284
285        class TestableTest(unittest.TestCase):
286            @classmethod
287            def setUpClass(cls):
288                ordering.append('setUpClass')
289                cls.addClassCleanup(cleanup, ordering, blowUp=blowUp)
290            def testNothing(self):
291                ordering.append('test')
292            @classmethod
293            def tearDownClass(cls):
294                raise Exception('TearDownClassExc')
295
296        suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest)
297        with self.assertRaises(Exception) as cm:
298            suite.debug()
299        self.assertEqual(str(cm.exception), 'TearDownClassExc')
300        self.assertEqual(ordering, ['setUpClass', 'test'])
301        self.assertTrue(TestableTest._class_cleanups)
302        TestableTest._class_cleanups.clear()
303
304        ordering = []
305        blowUp = True
306        suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest)
307        with self.assertRaises(Exception) as cm:
308            suite.debug()
309        self.assertEqual(str(cm.exception), 'TearDownClassExc')
310        self.assertEqual(ordering, ['setUpClass', 'test'])
311        self.assertTrue(TestableTest._class_cleanups)
312        TestableTest._class_cleanups.clear()
313
314    def test_doClassCleanups_with_errors_addClassCleanUp(self):
315        class TestableTest(unittest.TestCase):
316            def testNothing(self):
317                pass
318
319        def cleanup1():
320            raise Exception('cleanup1')
321
322        def cleanup2():
323            raise Exception('cleanup2')
324
325        TestableTest.addClassCleanup(cleanup1)
326        TestableTest.addClassCleanup(cleanup2)
327        with self.assertRaises(Exception) as e:
328            TestableTest.doClassCleanups()
329            self.assertEqual(e, 'cleanup1')
330
331    def test_with_errors_addCleanUp(self):
332        ordering = []
333        class TestableTest(unittest.TestCase):
334            @classmethod
335            def setUpClass(cls):
336                ordering.append('setUpClass')
337                cls.addClassCleanup(cleanup, ordering)
338            def setUp(self):
339                ordering.append('setUp')
340                self.addCleanup(cleanup, ordering, blowUp=True)
341            def testNothing(self):
342                pass
343            @classmethod
344            def tearDownClass(cls):
345                ordering.append('tearDownClass')
346
347        result = runTests(TestableTest)
348        self.assertEqual(result.errors[0][1].splitlines()[-1],
349                         'Exception: CleanUpExc')
350        self.assertEqual(ordering,
351                         ['setUpClass', 'setUp', 'cleanup_exc',
352                          'tearDownClass', 'cleanup_good'])
353
354    def test_run_with_errors_addClassCleanUp(self):
355        ordering = []
356        class TestableTest(unittest.TestCase):
357            @classmethod
358            def setUpClass(cls):
359                ordering.append('setUpClass')
360                cls.addClassCleanup(cleanup, ordering, blowUp=True)
361            def setUp(self):
362                ordering.append('setUp')
363                self.addCleanup(cleanup, ordering)
364            def testNothing(self):
365                ordering.append('test')
366            @classmethod
367            def tearDownClass(cls):
368                ordering.append('tearDownClass')
369
370        result = runTests(TestableTest)
371        self.assertEqual(result.errors[0][1].splitlines()[-1],
372                         'Exception: CleanUpExc')
373        self.assertEqual(ordering,
374                         ['setUpClass', 'setUp', 'test', 'cleanup_good',
375                          'tearDownClass', 'cleanup_exc'])
376
377    def test_with_errors_in_addClassCleanup_and_setUps(self):
378        ordering = []
379        class_blow_up = False
380        method_blow_up = False
381
382        class TestableTest(unittest.TestCase):
383            @classmethod
384            def setUpClass(cls):
385                ordering.append('setUpClass')
386                cls.addClassCleanup(cleanup, ordering, blowUp=True)
387                if class_blow_up:
388                    raise Exception('ClassExc')
389            def setUp(self):
390                ordering.append('setUp')
391                if method_blow_up:
392                    raise Exception('MethodExc')
393            def testNothing(self):
394                ordering.append('test')
395            @classmethod
396            def tearDownClass(cls):
397                ordering.append('tearDownClass')
398
399        result = runTests(TestableTest)
400        self.assertEqual(result.errors[0][1].splitlines()[-1],
401                         'Exception: CleanUpExc')
402        self.assertEqual(ordering,
403                         ['setUpClass', 'setUp', 'test',
404                          'tearDownClass', 'cleanup_exc'])
405
406        ordering = []
407        class_blow_up = True
408        method_blow_up = False
409        result = runTests(TestableTest)
410        self.assertEqual(result.errors[0][1].splitlines()[-1],
411                         'Exception: ClassExc')
412        self.assertEqual(result.errors[1][1].splitlines()[-1],
413                         'Exception: CleanUpExc')
414        self.assertEqual(ordering,
415                         ['setUpClass', 'cleanup_exc'])
416
417        ordering = []
418        class_blow_up = False
419        method_blow_up = True
420        result = runTests(TestableTest)
421        self.assertEqual(result.errors[0][1].splitlines()[-1],
422                         'Exception: MethodExc')
423        self.assertEqual(result.errors[1][1].splitlines()[-1],
424                         'Exception: CleanUpExc')
425        self.assertEqual(ordering,
426                         ['setUpClass', 'setUp', 'tearDownClass',
427                          'cleanup_exc'])
428
429    def test_with_errors_in_tearDownClass(self):
430        ordering = []
431        class TestableTest(unittest.TestCase):
432            @classmethod
433            def setUpClass(cls):
434                ordering.append('setUpClass')
435                cls.addClassCleanup(cleanup, ordering)
436            def testNothing(self):
437                ordering.append('test')
438            @classmethod
439            def tearDownClass(cls):
440                ordering.append('tearDownClass')
441                raise Exception('TearDownExc')
442
443        result = runTests(TestableTest)
444        self.assertEqual(result.errors[0][1].splitlines()[-1],
445                         'Exception: TearDownExc')
446        self.assertEqual(ordering,
447                         ['setUpClass', 'test', 'tearDownClass', 'cleanup_good'])
448
449
450class TestModuleCleanUp(unittest.TestCase):
451    def test_add_and_do_ModuleCleanup(self):
452        module_cleanups = []
453
454        def module_cleanup1(*args, **kwargs):
455            module_cleanups.append((3, args, kwargs))
456
457        def module_cleanup2(*args, **kwargs):
458            module_cleanups.append((4, args, kwargs))
459
460        class Module(object):
461            unittest.addModuleCleanup(module_cleanup1, 1, 2, 3,
462                                      four='hello', five='goodbye')
463            unittest.addModuleCleanup(module_cleanup2)
464
465        self.assertEqual(unittest.case._module_cleanups,
466                         [(module_cleanup1, (1, 2, 3),
467                           dict(four='hello', five='goodbye')),
468                          (module_cleanup2, (), {})])
469
470        unittest.case.doModuleCleanups()
471        self.assertEqual(module_cleanups, [(4, (), {}), (3, (1, 2, 3),
472                                          dict(four='hello', five='goodbye'))])
473        self.assertEqual(unittest.case._module_cleanups, [])
474
475    def test_doModuleCleanup_with_errors_in_addModuleCleanup(self):
476        module_cleanups = []
477
478        def module_cleanup_good(*args, **kwargs):
479            module_cleanups.append((3, args, kwargs))
480
481        def module_cleanup_bad(*args, **kwargs):
482            raise Exception('CleanUpExc')
483
484        class Module(object):
485            unittest.addModuleCleanup(module_cleanup_good, 1, 2, 3,
486                                      four='hello', five='goodbye')
487            unittest.addModuleCleanup(module_cleanup_bad)
488        self.assertEqual(unittest.case._module_cleanups,
489                         [(module_cleanup_good, (1, 2, 3),
490                           dict(four='hello', five='goodbye')),
491                          (module_cleanup_bad, (), {})])
492        with self.assertRaises(Exception) as e:
493            unittest.case.doModuleCleanups()
494        self.assertEqual(str(e.exception), 'CleanUpExc')
495        self.assertEqual(unittest.case._module_cleanups, [])
496
497    def test_addModuleCleanup_arg_errors(self):
498        cleanups = []
499        def cleanup(*args, **kwargs):
500            cleanups.append((args, kwargs))
501
502        class Module(object):
503            unittest.addModuleCleanup(cleanup, 1, 2, function='hello')
504            with self.assertRaises(TypeError):
505                unittest.addModuleCleanup(function=cleanup, arg='hello')
506            with self.assertRaises(TypeError):
507                unittest.addModuleCleanup()
508        unittest.case.doModuleCleanups()
509        self.assertEqual(cleanups,
510                         [((1, 2), {'function': 'hello'})])
511
512    def test_run_module_cleanUp(self):
513        blowUp = True
514        ordering = []
515        class Module(object):
516            @staticmethod
517            def setUpModule():
518                ordering.append('setUpModule')
519                unittest.addModuleCleanup(cleanup, ordering)
520                if blowUp:
521                    raise Exception('setUpModule Exc')
522            @staticmethod
523            def tearDownModule():
524                ordering.append('tearDownModule')
525
526        class TestableTest(unittest.TestCase):
527            @classmethod
528            def setUpClass(cls):
529                ordering.append('setUpClass')
530            def testNothing(self):
531                ordering.append('test')
532            @classmethod
533            def tearDownClass(cls):
534                ordering.append('tearDownClass')
535
536        TestableTest.__module__ = 'Module'
537        sys.modules['Module'] = Module
538        result = runTests(TestableTest)
539        self.assertEqual(ordering, ['setUpModule', 'cleanup_good'])
540        self.assertEqual(result.errors[0][1].splitlines()[-1],
541                         'Exception: setUpModule Exc')
542
543        ordering = []
544        blowUp = False
545        runTests(TestableTest)
546        self.assertEqual(ordering,
547                         ['setUpModule', 'setUpClass', 'test', 'tearDownClass',
548                          'tearDownModule', 'cleanup_good'])
549        self.assertEqual(unittest.case._module_cleanups, [])
550
551    def test_run_multiple_module_cleanUp(self):
552        blowUp = True
553        blowUp2 = False
554        ordering = []
555        class Module1(object):
556            @staticmethod
557            def setUpModule():
558                ordering.append('setUpModule')
559                unittest.addModuleCleanup(cleanup, ordering)
560                if blowUp:
561                    raise Exception()
562            @staticmethod
563            def tearDownModule():
564                ordering.append('tearDownModule')
565
566        class Module2(object):
567            @staticmethod
568            def setUpModule():
569                ordering.append('setUpModule2')
570                unittest.addModuleCleanup(cleanup, ordering)
571                if blowUp2:
572                    raise Exception()
573            @staticmethod
574            def tearDownModule():
575                ordering.append('tearDownModule2')
576
577        class TestableTest(unittest.TestCase):
578            @classmethod
579            def setUpClass(cls):
580                ordering.append('setUpClass')
581            def testNothing(self):
582                ordering.append('test')
583            @classmethod
584            def tearDownClass(cls):
585                ordering.append('tearDownClass')
586
587        class TestableTest2(unittest.TestCase):
588            @classmethod
589            def setUpClass(cls):
590                ordering.append('setUpClass2')
591            def testNothing(self):
592                ordering.append('test2')
593            @classmethod
594            def tearDownClass(cls):
595                ordering.append('tearDownClass2')
596
597        TestableTest.__module__ = 'Module1'
598        sys.modules['Module1'] = Module1
599        TestableTest2.__module__ = 'Module2'
600        sys.modules['Module2'] = Module2
601        runTests(TestableTest, TestableTest2)
602        self.assertEqual(ordering, ['setUpModule', 'cleanup_good',
603                                    'setUpModule2', 'setUpClass2', 'test2',
604                                    'tearDownClass2', 'tearDownModule2',
605                                    'cleanup_good'])
606        ordering = []
607        blowUp = False
608        blowUp2 = True
609        runTests(TestableTest, TestableTest2)
610        self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test',
611                                    'tearDownClass', 'tearDownModule',
612                                    'cleanup_good', 'setUpModule2',
613                                    'cleanup_good'])
614
615        ordering = []
616        blowUp = False
617        blowUp2 = False
618        runTests(TestableTest, TestableTest2)
619        self.assertEqual(ordering,
620                         ['setUpModule', 'setUpClass', 'test', 'tearDownClass',
621                          'tearDownModule', 'cleanup_good', 'setUpModule2',
622                          'setUpClass2', 'test2', 'tearDownClass2',
623                          'tearDownModule2', 'cleanup_good'])
624        self.assertEqual(unittest.case._module_cleanups, [])
625
626    def test_run_module_cleanUp_without_teardown(self):
627        ordering = []
628        class Module(object):
629            @staticmethod
630            def setUpModule():
631                ordering.append('setUpModule')
632                unittest.addModuleCleanup(cleanup, ordering)
633
634        class TestableTest(unittest.TestCase):
635            @classmethod
636            def setUpClass(cls):
637                ordering.append('setUpClass')
638            def testNothing(self):
639                ordering.append('test')
640            @classmethod
641            def tearDownClass(cls):
642                ordering.append('tearDownClass')
643
644        TestableTest.__module__ = 'Module'
645        sys.modules['Module'] = Module
646        runTests(TestableTest)
647        self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test',
648                                    'tearDownClass', 'cleanup_good'])
649        self.assertEqual(unittest.case._module_cleanups, [])
650
651    def test_run_module_cleanUp_when_teardown_exception(self):
652        ordering = []
653        class Module(object):
654            @staticmethod
655            def setUpModule():
656                ordering.append('setUpModule')
657                unittest.addModuleCleanup(cleanup, ordering)
658            @staticmethod
659            def tearDownModule():
660                raise Exception('CleanUpExc')
661
662        class TestableTest(unittest.TestCase):
663            @classmethod
664            def setUpClass(cls):
665                ordering.append('setUpClass')
666            def testNothing(self):
667                ordering.append('test')
668            @classmethod
669            def tearDownClass(cls):
670                ordering.append('tearDownClass')
671
672        TestableTest.__module__ = 'Module'
673        sys.modules['Module'] = Module
674        result = runTests(TestableTest)
675        self.assertEqual(result.errors[0][1].splitlines()[-1],
676                         'Exception: CleanUpExc')
677        self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test',
678                                    'tearDownClass', 'cleanup_good'])
679        self.assertEqual(unittest.case._module_cleanups, [])
680
681    def test_debug_module_executes_cleanUp(self):
682        ordering = []
683        blowUp = False
684        class Module(object):
685            @staticmethod
686            def setUpModule():
687                ordering.append('setUpModule')
688                unittest.addModuleCleanup(cleanup, ordering, blowUp=blowUp)
689            @staticmethod
690            def tearDownModule():
691                ordering.append('tearDownModule')
692
693        class TestableTest(unittest.TestCase):
694            @classmethod
695            def setUpClass(cls):
696                ordering.append('setUpClass')
697            def testNothing(self):
698                ordering.append('test')
699            @classmethod
700            def tearDownClass(cls):
701                ordering.append('tearDownClass')
702
703        TestableTest.__module__ = 'Module'
704        sys.modules['Module'] = Module
705        suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest)
706        suite.debug()
707        self.assertEqual(ordering,
708                         ['setUpModule', 'setUpClass', 'test', 'tearDownClass',
709                          'tearDownModule', 'cleanup_good'])
710        self.assertEqual(unittest.case._module_cleanups, [])
711
712        ordering = []
713        blowUp = True
714        suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest)
715        with self.assertRaises(Exception) as cm:
716            suite.debug()
717        self.assertEqual(str(cm.exception), 'CleanUpExc')
718        self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test',
719                                    'tearDownClass', 'tearDownModule', 'cleanup_exc'])
720        self.assertEqual(unittest.case._module_cleanups, [])
721
722    def test_debug_module_cleanUp_when_teardown_exception(self):
723        ordering = []
724        blowUp = False
725        class Module(object):
726            @staticmethod
727            def setUpModule():
728                ordering.append('setUpModule')
729                unittest.addModuleCleanup(cleanup, ordering, blowUp=blowUp)
730            @staticmethod
731            def tearDownModule():
732                raise Exception('TearDownModuleExc')
733
734        class TestableTest(unittest.TestCase):
735            @classmethod
736            def setUpClass(cls):
737                ordering.append('setUpClass')
738            def testNothing(self):
739                ordering.append('test')
740            @classmethod
741            def tearDownClass(cls):
742                ordering.append('tearDownClass')
743
744        TestableTest.__module__ = 'Module'
745        sys.modules['Module'] = Module
746        suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest)
747        with self.assertRaises(Exception) as cm:
748            suite.debug()
749        self.assertEqual(str(cm.exception), 'TearDownModuleExc')
750        self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test',
751                                    'tearDownClass'])
752        self.assertTrue(unittest.case._module_cleanups)
753        unittest.case._module_cleanups.clear()
754
755        ordering = []
756        blowUp = True
757        suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest)
758        with self.assertRaises(Exception) as cm:
759            suite.debug()
760        self.assertEqual(str(cm.exception), 'TearDownModuleExc')
761        self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test',
762                                    'tearDownClass'])
763        self.assertTrue(unittest.case._module_cleanups)
764        unittest.case._module_cleanups.clear()
765
766    def test_addClassCleanup_arg_errors(self):
767        cleanups = []
768        def cleanup(*args, **kwargs):
769            cleanups.append((args, kwargs))
770
771        class TestableTest(unittest.TestCase):
772            @classmethod
773            def setUpClass(cls):
774                cls.addClassCleanup(cleanup, 1, 2, function=3, cls=4)
775                with self.assertRaises(TypeError):
776                    cls.addClassCleanup(function=cleanup, arg='hello')
777            def testNothing(self):
778                pass
779
780        with self.assertRaises(TypeError):
781            TestableTest.addClassCleanup()
782        with self.assertRaises(TypeError):
783            unittest.TestCase.addCleanup(cls=TestableTest(), function=cleanup)
784        runTests(TestableTest)
785        self.assertEqual(cleanups,
786                         [((1, 2), {'function': 3, 'cls': 4})])
787
788    def test_addCleanup_arg_errors(self):
789        cleanups = []
790        def cleanup(*args, **kwargs):
791            cleanups.append((args, kwargs))
792
793        class TestableTest(unittest.TestCase):
794            def setUp(self2):
795                self2.addCleanup(cleanup, 1, 2, function=3, self=4)
796                with self.assertRaises(TypeError):
797                    self2.addCleanup(function=cleanup, arg='hello')
798            def testNothing(self):
799                pass
800
801        with self.assertRaises(TypeError):
802            TestableTest().addCleanup()
803        with self.assertRaises(TypeError):
804            unittest.TestCase.addCleanup(self=TestableTest(), function=cleanup)
805        runTests(TestableTest)
806        self.assertEqual(cleanups,
807                         [((1, 2), {'function': 3, 'self': 4})])
808
809    def test_with_errors_in_addClassCleanup(self):
810        ordering = []
811
812        class Module(object):
813            @staticmethod
814            def setUpModule():
815                ordering.append('setUpModule')
816                unittest.addModuleCleanup(cleanup, ordering)
817            @staticmethod
818            def tearDownModule():
819                ordering.append('tearDownModule')
820
821        class TestableTest(unittest.TestCase):
822            @classmethod
823            def setUpClass(cls):
824                ordering.append('setUpClass')
825                cls.addClassCleanup(cleanup, ordering, blowUp=True)
826            def testNothing(self):
827                ordering.append('test')
828            @classmethod
829            def tearDownClass(cls):
830                ordering.append('tearDownClass')
831
832        TestableTest.__module__ = 'Module'
833        sys.modules['Module'] = Module
834
835        result = runTests(TestableTest)
836        self.assertEqual(result.errors[0][1].splitlines()[-1],
837                         'Exception: CleanUpExc')
838        self.assertEqual(ordering,
839                         ['setUpModule', 'setUpClass', 'test', 'tearDownClass',
840                          'cleanup_exc', 'tearDownModule', 'cleanup_good'])
841
842    def test_with_errors_in_addCleanup(self):
843        ordering = []
844        class Module(object):
845            @staticmethod
846            def setUpModule():
847                ordering.append('setUpModule')
848                unittest.addModuleCleanup(cleanup, ordering)
849            @staticmethod
850            def tearDownModule():
851                ordering.append('tearDownModule')
852
853        class TestableTest(unittest.TestCase):
854            def setUp(self):
855                ordering.append('setUp')
856                self.addCleanup(cleanup, ordering, blowUp=True)
857            def testNothing(self):
858                ordering.append('test')
859            def tearDown(self):
860                ordering.append('tearDown')
861
862        TestableTest.__module__ = 'Module'
863        sys.modules['Module'] = Module
864
865        result = runTests(TestableTest)
866        self.assertEqual(result.errors[0][1].splitlines()[-1],
867                         'Exception: CleanUpExc')
868        self.assertEqual(ordering,
869                         ['setUpModule', 'setUp', 'test', 'tearDown',
870                          'cleanup_exc', 'tearDownModule', 'cleanup_good'])
871
872    def test_with_errors_in_addModuleCleanup_and_setUps(self):
873        ordering = []
874        module_blow_up = False
875        class_blow_up = False
876        method_blow_up = False
877        class Module(object):
878            @staticmethod
879            def setUpModule():
880                ordering.append('setUpModule')
881                unittest.addModuleCleanup(cleanup, ordering, blowUp=True)
882                if module_blow_up:
883                    raise Exception('ModuleExc')
884            @staticmethod
885            def tearDownModule():
886                ordering.append('tearDownModule')
887
888        class TestableTest(unittest.TestCase):
889            @classmethod
890            def setUpClass(cls):
891                ordering.append('setUpClass')
892                if class_blow_up:
893                    raise Exception('ClassExc')
894            def setUp(self):
895                ordering.append('setUp')
896                if method_blow_up:
897                    raise Exception('MethodExc')
898            def testNothing(self):
899                ordering.append('test')
900            @classmethod
901            def tearDownClass(cls):
902                ordering.append('tearDownClass')
903
904        TestableTest.__module__ = 'Module'
905        sys.modules['Module'] = Module
906
907        result = runTests(TestableTest)
908        self.assertEqual(result.errors[0][1].splitlines()[-1],
909                         'Exception: CleanUpExc')
910        self.assertEqual(ordering,
911                         ['setUpModule', 'setUpClass', 'setUp', 'test',
912                          'tearDownClass', 'tearDownModule',
913                          'cleanup_exc'])
914
915        ordering = []
916        module_blow_up = True
917        class_blow_up = False
918        method_blow_up = False
919        result = runTests(TestableTest)
920        self.assertEqual(result.errors[0][1].splitlines()[-1],
921                         'Exception: ModuleExc')
922        self.assertEqual(result.errors[1][1].splitlines()[-1],
923                         'Exception: CleanUpExc')
924        self.assertEqual(ordering, ['setUpModule', 'cleanup_exc'])
925
926        ordering = []
927        module_blow_up = False
928        class_blow_up = True
929        method_blow_up = False
930        result = runTests(TestableTest)
931        self.assertEqual(result.errors[0][1].splitlines()[-1],
932                         'Exception: ClassExc')
933        self.assertEqual(result.errors[1][1].splitlines()[-1],
934                         'Exception: CleanUpExc')
935        self.assertEqual(ordering, ['setUpModule', 'setUpClass',
936                                    'tearDownModule', 'cleanup_exc'])
937
938        ordering = []
939        module_blow_up = False
940        class_blow_up = False
941        method_blow_up = True
942        result = runTests(TestableTest)
943        self.assertEqual(result.errors[0][1].splitlines()[-1],
944                         'Exception: MethodExc')
945        self.assertEqual(result.errors[1][1].splitlines()[-1],
946                         'Exception: CleanUpExc')
947        self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'setUp',
948                                    'tearDownClass', 'tearDownModule',
949                                    'cleanup_exc'])
950
951    def test_module_cleanUp_with_multiple_classes(self):
952        ordering =[]
953        def cleanup1():
954            ordering.append('cleanup1')
955
956        def cleanup2():
957            ordering.append('cleanup2')
958
959        def cleanup3():
960            ordering.append('cleanup3')
961
962        class Module(object):
963            @staticmethod
964            def setUpModule():
965                ordering.append('setUpModule')
966                unittest.addModuleCleanup(cleanup1)
967            @staticmethod
968            def tearDownModule():
969                ordering.append('tearDownModule')
970
971        class TestableTest(unittest.TestCase):
972            def setUp(self):
973                ordering.append('setUp')
974                self.addCleanup(cleanup2)
975            def testNothing(self):
976                ordering.append('test')
977            def tearDown(self):
978                ordering.append('tearDown')
979
980        class OtherTestableTest(unittest.TestCase):
981            def setUp(self):
982                ordering.append('setUp2')
983                self.addCleanup(cleanup3)
984            def testNothing(self):
985                ordering.append('test2')
986            def tearDown(self):
987                ordering.append('tearDown2')
988
989        TestableTest.__module__ = 'Module'
990        OtherTestableTest.__module__ = 'Module'
991        sys.modules['Module'] = Module
992        runTests(TestableTest, OtherTestableTest)
993        self.assertEqual(ordering,
994                         ['setUpModule', 'setUp', 'test', 'tearDown',
995                          'cleanup2',  'setUp2', 'test2', 'tearDown2',
996                          'cleanup3', 'tearDownModule', 'cleanup1'])
997
998
999class Test_TextTestRunner(unittest.TestCase):
1000    """Tests for TextTestRunner."""
1001
1002    def setUp(self):
1003        # clean the environment from pre-existing PYTHONWARNINGS to make
1004        # test_warnings results consistent
1005        self.pythonwarnings = os.environ.get('PYTHONWARNINGS')
1006        if self.pythonwarnings:
1007            del os.environ['PYTHONWARNINGS']
1008
1009    def tearDown(self):
1010        # bring back pre-existing PYTHONWARNINGS if present
1011        if self.pythonwarnings:
1012            os.environ['PYTHONWARNINGS'] = self.pythonwarnings
1013
1014    def test_init(self):
1015        runner = unittest.TextTestRunner()
1016        self.assertFalse(runner.failfast)
1017        self.assertFalse(runner.buffer)
1018        self.assertEqual(runner.verbosity, 1)
1019        self.assertEqual(runner.warnings, None)
1020        self.assertTrue(runner.descriptions)
1021        self.assertEqual(runner.resultclass, unittest.TextTestResult)
1022        self.assertFalse(runner.tb_locals)
1023
1024    def test_multiple_inheritance(self):
1025        class AResult(unittest.TestResult):
1026            def __init__(self, stream, descriptions, verbosity):
1027                super(AResult, self).__init__(stream, descriptions, verbosity)
1028
1029        class ATextResult(unittest.TextTestResult, AResult):
1030            pass
1031
1032        # This used to raise an exception due to TextTestResult not passing
1033        # on arguments in its __init__ super call
1034        ATextResult(None, None, 1)
1035
1036    def testBufferAndFailfast(self):
1037        class Test(unittest.TestCase):
1038            def testFoo(self):
1039                pass
1040        result = unittest.TestResult()
1041        runner = unittest.TextTestRunner(stream=io.StringIO(), failfast=True,
1042                                         buffer=True)
1043        # Use our result object
1044        runner._makeResult = lambda: result
1045        runner.run(Test('testFoo'))
1046
1047        self.assertTrue(result.failfast)
1048        self.assertTrue(result.buffer)
1049
1050    def test_locals(self):
1051        runner = unittest.TextTestRunner(stream=io.StringIO(), tb_locals=True)
1052        result = runner.run(unittest.TestSuite())
1053        self.assertEqual(True, result.tb_locals)
1054
1055    def testRunnerRegistersResult(self):
1056        class Test(unittest.TestCase):
1057            def testFoo(self):
1058                pass
1059        originalRegisterResult = unittest.runner.registerResult
1060        def cleanup():
1061            unittest.runner.registerResult = originalRegisterResult
1062        self.addCleanup(cleanup)
1063
1064        result = unittest.TestResult()
1065        runner = unittest.TextTestRunner(stream=io.StringIO())
1066        # Use our result object
1067        runner._makeResult = lambda: result
1068
1069        self.wasRegistered = 0
1070        def fakeRegisterResult(thisResult):
1071            self.wasRegistered += 1
1072            self.assertEqual(thisResult, result)
1073        unittest.runner.registerResult = fakeRegisterResult
1074
1075        runner.run(unittest.TestSuite())
1076        self.assertEqual(self.wasRegistered, 1)
1077
1078    def test_works_with_result_without_startTestRun_stopTestRun(self):
1079        class OldTextResult(ResultWithNoStartTestRunStopTestRun):
1080            separator2 = ''
1081            def printErrors(self):
1082                pass
1083
1084        class Runner(unittest.TextTestRunner):
1085            def __init__(self):
1086                super(Runner, self).__init__(io.StringIO())
1087
1088            def _makeResult(self):
1089                return OldTextResult()
1090
1091        runner = Runner()
1092        runner.run(unittest.TestSuite())
1093
1094    def test_startTestRun_stopTestRun_called(self):
1095        class LoggingTextResult(LoggingResult):
1096            separator2 = ''
1097            def printErrors(self):
1098                pass
1099
1100        class LoggingRunner(unittest.TextTestRunner):
1101            def __init__(self, events):
1102                super(LoggingRunner, self).__init__(io.StringIO())
1103                self._events = events
1104
1105            def _makeResult(self):
1106                return LoggingTextResult(self._events)
1107
1108        events = []
1109        runner = LoggingRunner(events)
1110        runner.run(unittest.TestSuite())
1111        expected = ['startTestRun', 'stopTestRun']
1112        self.assertEqual(events, expected)
1113
1114    def test_pickle_unpickle(self):
1115        # Issue #7197: a TextTestRunner should be (un)pickleable. This is
1116        # required by test_multiprocessing under Windows (in verbose mode).
1117        stream = io.StringIO("foo")
1118        runner = unittest.TextTestRunner(stream)
1119        for protocol in range(2, pickle.HIGHEST_PROTOCOL + 1):
1120            s = pickle.dumps(runner, protocol)
1121            obj = pickle.loads(s)
1122            # StringIO objects never compare equal, a cheap test instead.
1123            self.assertEqual(obj.stream.getvalue(), stream.getvalue())
1124
1125    def test_resultclass(self):
1126        def MockResultClass(*args):
1127            return args
1128        STREAM = object()
1129        DESCRIPTIONS = object()
1130        VERBOSITY = object()
1131        runner = unittest.TextTestRunner(STREAM, DESCRIPTIONS, VERBOSITY,
1132                                         resultclass=MockResultClass)
1133        self.assertEqual(runner.resultclass, MockResultClass)
1134
1135        expectedresult = (runner.stream, DESCRIPTIONS, VERBOSITY)
1136        self.assertEqual(runner._makeResult(), expectedresult)
1137
1138    def test_warnings(self):
1139        """
1140        Check that warnings argument of TextTestRunner correctly affects the
1141        behavior of the warnings.
1142        """
1143        # see #10535 and the _test_warnings file for more information
1144
1145        def get_parse_out_err(p):
1146            return [b.splitlines() for b in p.communicate()]
1147        opts = dict(stdout=subprocess.PIPE, stderr=subprocess.PIPE,
1148                    cwd=os.path.dirname(__file__))
1149        ae_msg = b'Please use assertEqual instead.'
1150        at_msg = b'Please use assertTrue instead.'
1151
1152        # no args -> all the warnings are printed, unittest warnings only once
1153        p = subprocess.Popen([sys.executable, '-E', '_test_warnings.py'], **opts)
1154        with p:
1155            out, err = get_parse_out_err(p)
1156        self.assertIn(b'OK', err)
1157        # check that the total number of warnings in the output is correct
1158        self.assertEqual(len(out), 12)
1159        # check that the numbers of the different kind of warnings is correct
1160        for msg in [b'dw', b'iw', b'uw']:
1161            self.assertEqual(out.count(msg), 3)
1162        for msg in [ae_msg, at_msg, b'rw']:
1163            self.assertEqual(out.count(msg), 1)
1164
1165        args_list = (
1166            # passing 'ignore' as warnings arg -> no warnings
1167            [sys.executable, '_test_warnings.py', 'ignore'],
1168            # -W doesn't affect the result if the arg is passed
1169            [sys.executable, '-Wa', '_test_warnings.py', 'ignore'],
1170            # -W affects the result if the arg is not passed
1171            [sys.executable, '-Wi', '_test_warnings.py']
1172        )
1173        # in all these cases no warnings are printed
1174        for args in args_list:
1175            p = subprocess.Popen(args, **opts)
1176            with p:
1177                out, err = get_parse_out_err(p)
1178            self.assertIn(b'OK', err)
1179            self.assertEqual(len(out), 0)
1180
1181
1182        # passing 'always' as warnings arg -> all the warnings printed,
1183        #                                     unittest warnings only once
1184        p = subprocess.Popen([sys.executable, '_test_warnings.py', 'always'],
1185                             **opts)
1186        with p:
1187            out, err = get_parse_out_err(p)
1188        self.assertIn(b'OK', err)
1189        self.assertEqual(len(out), 14)
1190        for msg in [b'dw', b'iw', b'uw', b'rw']:
1191            self.assertEqual(out.count(msg), 3)
1192        for msg in [ae_msg, at_msg]:
1193            self.assertEqual(out.count(msg), 1)
1194
1195    def testStdErrLookedUpAtInstantiationTime(self):
1196        # see issue 10786
1197        old_stderr = sys.stderr
1198        f = io.StringIO()
1199        sys.stderr = f
1200        try:
1201            runner = unittest.TextTestRunner()
1202            self.assertTrue(runner.stream.stream is f)
1203        finally:
1204            sys.stderr = old_stderr
1205
1206    def testSpecifiedStreamUsed(self):
1207        # see issue 10786
1208        f = io.StringIO()
1209        runner = unittest.TextTestRunner(f)
1210        self.assertTrue(runner.stream.stream is f)
1211
1212
1213if __name__ == "__main__":
1214    unittest.main()
1215