Skip to content

bpo-45162: Remove many old deprecated unittest features #28268

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 7 additions & 48 deletions Doc/library/unittest.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1237,9 +1237,6 @@ Test cases
:meth:`.assertRegex`.
.. versionadded:: 3.2
:meth:`.assertNotRegex`.
.. versionadded:: 3.5
The name ``assertNotRegexpMatches`` is a deprecated alias
for :meth:`.assertNotRegex`.


.. method:: assertCountEqual(first, second, msg=None)
Expand Down Expand Up @@ -1605,40 +1602,6 @@ Test cases
:mod:`unittest`-based test framework.


.. _deprecated-aliases:

Deprecated aliases
##################

For historical reasons, some of the :class:`TestCase` methods had one or more
aliases that are now deprecated. The following table lists the correct names
along with their deprecated aliases:

============================== ====================== =======================
Method Name Deprecated alias Deprecated alias
============================== ====================== =======================
:meth:`.assertEqual` failUnlessEqual assertEquals
:meth:`.assertNotEqual` failIfEqual assertNotEquals
:meth:`.assertTrue` failUnless assert\_
:meth:`.assertFalse` failIf
:meth:`.assertRaises` failUnlessRaises
:meth:`.assertAlmostEqual` failUnlessAlmostEqual assertAlmostEquals
:meth:`.assertNotAlmostEqual` failIfAlmostEqual assertNotAlmostEquals
:meth:`.assertRegex` assertRegexpMatches
:meth:`.assertNotRegex` assertNotRegexpMatches
:meth:`.assertRaisesRegex` assertRaisesRegexp
============================== ====================== =======================

.. deprecated:: 3.1
The fail* aliases listed in the second column have been deprecated.
.. deprecated:: 3.2
The assert* aliases listed in the third column have been deprecated.
.. deprecated:: 3.2
``assertRegexpMatches`` and ``assertRaisesRegexp`` have been renamed to
:meth:`.assertRegex` and :meth:`.assertRaisesRegex`.
.. deprecated:: 3.5
The ``assertNotRegexpMatches`` name is deprecated in favor of :meth:`.assertNotRegex`.

.. _testsuite-objects:

Grouping tests
Expand Down Expand Up @@ -1764,7 +1727,7 @@ Loading and running tests
case is created for that method instead.


.. method:: loadTestsFromModule(module, pattern=None)
.. method:: loadTestsFromModule(module, *, pattern=None)

Return a suite of all test cases contained in the given module. This
method searches *module* for classes derived from :class:`TestCase` and
Expand All @@ -1788,10 +1751,11 @@ Loading and running tests
Support for ``load_tests`` added.

.. versionchanged:: 3.5
The undocumented and unofficial *use_load_tests* default argument is
deprecated and ignored, although it is still accepted for backward
compatibility. The method also now accepts a keyword-only argument
*pattern* which is passed to ``load_tests`` as the third argument.
Support for a keyword-only argument *pattern* has been added.

.. versionchanged:: 3.11
The undocumented and unofficial *use_load_tests* parameter has been
removed.


.. method:: loadTestsFromName(name, module=None)
Expand Down Expand Up @@ -2144,8 +2108,6 @@ Loading and running tests
:class:`TextTestRunner`.

.. versionadded:: 3.2
This class was previously named ``_TextTestResult``. The old name still
exists as an alias but is deprecated.


