mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
bpo-45162: Revert "Remove many old deprecated unittest features" (GH-30935)
Revert "bpo-45162: Remove many old deprecated unittest features (GH-28268)"
This reverts commit b0a6ede3d0
.
We're deferring this change until 3.12 while upstream projects that use
the legacy assertion method names are fixed. See the issue for links
to the discussion. Many upstream projects now have issues and PRs
filed.
This commit is contained in:
parent
9f0881476e
commit
b50322d203
14 changed files with 376 additions and 55 deletions
|
@ -18,6 +18,17 @@ def warnfun():
|
|||
warnings.warn('rw', RuntimeWarning)
|
||||
|
||||
class TestWarnings(unittest.TestCase):
|
||||
# unittest warnings will be printed at most once per type (max one message
|
||||
# for the fail* methods, and one for the assert* methods)
|
||||
def test_assert(self):
|
||||
self.assertEquals(2+2, 4)
|
||||
self.assertEquals(2*2, 4)
|
||||
self.assertEquals(2**2, 4)
|
||||
|
||||
def test_fail(self):
|
||||
self.failUnless(1)
|
||||
self.failUnless(True)
|
||||
|
||||
def test_other_unittest(self):
|
||||
self.assertAlmostEqual(2+2, 4)
|
||||
self.assertNotAlmostEqual(4+4, 2)
|
||||
|
|
|
@ -271,6 +271,15 @@ class TestLongMessage(unittest.TestCase):
|
|||
r"\+ \{'key': 'value'\}$",
|
||||
r"\+ \{'key': 'value'\} : oops$"])
|
||||
|
||||
def testAssertDictContainsSubset(self):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", DeprecationWarning)
|
||||
|
||||
self.assertMessages('assertDictContainsSubset', ({'key': 'value'}, {}),
|
||||
["^Missing: 'key'$", "^oops$",
|
||||
"^Missing: 'key'$",
|
||||
"^Missing: 'key' : oops$"])
|
||||
|
||||
def testAssertMultiLineEqual(self):
|
||||
self.assertMessages('assertMultiLineEqual', ("", "foo"),
|
||||
[r"\+ foo$", "^oops$",
|
||||
|
|
|
@ -698,6 +698,36 @@ class Test_TestCase(unittest.TestCase, TestEquality, TestHashing):
|
|||
self.assertRaises(self.failureException, self.assertNotIn, 'cow',
|
||||
animals)
|
||||
|
||||
def testAssertDictContainsSubset(self):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", DeprecationWarning)
|
||||
|
||||
self.assertDictContainsSubset({}, {})
|
||||
self.assertDictContainsSubset({}, {'a': 1})
|
||||
self.assertDictContainsSubset({'a': 1}, {'a': 1})
|
||||
self.assertDictContainsSubset({'a': 1}, {'a': 1, 'b': 2})
|
||||
self.assertDictContainsSubset({'a': 1, 'b': 2}, {'a': 1, 'b': 2})
|
||||
|
||||
with self.assertRaises(self.failureException):
|
||||
self.assertDictContainsSubset({1: "one"}, {})
|
||||
|
||||
with self.assertRaises(self.failureException):
|
||||
self.assertDictContainsSubset({'a': 2}, {'a': 1})
|
||||
|
||||
with self.assertRaises(self.failureException):
|
||||
self.assertDictContainsSubset({'c': 1}, {'a': 1})
|
||||
|
||||
with self.assertRaises(self.failureException):
|
||||
self.assertDictContainsSubset({'a': 1, 'c': 1}, {'a': 1})
|
||||
|
||||
with self.assertRaises(self.failureException):
|
||||
self.assertDictContainsSubset({'a': 1, 'c': 1}, {'a': 1})
|
||||
|
||||
one = ''.join(chr(i) for i in range(255))
|
||||
# this used to cause a UnicodeDecodeError constructing the failure msg
|
||||
with self.assertRaises(self.failureException):
|
||||
self.assertDictContainsSubset({'foo': one}, {'foo': '\uFFFD'})
|
||||
|
||||
def testAssertEqual(self):
|
||||
equal_pairs = [
|
||||
((), ()),
|
||||
|
@ -1760,18 +1790,45 @@ test case
|
|||
pass
|
||||
self.assertIsNone(value)
|
||||
|
||||
def testDeprecatedFailMethods(self):
|
||||
"""Test that the deprecated fail* methods get removed in 3.11"""
|
||||
def testDeprecatedMethodNames(self):
|
||||
"""
|
||||
Test that the deprecated methods raise a DeprecationWarning. See #9424.
|
||||
"""
|
||||
old = (
|
||||
(self.failIfEqual, (3, 5)),
|
||||
(self.assertNotEquals, (3, 5)),
|
||||
(self.failUnlessEqual, (3, 3)),
|
||||
(self.assertEquals, (3, 3)),
|
||||
(self.failUnlessAlmostEqual, (2.0, 2.0)),
|
||||
(self.assertAlmostEquals, (2.0, 2.0)),
|
||||
(self.failIfAlmostEqual, (3.0, 5.0)),
|
||||
(self.assertNotAlmostEquals, (3.0, 5.0)),
|
||||
(self.failUnless, (True,)),
|
||||
(self.assert_, (True,)),
|
||||
(self.failUnlessRaises, (TypeError, lambda _: 3.14 + 'spam')),
|
||||
(self.failIf, (False,)),
|
||||
(self.assertDictContainsSubset, (dict(a=1, b=2), dict(a=1, b=2, c=3))),
|
||||
(self.assertRaisesRegexp, (KeyError, 'foo', lambda: {}['foo'])),
|
||||
(self.assertRegexpMatches, ('bar', 'bar')),
|
||||
)
|
||||
for meth, args in old:
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
meth(*args)
|
||||
|
||||
# disable this test for now. When the version where the fail* methods will
|
||||
# be removed is decided, re-enable it and update the version
|
||||
def _testDeprecatedFailMethods(self):
|
||||
"""Test that the deprecated fail* methods get removed in 3.x"""
|
||||
if sys.version_info[:2] < (3, 3):
|
||||
return
|
||||
deprecated_names = [
|
||||
'failIfEqual', 'failUnlessEqual', 'failUnlessAlmostEqual',
|
||||
'failIfAlmostEqual', 'failUnless', 'failUnlessRaises', 'failIf',
|
||||
'assertNotEquals', 'assertEquals', 'assertAlmostEquals',
|
||||
'assertNotAlmostEquals', 'assert_', 'assertDictContainsSubset',
|
||||
'assertRaisesRegexp', 'assertRegexpMatches'
|
||||
'assertDictContainsSubset',
|
||||
]
|
||||
for deprecated_name in deprecated_names:
|
||||
with self.assertRaises(AttributeError):
|
||||
getattr(self, deprecated_name)
|
||||
getattr(self, deprecated_name) # remove these in 3.x
|
||||
|
||||
def testDeepcopy(self):
|
||||
# Issue: 5660
|
||||
|
|
|
@ -5,6 +5,25 @@ import warnings
|
|||
|
||||
import unittest
|
||||
|
||||
# Decorator used in the deprecation tests to reset the warning registry for
|
||||
# test isolation and reproducibility.
|
||||
def warningregistry(func):
|
||||
def wrapper(*args, **kws):
|
||||
missing = []
|
||||
saved = getattr(warnings, '__warningregistry__', missing).copy()
|
||||
try:
|
||||
return func(*args, **kws)
|
||||
finally:
|
||||
if saved is missing:
|
||||
try:
|
||||
del warnings.__warningregistry__
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
warnings.__warningregistry__ = saved
|
||||
return wrapper
|
||||
|
||||
|
||||
class Test_TestLoader(unittest.TestCase):
|
||||
|
||||
### Basic object tests
|
||||
|
@ -155,8 +174,9 @@ class Test_TestLoader(unittest.TestCase):
|
|||
self.assertEqual(list(suite), reference)
|
||||
|
||||
|
||||
# Check that loadTestsFromModule honors a module
|
||||
# Check that loadTestsFromModule honors (or not) a module
|
||||
# with a load_tests function.
|
||||
@warningregistry
|
||||
def test_loadTestsFromModule__load_tests(self):
|
||||
m = types.ModuleType('m')
|
||||
class MyTestCase(unittest.TestCase):
|
||||
|
@ -175,13 +195,126 @@ class Test_TestLoader(unittest.TestCase):
|
|||
suite = loader.loadTestsFromModule(m)
|
||||
self.assertIsInstance(suite, unittest.TestSuite)
|
||||
self.assertEqual(load_tests_args, [loader, suite, None])
|
||||
# With Python 3.5, the undocumented and unofficial use_load_tests is
|
||||
# ignored (and deprecated).
|
||||
load_tests_args = []
|
||||
with warnings.catch_warnings(record=False):
|
||||
warnings.simplefilter('ignore')
|
||||
suite = loader.loadTestsFromModule(m, use_load_tests=False)
|
||||
self.assertEqual(load_tests_args, [loader, suite, None])
|
||||
|
||||
# In Python 3.11, the undocumented and unofficial use_load_tests has
|
||||
# been removed.
|
||||
with self.assertRaises(TypeError):
|
||||
loader.loadTestsFromModule(m, False)
|
||||
with self.assertRaises(TypeError):
|
||||
loader.loadTestsFromModule(m, use_load_tests=False)
|
||||
@warningregistry
|
||||
def test_loadTestsFromModule__use_load_tests_deprecated_positional(self):
|
||||
m = types.ModuleType('m')
|
||||
class MyTestCase(unittest.TestCase):
|
||||
def test(self):
|
||||
pass
|
||||
m.testcase_1 = MyTestCase
|
||||
|
||||
load_tests_args = []
|
||||
def load_tests(loader, tests, pattern):
|
||||
self.assertIsInstance(tests, unittest.TestSuite)
|
||||
load_tests_args.extend((loader, tests, pattern))
|
||||
return tests
|
||||
m.load_tests = load_tests
|
||||
# The method still works.
|
||||
loader = unittest.TestLoader()
|
||||
# use_load_tests=True as a positional argument.
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
suite = loader.loadTestsFromModule(m, False)
|
||||
self.assertIsInstance(suite, unittest.TestSuite)
|
||||
# load_tests was still called because use_load_tests is deprecated
|
||||
# and ignored.
|
||||
self.assertEqual(load_tests_args, [loader, suite, None])
|
||||
# We got a warning.
|
||||
self.assertIs(w[-1].category, DeprecationWarning)
|
||||
self.assertEqual(str(w[-1].message),
|
||||
'use_load_tests is deprecated and ignored')
|
||||
|
||||
@warningregistry
|
||||
def test_loadTestsFromModule__use_load_tests_deprecated_keyword(self):
|
||||
m = types.ModuleType('m')
|
||||
class MyTestCase(unittest.TestCase):
|
||||
def test(self):
|
||||
pass
|
||||
m.testcase_1 = MyTestCase
|
||||
|
||||
load_tests_args = []
|
||||
def load_tests(loader, tests, pattern):
|
||||
self.assertIsInstance(tests, unittest.TestSuite)
|
||||
load_tests_args.extend((loader, tests, pattern))
|
||||
return tests
|
||||
m.load_tests = load_tests
|
||||
# The method still works.
|
||||
loader = unittest.TestLoader()
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
suite = loader.loadTestsFromModule(m, use_load_tests=False)
|
||||
self.assertIsInstance(suite, unittest.TestSuite)
|
||||
# load_tests was still called because use_load_tests is deprecated
|
||||
# and ignored.
|
||||
self.assertEqual(load_tests_args, [loader, suite, None])
|
||||
# We got a warning.
|
||||
self.assertIs(w[-1].category, DeprecationWarning)
|
||||
self.assertEqual(str(w[-1].message),
|
||||
'use_load_tests is deprecated and ignored')
|
||||
|
||||
@warningregistry
|
||||
def test_loadTestsFromModule__too_many_positional_args(self):
|
||||
m = types.ModuleType('m')
|
||||
class MyTestCase(unittest.TestCase):
|
||||
def test(self):
|
||||
pass
|
||||
m.testcase_1 = MyTestCase
|
||||
|
||||
load_tests_args = []
|
||||
def load_tests(loader, tests, pattern):
|
||||
self.assertIsInstance(tests, unittest.TestSuite)
|
||||
load_tests_args.extend((loader, tests, pattern))
|
||||
return tests
|
||||
m.load_tests = load_tests
|
||||
loader = unittest.TestLoader()
|
||||
with self.assertRaises(TypeError) as cm, \
|
||||
warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
loader.loadTestsFromModule(m, False, 'testme.*')
|
||||
# We still got the deprecation warning.
|
||||
self.assertIs(w[-1].category, DeprecationWarning)
|
||||
self.assertEqual(str(w[-1].message),
|
||||
'use_load_tests is deprecated and ignored')
|
||||
# We also got a TypeError for too many positional arguments.
|
||||
self.assertEqual(type(cm.exception), TypeError)
|
||||
self.assertEqual(
|
||||
str(cm.exception),
|
||||
'loadTestsFromModule() takes 1 positional argument but 3 were given')
|
||||
|
||||
@warningregistry
|
||||
def test_loadTestsFromModule__use_load_tests_other_bad_keyword(self):
|
||||
m = types.ModuleType('m')
|
||||
class MyTestCase(unittest.TestCase):
|
||||
def test(self):
|
||||
pass
|
||||
m.testcase_1 = MyTestCase
|
||||
|
||||
load_tests_args = []
|
||||
def load_tests(loader, tests, pattern):
|
||||
self.assertIsInstance(tests, unittest.TestSuite)
|
||||
load_tests_args.extend((loader, tests, pattern))
|
||||
return tests
|
||||
m.load_tests = load_tests
|
||||
loader = unittest.TestLoader()
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore')
|
||||
with self.assertRaises(TypeError) as cm:
|
||||
loader.loadTestsFromModule(
|
||||
m, use_load_tests=False, very_bad=True, worse=False)
|
||||
self.assertEqual(type(cm.exception), TypeError)
|
||||
# The error message names the first bad argument alphabetically,
|
||||
# however use_load_tests (which sorts first) is ignored.
|
||||
self.assertEqual(
|
||||
str(cm.exception),
|
||||
"loadTestsFromModule() got an unexpected keyword argument 'very_bad'")
|
||||
|
||||
def test_loadTestsFromModule__pattern(self):
|
||||
m = types.ModuleType('m')
|
||||
|
|
|
@ -460,14 +460,14 @@ class TestCommandLineArgs(unittest.TestCase):
|
|||
return stderr.decode()
|
||||
|
||||
t = '_test_warnings'
|
||||
self.assertIn('Ran 5 tests', run_unittest([t]))
|
||||
self.assertIn('Ran 5 tests', run_unittest(['-k', 'TestWarnings', t]))
|
||||
self.assertIn('Ran 5 tests', run_unittest(['discover', '-p', '*_test*', '-k', 'TestWarnings']))
|
||||
self.assertIn('Ran 1 test ', run_unittest(['-k', 'f', t]))
|
||||
self.assertIn('Ran 5 tests', run_unittest(['-k', 't', t]))
|
||||
self.assertIn('Ran 2 tests', run_unittest(['-k', '*t', t]))
|
||||
self.assertIn('Ran 5 tests', run_unittest(['-k', '*test_warnings.*Warning*', t]))
|
||||
self.assertIn('Ran 1 test ', run_unittest(['-k', '*test_warnings.*warning*', t]))
|
||||
self.assertIn('Ran 7 tests', run_unittest([t]))
|
||||
self.assertIn('Ran 7 tests', run_unittest(['-k', 'TestWarnings', t]))
|
||||
self.assertIn('Ran 7 tests', run_unittest(['discover', '-p', '*_test*', '-k', 'TestWarnings']))
|
||||
self.assertIn('Ran 2 tests', run_unittest(['-k', 'f', t]))
|
||||
self.assertIn('Ran 7 tests', run_unittest(['-k', 't', t]))
|
||||
self.assertIn('Ran 3 tests', run_unittest(['-k', '*t', t]))
|
||||
self.assertIn('Ran 7 tests', run_unittest(['-k', '*test_warnings.*Warning*', t]))
|
||||
self.assertIn('Ran 1 test', run_unittest(['-k', '*test_warnings.*warning*', t]))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -1150,6 +1150,8 @@ class Test_TextTestRunner(unittest.TestCase):
|
|||
return [b.splitlines() for b in p.communicate()]
|
||||
opts = dict(stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||
cwd=os.path.dirname(__file__))
|
||||
ae_msg = b'Please use assertEqual instead.'
|
||||
at_msg = b'Please use assertTrue instead.'
|
||||
|
||||
# no args -> all the warnings are printed, unittest warnings only once
|
||||
p = subprocess.Popen([sys.executable, '-E', '_test_warnings.py'], **opts)
|
||||
|
@ -1157,11 +1159,11 @@ class Test_TextTestRunner(unittest.TestCase):
|
|||
out, err = get_parse_out_err(p)
|
||||
self.assertIn(b'OK', err)
|
||||
# check that the total number of warnings in the output is correct
|
||||
self.assertEqual(len(out), 10)
|
||||
self.assertEqual(len(out), 12)
|
||||
# check that the numbers of the different kind of warnings is correct
|
||||
for msg in [b'dw', b'iw', b'uw']:
|
||||
self.assertEqual(out.count(msg), 3)
|
||||
for msg in [b'rw']:
|
||||
for msg in [ae_msg, at_msg, b'rw']:
|
||||
self.assertEqual(out.count(msg), 1)
|
||||
|
||||
args_list = (
|
||||
|
@ -1188,9 +1190,11 @@ class Test_TextTestRunner(unittest.TestCase):
|
|||
with p:
|
||||
out, err = get_parse_out_err(p)
|
||||
self.assertIn(b'OK', err)
|
||||
self.assertEqual(len(out), 12)
|
||||
self.assertEqual(len(out), 14)
|
||||
for msg in [b'dw', b'iw', b'uw', b'rw']:
|
||||
self.assertEqual(out.count(msg), 3)
|
||||
for msg in [ae_msg, at_msg]:
|
||||
self.assertEqual(out.count(msg), 1)
|
||||
|
||||
def testStdErrLookedUpAtInstantiationTime(self):
|
||||
# see issue 10786
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue