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_debug_executes_classCleanUp(self):
226        ordering = []
227
228        class TestableTest(unittest.TestCase):
229            @classmethod
230            def setUpClass(cls):
231                ordering.append('setUpClass')
232                cls.addClassCleanup(cleanup, ordering)
233            def testNothing(self):
234                ordering.append('test')
235            @classmethod
236            def tearDownClass(cls):
237                ordering.append('tearDownClass')
238
239        suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest)
240        suite.debug()
241        self.assertEqual(ordering,
242                         ['setUpClass', 'test', 'tearDownClass', 'cleanup_good'])
243
244    def test_doClassCleanups_with_errors_addClassCleanUp(self):
245        class TestableTest(unittest.TestCase):
246            def testNothing(self):
247                pass
248
249        def cleanup1():
250            raise Exception('cleanup1')
251
252        def cleanup2():
253            raise Exception('cleanup2')
254
255        TestableTest.addClassCleanup(cleanup1)
256        TestableTest.addClassCleanup(cleanup2)
257        with self.assertRaises(Exception) as e:
258            TestableTest.doClassCleanups()
259            self.assertEqual(e, 'cleanup1')
260
261    def test_with_errors_addCleanUp(self):
262        ordering = []
263        class TestableTest(unittest.TestCase):
264            @classmethod
265            def setUpClass(cls):
266                ordering.append('setUpClass')
267                cls.addClassCleanup(cleanup, ordering)
268            def setUp(self):
269                ordering.append('setUp')
270                self.addCleanup(cleanup, ordering, blowUp=True)
271            def testNothing(self):
272                pass
273            @classmethod
274            def tearDownClass(cls):
275                ordering.append('tearDownClass')
276
277        result = runTests(TestableTest)
278        self.assertEqual(result.errors[0][1].splitlines()[-1],
279                         'Exception: CleanUpExc')
280        self.assertEqual(ordering,
281                         ['setUpClass', 'setUp', 'cleanup_exc',
282                          'tearDownClass', 'cleanup_good'])
283
284    def test_run_with_errors_addClassCleanUp(self):
285        ordering = []
286        class TestableTest(unittest.TestCase):
287            @classmethod
288            def setUpClass(cls):
289                ordering.append('setUpClass')
290                cls.addClassCleanup(cleanup, ordering, blowUp=True)
291            def setUp(self):
292                ordering.append('setUp')
293                self.addCleanup(cleanup, ordering)
294            def testNothing(self):
295                ordering.append('test')
296            @classmethod
297            def tearDownClass(cls):
298                ordering.append('tearDownClass')
299
300        result = runTests(TestableTest)
301        self.assertEqual(result.errors[0][1].splitlines()[-1],
302                         'Exception: CleanUpExc')
303        self.assertEqual(ordering,
304                         ['setUpClass', 'setUp', 'test', 'cleanup_good',
305                          'tearDownClass', 'cleanup_exc'])
306
307    def test_with_errors_in_addClassCleanup_and_setUps(self):
308        ordering = []
309        class_blow_up = False
310        method_blow_up = False
311
312        class TestableTest(unittest.TestCase):
313            @classmethod
314            def setUpClass(cls):
315                ordering.append('setUpClass')
316                cls.addClassCleanup(cleanup, ordering, blowUp=True)
317                if class_blow_up:
318                    raise Exception('ClassExc')
319            def setUp(self):
320                ordering.append('setUp')
321                if method_blow_up:
322                    raise Exception('MethodExc')
323            def testNothing(self):
324                ordering.append('test')
325            @classmethod
326            def tearDownClass(cls):
327                ordering.append('tearDownClass')
328
329        result = runTests(TestableTest)
330        self.assertEqual(result.errors[0][1].splitlines()[-1],
331                         'Exception: CleanUpExc')
332        self.assertEqual(ordering,
333                         ['setUpClass', 'setUp', 'test',
334                          'tearDownClass', 'cleanup_exc'])
335        ordering = []
336        class_blow_up = True
337        method_blow_up = False
338        result = runTests(TestableTest)
339        self.assertEqual(result.errors[0][1].splitlines()[-1],
340                         'Exception: ClassExc')
341        self.assertEqual(result.errors[1][1].splitlines()[-1],
342                         'Exception: CleanUpExc')
343        self.assertEqual(ordering,
344                         ['setUpClass', 'cleanup_exc'])
345
346        ordering = []
347        class_blow_up = False
348        method_blow_up = True
349        result = runTests(TestableTest)
350        self.assertEqual(result.errors[0][1].splitlines()[-1],
351                         'Exception: MethodExc')
352        self.assertEqual(result.errors[1][1].splitlines()[-1],
353                         'Exception: CleanUpExc')
354        self.assertEqual(ordering,
355                         ['setUpClass', 'setUp', 'tearDownClass',
356                          'cleanup_exc'])
357
358
359class TestModuleCleanUp(unittest.TestCase):
360    def test_add_and_do_ModuleCleanup(self):
361        module_cleanups = []
362
363        def module_cleanup1(*args, **kwargs):
364            module_cleanups.append((3, args, kwargs))
365
366        def module_cleanup2(*args, **kwargs):
367            module_cleanups.append((4, args, kwargs))
368
369        class Module(object):
370            unittest.addModuleCleanup(module_cleanup1, 1, 2, 3,
371                                      four='hello', five='goodbye')
372            unittest.addModuleCleanup(module_cleanup2)
373
374        self.assertEqual(unittest.case._module_cleanups,
375                         [(module_cleanup1, (1, 2, 3),
376                           dict(four='hello', five='goodbye')),
377                          (module_cleanup2, (), {})])
378
379        unittest.case.doModuleCleanups()
380        self.assertEqual(module_cleanups, [(4, (), {}), (3, (1, 2, 3),
381                                          dict(four='hello', five='goodbye'))])
382        self.assertEqual(unittest.case._module_cleanups, [])
383
384    def test_doModuleCleanup_with_errors_in_addModuleCleanup(self):
385        module_cleanups = []
386
387        def module_cleanup_good(*args, **kwargs):
388            module_cleanups.append((3, args, kwargs))
389
390        def module_cleanup_bad(*args, **kwargs):
391            raise Exception('CleanUpExc')
392
393        class Module(object):
394            unittest.addModuleCleanup(module_cleanup_good, 1, 2, 3,
395                                      four='hello', five='goodbye')
396            unittest.addModuleCleanup(module_cleanup_bad)
397        self.assertEqual(unittest.case._module_cleanups,
398                         [(module_cleanup_good, (1, 2, 3),
399                           dict(four='hello', five='goodbye')),
400                          (module_cleanup_bad, (), {})])
401        with self.assertRaises(Exception) as e:
402            unittest.case.doModuleCleanups()
403        self.assertEqual(str(e.exception), 'CleanUpExc')
404        self.assertEqual(unittest.case._module_cleanups, [])
405
406    def test_addModuleCleanup_arg_errors(self):
407        cleanups = []
408        def cleanup(*args, **kwargs):
409            cleanups.append((args, kwargs))
410
411        class Module(object):
412            unittest.addModuleCleanup(cleanup, 1, 2, function='hello')
413            with self.assertRaises(TypeError):
414                unittest.addModuleCleanup(function=cleanup, arg='hello')
415            with self.assertRaises(TypeError):
416                unittest.addModuleCleanup()
417        unittest.case.doModuleCleanups()
418        self.assertEqual(cleanups,
419                         [((1, 2), {'function': 'hello'})])
420
421    def test_run_module_cleanUp(self):
422        blowUp = True
423        ordering = []
424        class Module(object):
425            @staticmethod
426            def setUpModule():
427                ordering.append('setUpModule')
428                unittest.addModuleCleanup(cleanup, ordering)
429                if blowUp:
430                    raise Exception('setUpModule Exc')
431            @staticmethod
432            def tearDownModule():
433                ordering.append('tearDownModule')
434
435        class TestableTest(unittest.TestCase):
436            @classmethod
437            def setUpClass(cls):
438                ordering.append('setUpClass')
439            def testNothing(self):
440                ordering.append('test')
441            @classmethod
442            def tearDownClass(cls):
443                ordering.append('tearDownClass')
444
445        TestableTest.__module__ = 'Module'
446        sys.modules['Module'] = Module
447        result = runTests(TestableTest)
448        self.assertEqual(ordering, ['setUpModule', 'cleanup_good'])
449        self.assertEqual(result.errors[0][1].splitlines()[-1],
450                         'Exception: setUpModule Exc')
451
452        ordering = []
453        blowUp = False
454        runTests(TestableTest)
455        self.assertEqual(ordering,
456                         ['setUpModule', 'setUpClass', 'test', 'tearDownClass',
457                          'tearDownModule', 'cleanup_good'])
458        self.assertEqual(unittest.case._module_cleanups, [])
459
460    def test_run_multiple_module_cleanUp(self):
461        blowUp = True
462        blowUp2 = False
463        ordering = []
464        class Module1(object):
465            @staticmethod
466            def setUpModule():
467                ordering.append('setUpModule')
468                unittest.addModuleCleanup(cleanup, ordering)
469                if blowUp:
470                    raise Exception()
471            @staticmethod
472            def tearDownModule():
473                ordering.append('tearDownModule')
474
475        class Module2(object):
476            @staticmethod
477            def setUpModule():
478                ordering.append('setUpModule2')
479                unittest.addModuleCleanup(cleanup, ordering)
480                if blowUp2:
481                    raise Exception()
482            @staticmethod
483            def tearDownModule():
484                ordering.append('tearDownModule2')
485
486        class TestableTest(unittest.TestCase):
487            @classmethod
488            def setUpClass(cls):
489                ordering.append('setUpClass')
490            def testNothing(self):
491                ordering.append('test')
492            @classmethod
493            def tearDownClass(cls):
494                ordering.append('tearDownClass')
495
496        class TestableTest2(unittest.TestCase):
497            @classmethod
498            def setUpClass(cls):
499                ordering.append('setUpClass2')
500            def testNothing(self):
501                ordering.append('test2')
502            @classmethod
503            def tearDownClass(cls):
504                ordering.append('tearDownClass2')
505
506        TestableTest.__module__ = 'Module1'
507        sys.modules['Module1'] = Module1
508        TestableTest2.__module__ = 'Module2'
509        sys.modules['Module2'] = Module2
510        runTests(TestableTest, TestableTest2)
511        self.assertEqual(ordering, ['setUpModule', 'cleanup_good',
512                                    'setUpModule2', 'setUpClass2', 'test2',
513                                    'tearDownClass2', 'tearDownModule2',
514                                    'cleanup_good'])
515        ordering = []
516        blowUp = False
517        blowUp2 = True
518        runTests(TestableTest, TestableTest2)
519        self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test',
520                                    'tearDownClass', 'tearDownModule',
521                                    'cleanup_good', 'setUpModule2',
522                                    'cleanup_good'])
523
524        ordering = []
525        blowUp = False
526        blowUp2 = False
527        runTests(TestableTest, TestableTest2)
528        self.assertEqual(ordering,
529                         ['setUpModule', 'setUpClass', 'test', 'tearDownClass',
530                          'tearDownModule', 'cleanup_good', 'setUpModule2',
531                          'setUpClass2', 'test2', 'tearDownClass2',
532                          'tearDownModule2', 'cleanup_good'])
533        self.assertEqual(unittest.case._module_cleanups, [])
534
535    def test_debug_module_executes_cleanUp(self):
536        ordering = []
537        class Module(object):
538            @staticmethod
539            def setUpModule():
540                ordering.append('setUpModule')
541                unittest.addModuleCleanup(cleanup, ordering)
542            @staticmethod
543            def tearDownModule():
544                ordering.append('tearDownModule')
545
546        class TestableTest(unittest.TestCase):
547            @classmethod
548            def setUpClass(cls):
549                ordering.append('setUpClass')
550            def testNothing(self):
551                ordering.append('test')
552            @classmethod
553            def tearDownClass(cls):
554                ordering.append('tearDownClass')
555
556        TestableTest.__module__ = 'Module'
557        sys.modules['Module'] = Module
558        suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest)
559        suite.debug()
560        self.assertEqual(ordering,
561                         ['setUpModule', 'setUpClass', 'test', 'tearDownClass',
562                          'tearDownModule', 'cleanup_good'])
563        self.assertEqual(unittest.case._module_cleanups, [])
564
565    def test_addClassCleanup_arg_errors(self):
566        cleanups = []
567        def cleanup(*args, **kwargs):
568            cleanups.append((args, kwargs))
569
570        class TestableTest(unittest.TestCase):
571            @classmethod
572            def setUpClass(cls):
573                cls.addClassCleanup(cleanup, 1, 2, function=3, cls=4)
574                with self.assertRaises(TypeError):
575                    cls.addClassCleanup(function=cleanup, arg='hello')
576            def testNothing(self):
577                pass
578
579        with self.assertRaises(TypeError):
580            TestableTest.addClassCleanup()
581        with self.assertRaises(TypeError):
582            unittest.TestCase.addCleanup(cls=TestableTest(), function=cleanup)
583        runTests(TestableTest)
584        self.assertEqual(cleanups,
585                         [((1, 2), {'function': 3, 'cls': 4})])
586
587    def test_addCleanup_arg_errors(self):
588        cleanups = []
589        def cleanup(*args, **kwargs):
590            cleanups.append((args, kwargs))
591
592        class TestableTest(unittest.TestCase):
593            def setUp(self2):
594                self2.addCleanup(cleanup, 1, 2, function=3, self=4)
595                with self.assertWarns(DeprecationWarning):
596                    self2.addCleanup(function=cleanup, arg='hello')
597            def testNothing(self):
598                pass
599
600        with self.assertRaises(TypeError):
601            TestableTest().addCleanup()
602        with self.assertRaises(TypeError):
603            unittest.TestCase.addCleanup(self=TestableTest(), function=cleanup)
604        runTests(TestableTest)
605        self.assertEqual(cleanups,
606                         [((), {'arg': 'hello'}),
607                          ((1, 2), {'function': 3, 'self': 4})])
608
609    def test_with_errors_in_addClassCleanup(self):
610        ordering = []
611
612        class Module(object):
613            @staticmethod
614            def setUpModule():
615                ordering.append('setUpModule')
616                unittest.addModuleCleanup(cleanup, ordering)
617            @staticmethod
618            def tearDownModule():
619                ordering.append('tearDownModule')
620
621        class TestableTest(unittest.TestCase):
622            @classmethod
623            def setUpClass(cls):
624                ordering.append('setUpClass')
625                cls.addClassCleanup(cleanup, ordering, blowUp=True)
626            def testNothing(self):
627                ordering.append('test')
628            @classmethod
629            def tearDownClass(cls):
630                ordering.append('tearDownClass')
631
632        TestableTest.__module__ = 'Module'
633        sys.modules['Module'] = Module
634
635        result = runTests(TestableTest)
636        self.assertEqual(result.errors[0][1].splitlines()[-1],
637                         'Exception: CleanUpExc')
638        self.assertEqual(ordering,
639                         ['setUpModule', 'setUpClass', 'test', 'tearDownClass',
640                          'cleanup_exc', 'tearDownModule', 'cleanup_good'])
641
642    def test_with_errors_in_addCleanup(self):
643        ordering = []
644        class Module(object):
645            @staticmethod
646            def setUpModule():
647                ordering.append('setUpModule')
648                unittest.addModuleCleanup(cleanup, ordering)
649            @staticmethod
650            def tearDownModule():
651                ordering.append('tearDownModule')
652
653        class TestableTest(unittest.TestCase):
654            def setUp(self):
655                ordering.append('setUp')
656                self.addCleanup(cleanup, ordering, blowUp=True)
657            def testNothing(self):
658                ordering.append('test')
659            def tearDown(self):
660                ordering.append('tearDown')
661
662        TestableTest.__module__ = 'Module'
663        sys.modules['Module'] = Module
664
665        result = runTests(TestableTest)
666        self.assertEqual(result.errors[0][1].splitlines()[-1],
667                         'Exception: CleanUpExc')
668        self.assertEqual(ordering,
669                         ['setUpModule', 'setUp', 'test', 'tearDown',
670                          'cleanup_exc', 'tearDownModule', 'cleanup_good'])
671
672    def test_with_errors_in_addModuleCleanup_and_setUps(self):
673        ordering = []
674        module_blow_up = False
675        class_blow_up = False
676        method_blow_up = False
677        class Module(object):
678            @staticmethod
679            def setUpModule():
680                ordering.append('setUpModule')
681                unittest.addModuleCleanup(cleanup, ordering, blowUp=True)
682                if module_blow_up:
683                    raise Exception('ModuleExc')
684            @staticmethod
685            def tearDownModule():
686                ordering.append('tearDownModule')
687
688        class TestableTest(unittest.TestCase):
689            @classmethod
690            def setUpClass(cls):
691                ordering.append('setUpClass')
692                if class_blow_up:
693                    raise Exception('ClassExc')
694            def setUp(self):
695                ordering.append('setUp')
696                if method_blow_up:
697                    raise Exception('MethodExc')
698            def testNothing(self):
699                ordering.append('test')
700            @classmethod
701            def tearDownClass(cls):
702                ordering.append('tearDownClass')
703
704        TestableTest.__module__ = 'Module'
705        sys.modules['Module'] = Module
706
707        result = runTests(TestableTest)
708        self.assertEqual(result.errors[0][1].splitlines()[-1],
709                         'Exception: CleanUpExc')
710        self.assertEqual(ordering,
711                         ['setUpModule', 'setUpClass', 'setUp', 'test',
712                          'tearDownClass', 'tearDownModule',
713                          'cleanup_exc'])
714
715        ordering = []
716        module_blow_up = True
717        class_blow_up = False
718        method_blow_up = False
719        result = runTests(TestableTest)
720        self.assertEqual(result.errors[0][1].splitlines()[-1],
721                         'Exception: CleanUpExc')
722        self.assertEqual(result.errors[1][1].splitlines()[-1],
723                         'Exception: ModuleExc')
724        self.assertEqual(ordering, ['setUpModule', 'cleanup_exc'])
725
726        ordering = []
727        module_blow_up = False
728        class_blow_up = True
729        method_blow_up = False
730        result = runTests(TestableTest)
731        self.assertEqual(result.errors[0][1].splitlines()[-1],
732                         'Exception: ClassExc')
733        self.assertEqual(result.errors[1][1].splitlines()[-1],
734                         'Exception: CleanUpExc')
735        self.assertEqual(ordering, ['setUpModule', 'setUpClass',
736                                    'tearDownModule', 'cleanup_exc'])
737
738        ordering = []
739        module_blow_up = False
740        class_blow_up = False
741        method_blow_up = True
742        result = runTests(TestableTest)
743        self.assertEqual(result.errors[0][1].splitlines()[-1],
744                         'Exception: MethodExc')
745        self.assertEqual(result.errors[1][1].splitlines()[-1],
746                         'Exception: CleanUpExc')
747        self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'setUp',
748                                    'tearDownClass', 'tearDownModule',
749                                    'cleanup_exc'])
750
751    def test_module_cleanUp_with_multiple_classes(self):
752        ordering =[]
753        def cleanup1():
754            ordering.append('cleanup1')
755
756        def cleanup2():
757            ordering.append('cleanup2')
758
759        def cleanup3():
760            ordering.append('cleanup3')
761
762        class Module(object):
763            @staticmethod
764            def setUpModule():
765                ordering.append('setUpModule')
766                unittest.addModuleCleanup(cleanup1)
767            @staticmethod
768            def tearDownModule():
769                ordering.append('tearDownModule')
770
771        class TestableTest(unittest.TestCase):
772            def setUp(self):
773                ordering.append('setUp')
774                self.addCleanup(cleanup2)
775            def testNothing(self):
776                ordering.append('test')
777            def tearDown(self):
778                ordering.append('tearDown')
779
780        class OtherTestableTest(unittest.TestCase):
781            def setUp(self):
782                ordering.append('setUp2')
783                self.addCleanup(cleanup3)
784            def testNothing(self):
785                ordering.append('test2')
786            def tearDown(self):
787                ordering.append('tearDown2')
788
789        TestableTest.__module__ = 'Module'
790        OtherTestableTest.__module__ = 'Module'
791        sys.modules['Module'] = Module
792        runTests(TestableTest, OtherTestableTest)
793        self.assertEqual(ordering,
794                         ['setUpModule', 'setUp', 'test', 'tearDown',
795                          'cleanup2',  'setUp2', 'test2', 'tearDown2',
796                          'cleanup3', 'tearDownModule', 'cleanup1'])
797
798
799class Test_TextTestRunner(unittest.TestCase):
800    """Tests for TextTestRunner."""
801
802    def setUp(self):
803        # clean the environment from pre-existing PYTHONWARNINGS to make
804        # test_warnings results consistent
805        self.pythonwarnings = os.environ.get('PYTHONWARNINGS')
806        if self.pythonwarnings:
807            del os.environ['PYTHONWARNINGS']
808
809    def tearDown(self):
810        # bring back pre-existing PYTHONWARNINGS if present
811        if self.pythonwarnings:
812            os.environ['PYTHONWARNINGS'] = self.pythonwarnings
813
814    def test_init(self):
815        runner = unittest.TextTestRunner()
816        self.assertFalse(runner.failfast)
817        self.assertFalse(runner.buffer)
818        self.assertEqual(runner.verbosity, 1)
819        self.assertEqual(runner.warnings, None)
820        self.assertTrue(runner.descriptions)
821        self.assertEqual(runner.resultclass, unittest.TextTestResult)
822        self.assertFalse(runner.tb_locals)
823
824    def test_multiple_inheritance(self):
825        class AResult(unittest.TestResult):
826            def __init__(self, stream, descriptions, verbosity):
827                super(AResult, self).__init__(stream, descriptions, verbosity)
828
829        class ATextResult(unittest.TextTestResult, AResult):
830            pass
831
832        # This used to raise an exception due to TextTestResult not passing
833        # on arguments in its __init__ super call
834        ATextResult(None, None, 1)
835
836    def testBufferAndFailfast(self):
837        class Test(unittest.TestCase):
838            def testFoo(self):
839                pass
840        result = unittest.TestResult()
841        runner = unittest.TextTestRunner(stream=io.StringIO(), failfast=True,
842                                         buffer=True)
843        # Use our result object
844        runner._makeResult = lambda: result
845        runner.run(Test('testFoo'))
846
847        self.assertTrue(result.failfast)
848        self.assertTrue(result.buffer)
849
850    def test_locals(self):
851        runner = unittest.TextTestRunner(stream=io.StringIO(), tb_locals=True)
852        result = runner.run(unittest.TestSuite())
853        self.assertEqual(True, result.tb_locals)
854
855    def testRunnerRegistersResult(self):
856        class Test(unittest.TestCase):
857            def testFoo(self):
858                pass
859        originalRegisterResult = unittest.runner.registerResult
860        def cleanup():
861            unittest.runner.registerResult = originalRegisterResult
862        self.addCleanup(cleanup)
863
864        result = unittest.TestResult()
865        runner = unittest.TextTestRunner(stream=io.StringIO())
866        # Use our result object
867        runner._makeResult = lambda: result
868
869        self.wasRegistered = 0
870        def fakeRegisterResult(thisResult):
871            self.wasRegistered += 1
872            self.assertEqual(thisResult, result)
873        unittest.runner.registerResult = fakeRegisterResult
874
875        runner.run(unittest.TestSuite())
876        self.assertEqual(self.wasRegistered, 1)
877
878    def test_works_with_result_without_startTestRun_stopTestRun(self):
879        class OldTextResult(ResultWithNoStartTestRunStopTestRun):
880            separator2 = ''
881            def printErrors(self):
882                pass
883
884        class Runner(unittest.TextTestRunner):
885            def __init__(self):
886                super(Runner, self).__init__(io.StringIO())
887
888            def _makeResult(self):
889                return OldTextResult()
890
891        runner = Runner()
892        runner.run(unittest.TestSuite())
893
894    def test_startTestRun_stopTestRun_called(self):
895        class LoggingTextResult(LoggingResult):
896            separator2 = ''
897            def printErrors(self):
898                pass
899
900        class LoggingRunner(unittest.TextTestRunner):
901            def __init__(self, events):
902                super(LoggingRunner, self).__init__(io.StringIO())
903                self._events = events
904
905            def _makeResult(self):
906                return LoggingTextResult(self._events)
907
908        events = []
909        runner = LoggingRunner(events)
910        runner.run(unittest.TestSuite())
911        expected = ['startTestRun', 'stopTestRun']
912        self.assertEqual(events, expected)
913
914    def test_pickle_unpickle(self):
915        # Issue #7197: a TextTestRunner should be (un)pickleable. This is
916        # required by test_multiprocessing under Windows (in verbose mode).
917        stream = io.StringIO("foo")
918        runner = unittest.TextTestRunner(stream)
919        for protocol in range(2, pickle.HIGHEST_PROTOCOL + 1):
920            s = pickle.dumps(runner, protocol)
921            obj = pickle.loads(s)
922            # StringIO objects never compare equal, a cheap test instead.
923            self.assertEqual(obj.stream.getvalue(), stream.getvalue())
924
925    def test_resultclass(self):
926        def MockResultClass(*args):
927            return args
928        STREAM = object()
929        DESCRIPTIONS = object()
930        VERBOSITY = object()
931        runner = unittest.TextTestRunner(STREAM, DESCRIPTIONS, VERBOSITY,
932                                         resultclass=MockResultClass)
933        self.assertEqual(runner.resultclass, MockResultClass)
934
935        expectedresult = (runner.stream, DESCRIPTIONS, VERBOSITY)
936        self.assertEqual(runner._makeResult(), expectedresult)
937
938    def test_warnings(self):
939        """
940        Check that warnings argument of TextTestRunner correctly affects the
941        behavior of the warnings.
942        """
943        # see #10535 and the _test_warnings file for more information
944
945        def get_parse_out_err(p):
946            return [b.splitlines() for b in p.communicate()]
947        opts = dict(stdout=subprocess.PIPE, stderr=subprocess.PIPE,
948                    cwd=os.path.dirname(__file__))
949        ae_msg = b'Please use assertEqual instead.'
950        at_msg = b'Please use assertTrue instead.'
951
952        # no args -> all the warnings are printed, unittest warnings only once
953        p = subprocess.Popen([sys.executable, '-E', '_test_warnings.py'], **opts)
954        with p:
955            out, err = get_parse_out_err(p)
956        self.assertIn(b'OK', err)
957        # check that the total number of warnings in the output is correct
958        self.assertEqual(len(out), 12)
959        # check that the numbers of the different kind of warnings is correct
960        for msg in [b'dw', b'iw', b'uw']:
961            self.assertEqual(out.count(msg), 3)
962        for msg in [ae_msg, at_msg, b'rw']:
963            self.assertEqual(out.count(msg), 1)
964
965        args_list = (
966            # passing 'ignore' as warnings arg -> no warnings
967            [sys.executable, '_test_warnings.py', 'ignore'],
968            # -W doesn't affect the result if the arg is passed
969            [sys.executable, '-Wa', '_test_warnings.py', 'ignore'],
970            # -W affects the result if the arg is not passed
971            [sys.executable, '-Wi', '_test_warnings.py']
972        )
973        # in all these cases no warnings are printed
974        for args in args_list:
975            p = subprocess.Popen(args, **opts)
976            with p:
977                out, err = get_parse_out_err(p)
978            self.assertIn(b'OK', err)
979            self.assertEqual(len(out), 0)
980
981
982        # passing 'always' as warnings arg -> all the warnings printed,
983        #                                     unittest warnings only once
984        p = subprocess.Popen([sys.executable, '_test_warnings.py', 'always'],
985                             **opts)
986        with p:
987            out, err = get_parse_out_err(p)
988        self.assertIn(b'OK', err)
989        self.assertEqual(len(out), 14)
990        for msg in [b'dw', b'iw', b'uw', b'rw']:
991            self.assertEqual(out.count(msg), 3)
992        for msg in [ae_msg, at_msg]:
993            self.assertEqual(out.count(msg), 1)
994
995    def testStdErrLookedUpAtInstantiationTime(self):
996        # see issue 10786
997        old_stderr = sys.stderr
998        f = io.StringIO()
999        sys.stderr = f
1000        try:
1001            runner = unittest.TextTestRunner()
1002            self.assertTrue(runner.stream.stream is f)
1003        finally:
1004            sys.stderr = old_stderr
1005
1006    def testSpecifiedStreamUsed(self):
1007        # see issue 10786
1008        f = io.StringIO()
1009        runner = unittest.TextTestRunner(f)
1010        self.assertTrue(runner.stream.stream is f)
1011
1012
1013if __name__ == "__main__":
1014    unittest.main()
1015