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