Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[3.12] gh-71339: Add additional assertion methods in test.support (GH-128707) (GH-128815) #129059

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
57 changes: 57 additions & 0 deletions Lib/test/support/testcase.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,63 @@
from math import copysign, isnan


class ExtraAssertions:

def assertIsSubclass(self, cls, superclass, msg=None):
if issubclass(cls, superclass):
return
standardMsg = f'{cls!r} is not a subclass of {superclass!r}'
self.fail(self._formatMessage(msg, standardMsg))

def assertNotIsSubclass(self, cls, superclass, msg=None):
if not issubclass(cls, superclass):
return
standardMsg = f'{cls!r} is a subclass of {superclass!r}'
self.fail(self._formatMessage(msg, standardMsg))

def assertHasAttr(self, obj, name, msg=None):
if not hasattr(obj, name):
if isinstance(obj, types.ModuleType):
standardMsg = f'module {obj.__name__!r} has no attribute {name!r}'
elif isinstance(obj, type):
standardMsg = f'type object {obj.__name__!r} has no attribute {name!r}'
else:
standardMsg = f'{type(obj).__name__!r} object has no attribute {name!r}'
self.fail(self._formatMessage(msg, standardMsg))

def assertNotHasAttr(self, obj, name, msg=None):
if hasattr(obj, name):
if isinstance(obj, types.ModuleType):
standardMsg = f'module {obj.__name__!r} has unexpected attribute {name!r}'
elif isinstance(obj, type):
standardMsg = f'type object {obj.__name__!r} has unexpected attribute {name!r}'
else:
standardMsg = f'{type(obj).__name__!r} object has unexpected attribute {name!r}'
self.fail(self._formatMessage(msg, standardMsg))

def assertStartsWith(self, s, prefix, msg=None):
if s.startswith(prefix):
return
standardMsg = f"{s!r} doesn't start with {prefix!r}"
self.fail(self._formatMessage(msg, standardMsg))

def assertNotStartsWith(self, s, prefix, msg=None):
if not s.startswith(prefix):
return
self.fail(self._formatMessage(msg, f"{s!r} starts with {prefix!r}"))

def assertEndsWith(self, s, suffix, msg=None):
if s.endswith(suffix):
return
standardMsg = f"{s!r} doesn't end with {suffix!r}"
self.fail(self._formatMessage(msg, standardMsg))

def assertNotEndsWith(self, s, suffix, msg=None):
if not s.endswith(suffix):
return
self.fail(self._formatMessage(msg, f"{s!r} ends with {suffix!r}"))


