1import unittest
2
3from cStringIO import StringIO
4import pickle
5
6from .support import LoggingResult, ResultWithNoStartTestRunStopTestRun
7
8
9class TestCleanUp(unittest.TestCase):
10
11    def testCleanUp(self):
12        class TestableTest(unittest.TestCase):
13            def testNothing(self):
14                pass
15
16        test = TestableTest('testNothing')
17        self.assertEqual(test._cleanups, [])
18
19        cleanups = []
20
21        def cleanup1(*args, **kwargs):
22            cleanups.append((1, args, kwargs))
23
24        def cleanup2(*args, **kwargs):
25            cleanups.append((2, args, kwargs))
26
27        test.addCleanup(cleanup1, 1, 2, 3, four='hello', five='goodbye')
28        test.addCleanup(cleanup2)
29
30        self.assertEqual(test._cleanups,
31                         [(cleanup1, (1, 2, 3), dict(four='hello', five='goodbye')),
32                          (cleanup2, (), {})])
33
34        result = test.doCleanups()
35        self.assertTrue(result)
36
37        self.assertEqual(cleanups, [(2, (), {}), (1, (1, 2, 3),
38                                    dict(four='hello', five='goodbye'))])
39
40    def testCleanUpWithErrors(self):
41        class TestableTest(unittest.TestCase):
42            def testNothing(self):
43                pass
44
45        class MockResult(object):
46            errors = []
47            def addError(self, test, exc_info):
48                self.errors.append((test, exc_info))
49
50        result = MockResult()
51        test = TestableTest('testNothing')
52        test._resultForDoCleanups = result
53
54        exc1 = Exception('foo')
55        exc2 = Exception('bar')
56        def cleanup1():
57            raise exc1
58
59        def cleanup2():
60            raise exc2
61
62        test.addCleanup(cleanup1)
63        test.addCleanup(cleanup2)
64
65        self.assertFalse(test.doCleanups())
66
67        (test1, (Type1, instance1, _)), (test2, (Type2, instance2, _)) = reversed(MockResult.errors)
68        self.assertEqual((test1, Type1, instance1), (test, Exception, exc1))
69        self.assertEqual((test2, Type2, instance2), (test, Exception, exc2))
70
71    def testCleanupInRun(self):
72        blowUp = False
73        ordering = []
74
75        class TestableTest(unittest.TestCase):
76            def setUp(self):
77                ordering.append('setUp')
78                if blowUp:
79                    raise Exception('foo')
80
81            def testNothing(self):
82                ordering.append('test')
83
84            def tearDown(self):
85                ordering.append('tearDown')
86
87        test = TestableTest('testNothing')
88
89        def cleanup1():
90            ordering.append('cleanup1')
91        def cleanup2():
92            ordering.append('cleanup2')
93        test.addCleanup(cleanup1)
94        test.addCleanup(cleanup2)
95
96        def success(some_test):
97            self.assertEqual(some_test, test)
98            ordering.append('success')
99
100        result = unittest.TestResult()
101        result.addSuccess = success
102
103        test.run(result)
104        self.assertEqual(ordering, ['setUp', 'test', 'tearDown',
105                                    'cleanup2', 'cleanup1', 'success'])
106
107        blowUp = True
108        ordering = []
109        test = TestableTest('testNothing')
110        test.addCleanup(cleanup1)
111        test.run(result)
112        self.assertEqual(ordering, ['setUp', 'cleanup1'])
113
114    def testTestCaseDebugExecutesCleanups(self):
115        ordering = []
116
117        class TestableTest(unittest.TestCase):
118            def setUp(self):
119                ordering.append('setUp')
120                self.addCleanup(cleanup1)
121
122            def testNothing(self):
123                ordering.append('test')
124
125            def tearDown(self):
126                ordering.append('tearDown')
127
128        test = TestableTest('testNothing')
129
130        def cleanup1():
131            ordering.append('cleanup1')
132            test.addCleanup(cleanup2)
133        def cleanup2():
134            ordering.append('cleanup2')
135
136        test.debug()
137        self.assertEqual(ordering, ['setUp', 'test', 'tearDown', 'cleanup1', 'cleanup2'])
138
139
140class Test_TextTestRunner(unittest.TestCase):
141    """Tests for TextTestRunner."""
142
143    def test_init(self):
144        runner = unittest.TextTestRunner()
145        self.assertFalse(runner.failfast)
146        self.assertFalse(runner.buffer)
147        self.assertEqual(runner.verbosity, 1)
148        self.assertTrue(runner.descriptions)
149        self.assertEqual(runner.resultclass, unittest.TextTestResult)
150
151
152    def test_multiple_inheritance(self):
153        class AResult(unittest.TestResult):
154            def __init__(self, stream, descriptions, verbosity):
155                super(AResult, self).__init__(stream, descriptions, verbosity)
156
157        class ATextResult(unittest.TextTestResult, AResult):
158            pass
159
160        # This used to raise an exception due to TextTestResult not passing
161        # on arguments in its __init__ super call
162        ATextResult(None, None, None)
163
164
165    def testBufferAndFailfast(self):
166        class Test(unittest.TestCase):
167            def testFoo(self):
168                pass
169        result = unittest.TestResult()
170        runner = unittest.TextTestRunner(stream=StringIO(), failfast=True,
171                                           buffer=True)
172        # Use our result object
173        runner._makeResult = lambda: result
174        runner.run(Test('testFoo'))
175
176        self.assertTrue(result.failfast)
177        self.assertTrue(result.buffer)
178
179    def testRunnerRegistersResult(self):
180        class Test(unittest.TestCase):
181            def testFoo(self):
182                pass
183        originalRegisterResult = unittest.runner.registerResult
184        def cleanup():
185            unittest.runner.registerResult = originalRegisterResult
186        self.addCleanup(cleanup)
187
188        result = unittest.TestResult()
189        runner = unittest.TextTestRunner(stream=StringIO())
190        # Use our result object
191        runner._makeResult = lambda: result
192
193        self.wasRegistered = 0
194        def fakeRegisterResult(thisResult):
195            self.wasRegistered += 1
196            self.assertEqual(thisResult, result)
197        unittest.runner.registerResult = fakeRegisterResult
198
199        runner.run(unittest.TestSuite())
200        self.assertEqual(self.wasRegistered, 1)
201
202    def test_works_with_result_without_startTestRun_stopTestRun(self):
203        class OldTextResult(ResultWithNoStartTestRunStopTestRun):
204            separator2 = ''
205            def printErrors(self):
206                pass
207
208        class Runner(unittest.TextTestRunner):
209            def __init__(self):
210                super(Runner, self).__init__(StringIO())
211
212            def _makeResult(self):
213                return OldTextResult()
214
215        runner = Runner()
216        runner.run(unittest.TestSuite())
217
218    def test_startTestRun_stopTestRun_called(self):
219        class LoggingTextResult(LoggingResult):
220            separator2 = ''
221            def printErrors(self):
222                pass
223
224        class LoggingRunner(unittest.TextTestRunner):
225            def __init__(self, events):
226                super(LoggingRunner, self).__init__(StringIO())
227                self._events = events
228
229            def _makeResult(self):
230                return LoggingTextResult(self._events)
231
232        events = []
233        runner = LoggingRunner(events)
234        runner.run(unittest.TestSuite())
235        expected = ['startTestRun', 'stopTestRun']
236        self.assertEqual(events, expected)
237
238    def test_pickle_unpickle(self):
239        # Issue #7197: a TextTestRunner should be (un)pickleable. This is
240        # required by test_multiprocessing under Windows (in verbose mode).
241        from StringIO import StringIO as PickleableIO
242        # cStringIO objects are not pickleable, but StringIO objects are.
243        stream = PickleableIO("foo")
244        runner = unittest.TextTestRunner(stream)
245        for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
246            s = pickle.dumps(runner, protocol=protocol)
247            obj = pickle.loads(s)
248            # StringIO objects never compare equal, a cheap test instead.
249            self.assertEqual(obj.stream.getvalue(), stream.getvalue())
250
251    def test_resultclass(self):
252        def MockResultClass(*args):
253            return args
254        STREAM = object()
255        DESCRIPTIONS = object()
256        VERBOSITY = object()
257        runner = unittest.TextTestRunner(STREAM, DESCRIPTIONS, VERBOSITY,
258                                         resultclass=MockResultClass)
259        self.assertEqual(runner.resultclass, MockResultClass)
260
261        expectedresult = (runner.stream, DESCRIPTIONS, VERBOSITY)
262        self.assertEqual(runner._makeResult(), expectedresult)
263
264
265if __name__ == '__main__':
266    unittest.main()
267