Skip to content

Commit ae3db0a

Browse files
author
Michael Foord
committed
Support for old TestResult object (unittest) with warnings when using unsupported features.
1 parent 4b81bc7 commit ae3db0a

3 files changed

Lines changed: 77 additions & 8 deletions

File tree

Lib/test/test_unittest.py

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2062,6 +2062,53 @@ def testGetDescriptionWithMultiLineDocstring(self):
20622062
'Tests getDescription() for a method with a longer '
20632063
'docstring.'))
20642064

2065+
classDict = dict(unittest.TestResult.__dict__)
2066+
for m in 'addSkip', 'addExpectedFailure', 'addUnexpectedSuccess':
2067+
del classDict[m]
2068+
OldResult = type('OldResult', (object,), classDict)
2069+
2070+
class Test_OldTestResult(unittest.TestCase):
2071+
2072+
def assertOldResultWarning(self, test, failures):
2073+
with warnings.catch_warnings(record=True) as log:
2074+
result = OldResult()
2075+
test.run(result)
2076+
self.assertEqual(len(result.failures), failures)
2077+
warning, = log
2078+
self.assertIs(warning.category, RuntimeWarning)
2079+
2080+
def testOldTestResult(self):
2081+
class Test(unittest.TestCase):
2082+
def testSkip(self):
2083+
self.skipTest('foobar')
2084+
@unittest.expectedFailure
2085+
def testExpectedFail(self):
2086+
raise TypeError
2087+
@unittest.expectedFailure
2088+
def testUnexpectedSuccess(self):
2089+
pass
2090+
2091+
for test_name, should_pass in (('testSkip', True),
2092+
('testExpectedFail', True),
2093+
('testUnexpectedSuccess', False)):
2094+
test = Test(test_name)
2095+
self.assertOldResultWarning(test, int(not should_pass))
2096+
2097+
def testOldTestTesultSetup(self):
2098+
class Test(unittest.TestCase):
2099+
def setUp(self):
2100+
self.skipTest('no reason')
2101+
def testFoo(self):
2102+
pass
2103+
self.assertOldResultWarning(Test('testFoo'), 0)
2104+
2105+
def testOldTestResultClass(self):
2106+
@unittest.skip('no reason')
2107+
class Test(unittest.TestCase):
2108+
def testFoo(self):
2109+
pass
2110+
self.assertOldResultWarning(Test('testFoo'), 0)
2111+
20652112

20662113
### Support code for Test_TestCase
20672114
################################################################
@@ -3826,7 +3873,8 @@ def test_main():
38263873
test_support.run_unittest(Test_TestCase, Test_TestLoader,
38273874
Test_TestSuite, Test_TestResult, Test_FunctionTestCase,
38283875
Test_TestSkipping, Test_Assertions, TestLongMessage,
3829-
Test_TestProgram, TestCleanUp, TestDiscovery, Test_TextTestRunner)
3876+
Test_TestProgram, TestCleanUp, TestDiscovery, Test_TextTestRunner,
3877+
Test_OldTestResult)
38303878

38313879
if __name__ == "__main__":
38323880
test_main()

Lib/unittest/case.py

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,15 @@ def __repr__(self):
249249
return "<%s testMethod=%s>" % \
250250
(strclass(self.__class__), self._testMethodName)
251251

252+
def _addSkip(self, result, reason):
253+
addSkip = getattr(result, 'addSkip', None)
254+
if addSkip is not None:
255+
addSkip(self, reason)
256+
else:
257+
warnings.warn("TestResult has no addSkip method, skips not reported",
258+
RuntimeWarning, 2)
259+
result.addSuccess(self)
260+
252261
def run(self, result=None):
253262
orig_result = result
254263
if result is None:
@@ -262,7 +271,7 @@ def run(self, result=None):
262271
if getattr(self.__class__, "__unittest_skip__", False):
263272
# If the whole class was skipped.
264273
try:
265-
result.addSkip(self, self.__class__.__unittest_skip_why__)
274+
self._addSkip(result, self.__class__.__unittest_skip_why__)
266275
finally:
267276
result.stopTest(self)
268277
return
@@ -272,7 +281,7 @@ def run(self, result=None):
272281
try:
273282
self.setUp()
274283
except SkipTest as e:
275-
result.addSkip(self, str(e))
284+
self._addSkip(result, str(e))
276285
except Exception:
277286
result.addError(self, sys.exc_info())
278287
else:
@@ -281,11 +290,23 @@ def run(self, result=None):
281290
except self.failureException:
282291
result.addFailure(self, sys.exc_info())
283292
except _ExpectedFailure as e:
284-
result.addExpectedFailure(self, e.exc_info)
293+
addExpectedFailure = getattr(result, 'addExpectedFailure', None)
294+
if addExpectedFailure is not None:
295+
addExpectedFailure(self, e.exc_info)
296+
else:
297+
warnings.warn("TestResult has no addExpectedFailure method, reporting as passes",
298+
RuntimeWarning)
299+
result.addSuccess(self)
285300
except _UnexpectedSuccess:
286-
result.addUnexpectedSuccess(self)
301+
addUnexpectedSuccess = getattr(result, 'addUnexpectedSuccess', None)
302+
if addUnexpectedSuccess is not None:
303+
addUnexpectedSuccess(self)
304+
else:
305+
warnings.warn("TestResult has no addUnexpectedSuccess method, reporting as failures",
306+
RuntimeWarning)
307+
result.addFailure(self, sys.exc_info())
287308
except SkipTest as e:
288-
result.addSkip(self, str(e))
309+
self._addSkip(result, str(e))
289310
except Exception:
290311
result.addError(self, sys.exc_info())
291312
else:

Lib/unittest/result.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,6 @@ def _count_relevant_tb_levels(self, tb):
107107
return length
108108

109109
def __repr__(self):
110-
return "<%s run=%i errors=%i failures=%i>" % \
110+
return ("<%s run=%i errors=%i failures=%i>" %
111111
(util.strclass(self.__class__), self.testsRun, len(self.errors),
112-
len(self.failures))
112+
len(self.failures)))

0 commit comments

Comments
 (0)