class ExceptionIsLikeMixin:
def assertExceptionIsLike(self, exc, template):
"""
Expand Down
11 changes: 2 additions & 9 deletions Lib/test/test_descr.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from copy import deepcopy
from contextlib import redirect_stdout
from test import support
from test.support.testcase import ExtraAssertions

try:
import _testcapi
Expand Down Expand Up @@ -403,15 +404,7 @@ def test_wrap_lenfunc_bad_cast(self):
self.assertEqual(range(sys.maxsize).__len__(), sys.maxsize)


class ClassPropertiesAndMethods(unittest.TestCase):

def assertHasAttr(self, obj, name):
self.assertTrue(hasattr(obj, name),
'%r has no attribute %r' % (obj, name))

def assertNotHasAttr(self, obj, name):
self.assertFalse(hasattr(obj, name),
'%r has unexpected attribute %r' % (obj, name))
class ClassPropertiesAndMethods(unittest.TestCase, ExtraAssertions):

def test_python_dicts(self):
# Testing Python subclass of dict...
Expand Down
8 changes: 2 additions & 6 deletions Lib/test/test_gdb/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import sysconfig
import unittest
from test import support
from test.support.testcase import ExtraAssertions


GDB_PROGRAM = shutil.which('gdb') or 'gdb'
Expand Down Expand Up @@ -152,7 +153,7 @@ def setup_module():
print()


class DebuggerTests(unittest.TestCase):
class DebuggerTests(unittest.TestCase, ExtraAssertions):

"""Test that the debugger can debug Python."""

Expand Down Expand Up @@ -280,11 +281,6 @@ def get_stack_trace(self, source=None, script=None,

return out

def assertEndsWith(self, actual, exp_end):
'''Ensure that the given "actual" string ends with "exp_end"'''
self.assertTrue(actual.endswith(exp_end),
msg='%r did not end with %r' % (actual, exp_end))

def assertMultilineMatches(self, actual, pattern):
m = re.match(pattern, actual, re.DOTALL)
if not m:
Expand Down
13 changes: 3 additions & 10 deletions Lib/test/test_pyclbr.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from unittest import TestCase, main as unittest_main
from test.test_importlib import util as test_importlib_util
import warnings
from test.support.testcase import ExtraAssertions


StaticMethodType = type(staticmethod(lambda: None))
Expand All @@ -22,7 +23,7 @@
# is imperfect (as designed), testModule is called with a set of
# members to ignore.

class PyclbrTest(TestCase):
class PyclbrTest(TestCase, ExtraAssertions):

def assertListEq(self, l1, l2, ignore):
''' succeed iff {l1} - {ignore} == {l2} - {ignore} '''
Expand All @@ -31,14 +32,6 @@ def assertListEq(self, l1, l2, ignore):
print("l1=%r\nl2=%r\nignore=%r" % (l1, l2, ignore), file=sys.stderr)
self.fail("%r missing" % missing.pop())

def assertHasattr(self, obj, attr, ignore):
''' succeed iff hasattr(obj,attr) or attr in ignore. '''
if attr in ignore: return
if not hasattr(obj, attr): print("???", attr)
self.assertTrue(hasattr(obj, attr),
'expected hasattr(%r, %r)' % (obj, attr))


def assertHaskey(self, obj, key, ignore):
''' succeed iff key in obj or key in ignore. '''
if key in ignore: return
Expand Down Expand Up @@ -86,7 +79,7 @@ def ismethod(oclass, obj, name):
for name, value in dict.items():
if name in ignore:
continue
self.assertHasattr(module, name, ignore)
self.assertHasAttr(module, name, ignore)
py_item = getattr(module, name)
if isinstance(value, pyclbr.Function):
self.assertIsInstance(py_item, (FunctionType, BuiltinFunctionType))
Expand Down
21 changes: 2 additions & 19 deletions Lib/test/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import types

from test.support import captured_stderr, cpython_only
from test.support.testcase import ExtraAssertions
from test.typinganndata import ann_module695, mod_generics_cache, _typed_dict_helper


Expand All @@ -55,21 +56,7 @@
CANNOT_SUBCLASS_INSTANCE = 'Cannot subclass an instance of %s'


class BaseTestCase(TestCase):

def assertIsSubclass(self, cls, class_or_tuple, msg=None):
if not issubclass(cls, class_or_tuple):
message = '%r is not a subclass of %r' % (cls, class_or_tuple)
if msg is not None:
message += ' : %s' % msg
raise self.failureException(message)

def assertNotIsSubclass(self, cls, class_or_tuple, msg=None):
if issubclass(cls, class_or_tuple):
message = '%r is a subclass of %r' % (cls, class_or_tuple)
if msg is not None:
message += ' : %s' % msg
raise self.failureException(message)
class BaseTestCase(TestCase, ExtraAssertions):

def clear_caches(self):
for f in typing._cleanups:
Expand Down Expand Up @@ -1051,10 +1038,6 @@ class Gen[*Ts]: ...

class TypeVarTupleTests(BaseTestCase):

def assertEndsWith(self, string, tail):
if not string.endswith(tail):
self.fail(f"String {string!r} does not end with {tail!r}")

def test_name(self):
Ts = TypeVarTuple('Ts')
self.assertEqual(Ts.__name__, 'Ts')
Expand Down
7 changes: 2 additions & 5 deletions Lib/test/test_venv.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
requires_resource, copy_python_src_ignore)
from test.support.os_helper import (can_symlink, EnvironmentVarGuard, rmtree,
TESTFN, FakePath)
from test.support.testcase import ExtraAssertions
import unittest
import venv
from unittest.mock import patch, Mock
Expand Down Expand Up @@ -58,7 +59,7 @@ def check_output(cmd, encoding=None):
p.returncode, cmd, out, err)
return out, err

class BaseTest(unittest.TestCase):
class BaseTest(unittest.TestCase, ExtraAssertions):
"""Base class for venv tests."""
maxDiff = 80 * 50

Expand Down Expand Up @@ -98,10 +99,6 @@ def get_text_file_contents(self, *args, encoding='utf-8'):
result = f.read()
return result

def assertEndsWith(self, string, tail):
if not string.endswith(tail):
self.fail(f"String {string!r} does not end with {tail!r}")

class BasicTest(BaseTest):
"""Test venv module functionality."""

Expand Down
Loading