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