.. data:: defaultTestLoader
Expand All @@ -2168,10 +2130,7 @@ Loading and running tests
By default this runner shows :exc:`DeprecationWarning`,
:exc:`PendingDeprecationWarning`, :exc:`ResourceWarning` and
:exc:`ImportWarning` even if they are :ref:`ignored by default
<warning-ignored>`. Deprecation warnings caused by :ref:`deprecated unittest
methods <deprecated-aliases>` are also special-cased and, when the warning
filters are ``'default'`` or ``'always'``, they will appear only once
per-module, in order to avoid too many warning messages. This behavior can
<warning-ignored>`. This behavior can
be overridden using Python's :option:`!-Wd` or :option:`!-Wa` options
(see :ref:`Warning control <using-on-warnings>`) and leaving
*warnings* to ``None``.
Expand Down
22 changes: 22 additions & 0 deletions Doc/whatsnew/3.11.rst
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,28 @@ Removed
and :class:`fileinput.FileInput`, deprecated since Python 3.9.
(Contributed by Hugo van Kemenade in :issue:`45132`.)

* Removed many old deprecated :mod:`unittest` features:

- :class:`~unittest.TestCase` method aliases ``failUnlessEqual``,
``failIfEqual``, ``failUnless``, ``failIf``, ``failUnlessRaises``,
``failUnlessAlmostEqual``, ``failIfAlmostEqual`` (deprecated in Python 3.1),
``assertEquals``, ``assertNotEquals``, ``assert_``, ``assertAlmostEquals``,
``assertNotAlmostEquals``, ``assertRegexpMatches``, ``assertRaisesRegexp``
(deprecated in Python 3.2), and ``assertNotRegexpMatches`` (deprecated in
Python 3.5).

- Undocumented and broken :class:`~unittest.TestCase` method
``assertDictContainsSubset`` (deprecated in Python 3.2).

- Undocumented :meth:`<unittest.TestLoader.loadTestsFromModule>
TestLoader.loadTestsFromModule` parameter *use_load_tests* (deprecated
and ignored since Python 3.2).

- An alias of the :class:`~unittest.TextTestResult` class:
``_TextTestResult`` (deprecated in Python 3.2).

(Contributed by Serhiy Storchaka in :issue:`45162`.)

* The following deprecated functions and methods are removed in the :mod:`gettext`
module: :func:`~gettext.lgettext`, :func:`~gettext.ldgettext`,
:func:`~gettext.lngettext` and :func:`~gettext.ldngettext`.
Expand Down
3 changes: 1 addition & 2 deletions Doc/whatsnew/3.2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1815,8 +1815,7 @@ names.
=============================== ==============================

Likewise, the ``TestCase.fail*`` methods deprecated in Python 3.1 are expected
to be removed in Python 3.3. Also see the :ref:`deprecated-aliases` section in
the :mod:`unittest` documentation.
to be removed in Python 3.3.

(Contributed by Ezio Melotti; :issue:`9424`.)

Expand Down
3 changes: 0 additions & 3 deletions Lib/unittest/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,6 @@ def testMultiply(self):
# IsolatedAsyncioTestCase will be imported lazily.
from .loader import makeSuite, getTestCaseNames, findTestCases

# deprecated
_TextTestResult = TextTestResult


# There are no tests here, so don't try to run anything discovered from
# introspecting the symbols (e.g. FunctionTestCase). Instead, all our
Expand Down
50 changes: 0 additions & 50 deletions Lib/unittest/case.py
Original file line number Diff line number Diff line change
Expand Up @@ -1137,35 +1137,6 @@ def assertDictEqual(self, d1, d2, msg=None):
standardMsg = self._truncateMessage(standardMsg, diff)
self.fail(self._formatMessage(msg, standardMsg))

def assertDictContainsSubset(self, subset, dictionary, msg=None):
"""Checks whether dictionary is a superset of subset."""
warnings.warn('assertDictContainsSubset is deprecated',
DeprecationWarning)
missing = []
mismatched = []
for key, value in subset.items():
if key not in dictionary:
missing.append(key)
elif value != dictionary[key]:
mismatched.append('%s, expected: %s, actual: %s' %
(safe_repr(key), safe_repr(value),
safe_repr(dictionary[key])))

if not (missing or mismatched):
return

standardMsg = ''
if missing:
standardMsg = 'Missing: %s' % ','.join(safe_repr(m) for m in
missing)
if mismatched:
if standardMsg:
standardMsg += '; '
standardMsg += 'Mismatched values: %s' % ','.join(mismatched)

self.fail(self._formatMessage(msg, standardMsg))


def assertCountEqual(self, first, second, msg=None):
"""Asserts that two iterables have the same elements, the same number of
times, without regard to order.
Expand Down Expand Up @@ -1329,27 +1300,6 @@ def assertNotRegex(self, text, unexpected_regex, msg=None):
raise self.failureException(msg)


def _deprecate(original_func):
def deprecated_func(*args, **kwargs):
warnings.warn(
'Please use {0} instead.'.format(original_func.__name__),
DeprecationWarning, 2)
return original_func(*args, **kwargs)
return deprecated_func

# see #9424
failUnlessEqual = assertEquals = _deprecate(assertEqual)
failIfEqual = assertNotEquals = _deprecate(assertNotEqual)
failUnlessAlmostEqual = assertAlmostEquals = _deprecate(assertAlmostEqual)
failIfAlmostEqual = assertNotAlmostEquals = _deprecate(assertNotAlmostEqual)
failUnless = assert_ = _deprecate(assertTrue)
failUnlessRaises = _deprecate(assertRaises)
failIf = _deprecate(assertFalse)
assertRaisesRegexp = _deprecate(assertRaisesRegex)
assertRegexpMatches = _deprecate(assertRegex)
assertNotRegexpMatches = _deprecate(assertNotRegex)



class FunctionTestCase(TestCase):
"""A test case that wraps a test function.
Expand Down
24 changes: 1 addition & 23 deletions Lib/unittest/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,30 +93,8 @@ def loadTestsFromTestCase(self, testCaseClass):
loaded_suite = self.suiteClass(map(testCaseClass, testCaseNames))
return loaded_suite

# XXX After Python 3.5, remove backward compatibility hacks for
# use_load_tests deprecation via *args and **kws. See issue 16662.
def loadTestsFromModule(self, module, *args, pattern=None, **kws):
def loadTestsFromModule(self, module, *, pattern=None):
"""Return a suite of all test cases contained in the given module"""
# This method used to take an undocumented and unofficial
# use_load_tests argument. For backward compatibility, we still
# accept the argument (which can also be the first position) but we
# ignore it and issue a deprecation warning if it's present.
if len(args) > 0 or 'use_load_tests' in kws:
warnings.warn('use_load_tests is deprecated and ignored',
DeprecationWarning)
kws.pop('use_load_tests', None)
if len(args) > 1:
# Complain about the number of arguments, but don't forget the
# required `module` argument.
complaint = len(args) + 1
raise TypeError('loadTestsFromModule() takes 1 positional argument but {} were given'.format(complaint))
if len(kws) != 0:
# Since the keyword arguments are unsorted (see PEP 468), just
# pick the alphabetically sorted first argument to complain about,
# if multiple were given. At least the error message will be
# predictable.
complaint = sorted(kws)[0]
raise TypeError("loadTestsFromModule() got an unexpected keyword argument '{}'".format(complaint))
tests = []
for name in dir(module):
obj = getattr(module, name)
Expand Down
9 changes: 0 additions & 9 deletions Lib/unittest/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,15 +189,6 @@ def run(self, test):
if self.warnings:
# if self.warnings is set, use it to filter all the warnings
warnings.simplefilter(self.warnings)
# if the filter is 'default' or 'always', special-case the
# warnings from the deprecated unittest methods to show them
# no more than once per module, because they can be fairly
# noisy. The -Wd and -Wa flags can be used to bypass this
# only when self.warnings is None.
if self.warnings in ['default', 'always']:
warnings.filterwarnings('module',
category=DeprecationWarning,
message=r'Please use assert\w+ instead.')
startTime = time.perf_counter()
startTestRun = getattr(result, 'startTestRun', None)
if startTestRun is not None:
Expand Down
11 changes: 0 additions & 11 deletions Lib/unittest/test/_test_warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,6 @@ 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)
Expand Down
9 changes: 0 additions & 9 deletions Lib/unittest/test/test_assertions.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,15 +271,6 @@ def testAssertDictEqual(self):
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$",
Expand Down
69 changes: 6 additions & 63 deletions Lib/unittest/test/test_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -696,36 +696,6 @@ def testAssertIn(self):
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 = [
((), ()),
Expand Down Expand Up @@ -1788,45 +1758,18 @@ def testAssertNoLogsYieldsNone(self):
pass
self.assertIsNone(value)

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
def testDeprecatedFailMethods(self):
"""Test that the deprecated fail* methods get removed in 3.11"""
deprecated_names = [
'failIfEqual', 'failUnlessEqual', 'failUnlessAlmostEqual',
'failIfAlmostEqual', 'failUnless', 'failUnlessRaises', 'failIf',
'assertDictContainsSubset',
'assertNotEquals', 'assertEquals', 'assertAlmostEquals',
'assertNotAlmostEquals', 'assert_', 'assertDictContainsSubset',
'assertRaisesRegexp', 'assertRegexpMatches'
]
for deprecated_name in deprecated_names:
with self.assertRaises(AttributeError):
getattr(self, deprecated_name) # remove these in 3.x
getattr(self, deprecated_name)

def testDeepcopy(self):
# Issue: 5660
Expand Down
Loading