mirror of
https://github.com/python/cpython.git
synced 2025-08-31 05:58:33 +00:00
gh-71339: Add additional assertion methods for unittest (GH-128707)
Add the following methods: * assertHasAttr() and assertNotHasAttr() * assertIsSubclass() and assertNotIsSubclass() * assertStartsWith() and assertNotStartsWith() * assertEndsWith() and assertNotEndsWith() Also improve error messages for assertIsInstance() and assertNotIsInstance().
This commit is contained in:
parent
41f73501ec
commit
06cad77a5b
20 changed files with 555 additions and 100 deletions
|
@ -883,6 +883,12 @@ Test cases
|
|||
| :meth:`assertNotIsInstance(a, b) | ``not isinstance(a, b)`` | 3.2 |
|
||||
| <TestCase.assertNotIsInstance>` | | |
|
||||
+-----------------------------------------+-----------------------------+---------------+
|
||||
| :meth:`assertIsSubclass(a, b) | ``issubclass(a, b)`` | 3.14 |
|
||||
| <TestCase.assertIsSubclass>` | | |
|
||||
+-----------------------------------------+-----------------------------+---------------+
|
||||
| :meth:`assertNotIsSubclass(a, b) | ``not issubclass(a, b)`` | 3.14 |
|
||||
| <TestCase.assertNotIsSubclass>` | | |
|
||||
+-----------------------------------------+-----------------------------+---------------+
|
||||
|
||||
All the assert methods accept a *msg* argument that, if specified, is used
|
||||
as the error message on failure (see also :data:`longMessage`).
|
||||
|
@ -961,6 +967,15 @@ Test cases
|
|||
.. versionadded:: 3.2
|
||||
|
||||
|
||||
.. method:: assertIsSubclass(cls, superclass, msg=None)
|
||||
assertNotIsSubclass(cls, superclass, msg=None)
|
||||
|
||||
Test that *cls* is (or is not) a subclass of *superclass* (which can be a
|
||||
class or a tuple of classes, as supported by :func:`issubclass`).
|
||||
To check for the exact type, use :func:`assertIs(cls, superclass) <assertIs>`.
|
||||
|
||||
.. versionadded:: next
|
||||
|
||||
|
||||
It is also possible to check the production of exceptions, warnings, and
|
||||
log messages using the following methods:
|
||||
|
@ -1210,6 +1225,24 @@ Test cases
|
|||
| <TestCase.assertCountEqual>` | elements in the same number, | |
|
||||
| | regardless of their order. | |
|
||||
+---------------------------------------+--------------------------------+--------------+
|
||||
| :meth:`assertStartsWith(a, b) | ``a.startswith(b)`` | 3.14 |
|
||||
| <TestCase.assertStartsWith>` | | |
|
||||
+---------------------------------------+--------------------------------+--------------+
|
||||
| :meth:`assertNotStartsWith(a, b) | ``not a.startswith(b)`` | 3.14 |
|
||||
| <TestCase.assertNotStartsWith>` | | |
|
||||
+---------------------------------------+--------------------------------+--------------+
|
||||
| :meth:`assertEndsWith(a, b) | ``a.endswith(b)`` | 3.14 |
|
||||
| <TestCase.assertEndsWith>` | | |
|
||||
+---------------------------------------+--------------------------------+--------------+
|
||||
| :meth:`assertNotEndsWith(a, b) | ``not a.endswith(b)`` | 3.14 |
|
||||
| <TestCase.assertNotEndsWith>` | | |
|
||||
+---------------------------------------+--------------------------------+--------------+
|
||||
| :meth:`assertHasAttr(a, b) | ``hastattr(a, b)`` | 3.14 |
|
||||
| <TestCase.assertHasAttr>` | | |
|
||||
+---------------------------------------+--------------------------------+--------------+
|
||||
| :meth:`assertNotHasAttr(a, b) | ``not hastattr(a, b)`` | 3.14 |
|
||||
| <TestCase.assertNotHasAttr>` | | |
|
||||
+---------------------------------------+--------------------------------+--------------+
|
||||
|
||||
|
||||
.. method:: assertAlmostEqual(first, second, places=7, msg=None, delta=None)
|
||||
|
@ -1279,6 +1312,34 @@ Test cases
|
|||
.. versionadded:: 3.2
|
||||
|
||||
|
||||
.. method:: assertStartsWith(s, prefix, msg=None)
|
||||
.. method:: assertNotStartsWith(s, prefix, msg=None)
|
||||
|
||||
Test that the Unicode or byte string *s* starts (or does not start)
|
||||
with a *prefix*.
|
||||
*prefix* can also be a tuple of strings to try.
|
||||
|
||||
.. versionadded:: next
|
||||
|
||||
|
||||
.. method:: assertEndsWith(s, suffix, msg=None)
|
||||
.. method:: assertNotEndsWith(s, suffix, msg=None)
|
||||
|
||||
Test that the Unicode or byte string *s* ends (or does not end)
|
||||
with a *suffix*.
|
||||
*suffix* can also be a tuple of strings to try.
|
||||
|
||||
.. versionadded:: next
|
||||
|
||||
|
||||
.. method:: assertHasAttr(obj, name, msg=None)
|
||||
.. method:: assertNotHasAttr(obj, name, msg=None)
|
||||
|
||||
Test that the object *obj* has (or has not) an attribute *name*.
|
||||
|
||||
.. versionadded:: next
|
||||
|
||||
|
||||
.. _type-specific-methods:
|
||||
|
||||
The :meth:`assertEqual` method dispatches the equality check for objects of
|
||||
|
|
|
@ -670,6 +670,23 @@ unittest
|
|||
directory again. It was removed in Python 3.11.
|
||||
(Contributed by Jacob Walls in :gh:`80958`.)
|
||||
|
||||
* A number of new methods were added in the :class:`~unittest.TestCase` class
|
||||
that provide more specialized tests.
|
||||
|
||||
- :meth:`~unittest.TestCase.assertHasAttr` and
|
||||
:meth:`~unittest.TestCase.assertNotHasAttr` check whether the object
|
||||
has a particular attribute.
|
||||
- :meth:`~unittest.TestCase.assertIsSubclass` and
|
||||
:meth:`~unittest.TestCase.assertNotIsSubclass` check whether the object
|
||||
is a subclass of a particular class, or of one of a tuple of classes.
|
||||
- :meth:`~unittest.TestCase.assertStartsWith`,
|
||||
:meth:`~unittest.TestCase.assertNotStartsWith`,
|
||||
:meth:`~unittest.TestCase.assertEndsWith` and
|
||||
:meth:`~unittest.TestCase.assertNotEndsWith` check whether the Unicode
|
||||
or byte string starts or ends with particular string(s).
|
||||
|
||||
(Contributed by Serhiy Storchaka in :gh:`71339`.)
|
||||
|
||||
|
||||
urllib
|
||||
------
|
||||
|
|
|
@ -405,14 +405,6 @@ class OperatorsTest(unittest.TestCase):
|
|||
|
||||
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))
|
||||
|
||||
def test_python_dicts(self):
|
||||
# Testing Python subclass of dict...
|
||||
self.assertTrue(issubclass(dict, dict))
|
||||
|
|
|
@ -280,11 +280,6 @@ class DebuggerTests(unittest.TestCase):
|
|||
|
||||
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:
|
||||
|
|
|
@ -43,12 +43,6 @@ class FunctionalAPIBase(util.DiskSetup):
|
|||
with self.subTest(path_parts=path_parts):
|
||||
yield path_parts
|
||||
|
||||
def assertEndsWith(self, string, suffix):
|
||||
"""Assert that `string` ends with `suffix`.
|
||||
|
||||
Used to ignore an architecture-specific UTF-16 byte-order mark."""
|
||||
self.assertEqual(string[-len(suffix) :], suffix)
|
||||
|
||||
def test_read_text(self):
|
||||
self.assertEqual(
|
||||
resources.read_text(self.anchor01, 'utf-8.file'),
|
||||
|
|
|
@ -31,14 +31,6 @@ class PyclbrTest(TestCase):
|
|||
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
|
||||
|
@ -86,7 +78,7 @@ class PyclbrTest(TestCase):
|
|||
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))
|
||||
|
|
|
@ -59,20 +59,6 @@ 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)
|
||||
|
||||
def clear_caches(self):
|
||||
for f in typing._cleanups:
|
||||
f()
|
||||
|
@ -1252,10 +1238,6 @@ class UnpackTests(BaseTestCase):
|
|||
|
||||
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')
|
||||
|
|
|
@ -10,6 +10,7 @@ import weakref
|
|||
import inspect
|
||||
import types
|
||||
|
||||
from collections import UserString
|
||||
from copy import deepcopy
|
||||
from test import support
|
||||
|
||||
|
@ -54,6 +55,10 @@ class Test(object):
|
|||
self.events.append('tearDown')
|
||||
|
||||
|
||||
class List(list):
|
||||
pass
|
||||
|
||||
|
||||
class Test_TestCase(unittest.TestCase, TestEquality, TestHashing):
|
||||
|
||||
### Set up attributes used by inherited tests
|
||||
|
@ -85,7 +90,7 @@ class Test_TestCase(unittest.TestCase, TestEquality, TestHashing):
|
|||
def runTest(self): raise MyException()
|
||||
def test(self): pass
|
||||
|
||||
self.assertEqual(Test().id()[-13:], '.Test.runTest')
|
||||
self.assertEndsWith(Test().id(), '.Test.runTest')
|
||||
|
||||
# test that TestCase can be instantiated with no args
|
||||
# primarily for use at the interactive interpreter
|
||||
|
@ -106,7 +111,7 @@ class Test_TestCase(unittest.TestCase, TestEquality, TestHashing):
|
|||
def runTest(self): raise MyException()
|
||||
def test(self): pass
|
||||
|
||||
self.assertEqual(Test('test').id()[-10:], '.Test.test')
|
||||
self.assertEndsWith(Test('test').id(), '.Test.test')
|
||||
|
||||
# "class TestCase([methodName])"
|
||||
# ...
|
||||
|
@ -700,16 +705,120 @@ class Test_TestCase(unittest.TestCase, TestEquality, TestHashing):
|
|||
self.assertRaises(self.failureException, self.assertIsNot, thing, thing)
|
||||
|
||||
def testAssertIsInstance(self):
|
||||
thing = []
|
||||
thing = List()
|
||||
self.assertIsInstance(thing, list)
|
||||
self.assertRaises(self.failureException, self.assertIsInstance,
|
||||
thing, dict)
|
||||
self.assertIsInstance(thing, (int, list))
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertIsInstance(thing, int)
|
||||
self.assertEqual(str(cm.exception),
|
||||
"[] is not an instance of <class 'int'>")
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertIsInstance(thing, (int, float))
|
||||
self.assertEqual(str(cm.exception),
|
||||
"[] is not an instance of any of (<class 'int'>, <class 'float'>)")
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertIsInstance(thing, int, 'ababahalamaha')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertIsInstance(thing, int, msg='ababahalamaha')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
|
||||
def testAssertNotIsInstance(self):
|
||||
thing = []
|
||||
self.assertNotIsInstance(thing, dict)
|
||||
self.assertRaises(self.failureException, self.assertNotIsInstance,
|
||||
thing, list)
|
||||
thing = List()
|
||||
self.assertNotIsInstance(thing, int)
|
||||
self.assertNotIsInstance(thing, (int, float))
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotIsInstance(thing, list)
|
||||
self.assertEqual(str(cm.exception),
|
||||
"[] is an instance of <class 'list'>")
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotIsInstance(thing, (int, list))
|
||||
self.assertEqual(str(cm.exception),
|
||||
"[] is an instance of <class 'list'>")
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotIsInstance(thing, list, 'ababahalamaha')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotIsInstance(thing, list, msg='ababahalamaha')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
|
||||
def testAssertIsSubclass(self):
|
||||
self.assertIsSubclass(List, list)
|
||||
self.assertIsSubclass(List, (int, list))
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertIsSubclass(List, int)
|
||||
self.assertEqual(str(cm.exception),
|
||||
f"{List!r} is not a subclass of <class 'int'>")
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertIsSubclass(List, (int, float))
|
||||
self.assertEqual(str(cm.exception),
|
||||
f"{List!r} is not a subclass of any of (<class 'int'>, <class 'float'>)")
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertIsSubclass(1, int)
|
||||
self.assertEqual(str(cm.exception), "1 is not a class")
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertIsSubclass(List, int, 'ababahalamaha')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertIsSubclass(List, int, msg='ababahalamaha')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
|
||||
def testAssertNotIsSubclass(self):
|
||||
self.assertNotIsSubclass(List, int)
|
||||
self.assertNotIsSubclass(List, (int, float))
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotIsSubclass(List, list)
|
||||
self.assertEqual(str(cm.exception),
|
||||
f"{List!r} is a subclass of <class 'list'>")
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotIsSubclass(List, (int, list))
|
||||
self.assertEqual(str(cm.exception),
|
||||
f"{List!r} is a subclass of <class 'list'>")
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotIsSubclass(1, int)
|
||||
self.assertEqual(str(cm.exception), "1 is not a class")
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotIsSubclass(List, list, 'ababahalamaha')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotIsSubclass(List, list, msg='ababahalamaha')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
|
||||
def testAssertHasAttr(self):
|
||||
a = List()
|
||||
a.x = 1
|
||||
self.assertHasAttr(a, 'x')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertHasAttr(a, 'y')
|
||||
self.assertEqual(str(cm.exception),
|
||||
"List instance has no attribute 'y'")
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertHasAttr(a, 'y', 'ababahalamaha')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertHasAttr(a, 'y', msg='ababahalamaha')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
|
||||
def testAssertNotHasAttr(self):
|
||||
a = List()
|
||||
a.x = 1
|
||||
self.assertNotHasAttr(a, 'y')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotHasAttr(a, 'x')
|
||||
self.assertEqual(str(cm.exception),
|
||||
"List instance has unexpected attribute 'x'")
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotHasAttr(a, 'x', 'ababahalamaha')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotHasAttr(a, 'x', msg='ababahalamaha')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
|
||||
def testAssertIn(self):
|
||||
animals = {'monkey': 'banana', 'cow': 'grass', 'seal': 'fish'}
|
||||
|
@ -1864,6 +1973,186 @@ test case
|
|||
pass
|
||||
self.assertIsNone(value)
|
||||
|
||||
def testAssertStartswith(self):
|
||||
self.assertStartsWith('ababahalamaha', 'ababa')
|
||||
self.assertStartsWith('ababahalamaha', ('x', 'ababa', 'y'))
|
||||
self.assertStartsWith(UserString('ababahalamaha'), 'ababa')
|
||||
self.assertStartsWith(UserString('ababahalamaha'), ('x', 'ababa', 'y'))
|
||||
self.assertStartsWith(bytearray(b'ababahalamaha'), b'ababa')
|
||||
self.assertStartsWith(bytearray(b'ababahalamaha'), (b'x', b'ababa', b'y'))
|
||||
self.assertStartsWith(b'ababahalamaha', bytearray(b'ababa'))
|
||||
self.assertStartsWith(b'ababahalamaha',
|
||||
(bytearray(b'x'), bytearray(b'ababa'), bytearray(b'y')))
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertStartsWith('ababahalamaha', 'amaha')
|
||||
self.assertEqual(str(cm.exception),
|
||||
"'ababahalamaha' doesn't start with 'amaha'")
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertStartsWith('ababahalamaha', ('x', 'y'))
|
||||
self.assertEqual(str(cm.exception),
|
||||
"'ababahalamaha' doesn't start with any of ('x', 'y')")
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertStartsWith(b'ababahalamaha', 'ababa')
|
||||
self.assertEqual(str(cm.exception), 'Expected str, not bytes')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertStartsWith(b'ababahalamaha', ('amaha', 'ababa'))
|
||||
self.assertEqual(str(cm.exception), 'Expected str, not bytes')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertStartsWith([], 'ababa')
|
||||
self.assertEqual(str(cm.exception), 'Expected str, not list')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertStartsWith('ababahalamaha', b'ababa')
|
||||
self.assertEqual(str(cm.exception), 'Expected bytes, not str')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertStartsWith('ababahalamaha', (b'amaha', b'ababa'))
|
||||
self.assertEqual(str(cm.exception), 'Expected bytes, not str')
|
||||
with self.assertRaises(TypeError):
|
||||
self.assertStartsWith('ababahalamaha', ord('a'))
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertStartsWith('ababahalamaha', 'amaha', 'abracadabra')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertStartsWith('ababahalamaha', 'amaha', msg='abracadabra')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
|
||||
def testAssertNotStartswith(self):
|
||||
self.assertNotStartsWith('ababahalamaha', 'amaha')
|
||||
self.assertNotStartsWith('ababahalamaha', ('x', 'amaha', 'y'))
|
||||
self.assertNotStartsWith(UserString('ababahalamaha'), 'amaha')
|
||||
self.assertNotStartsWith(UserString('ababahalamaha'), ('x', 'amaha', 'y'))
|
||||
self.assertNotStartsWith(bytearray(b'ababahalamaha'), b'amaha')
|
||||
self.assertNotStartsWith(bytearray(b'ababahalamaha'), (b'x', b'amaha', b'y'))
|
||||
self.assertNotStartsWith(b'ababahalamaha', bytearray(b'amaha'))
|
||||
self.assertNotStartsWith(b'ababahalamaha',
|
||||
(bytearray(b'x'), bytearray(b'amaha'), bytearray(b'y')))
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotStartsWith('ababahalamaha', 'ababa')
|
||||
self.assertEqual(str(cm.exception),
|
||||
"'ababahalamaha' starts with 'ababa'")
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotStartsWith('ababahalamaha', ('x', 'ababa', 'y'))
|
||||
self.assertEqual(str(cm.exception),
|
||||
"'ababahalamaha' starts with 'ababa'")
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotStartsWith(b'ababahalamaha', 'ababa')
|
||||
self.assertEqual(str(cm.exception), 'Expected str, not bytes')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotStartsWith(b'ababahalamaha', ('amaha', 'ababa'))
|
||||
self.assertEqual(str(cm.exception), 'Expected str, not bytes')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotStartsWith([], 'ababa')
|
||||
self.assertEqual(str(cm.exception), 'Expected str, not list')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotStartsWith('ababahalamaha', b'ababa')
|
||||
self.assertEqual(str(cm.exception), 'Expected bytes, not str')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotStartsWith('ababahalamaha', (b'amaha', b'ababa'))
|
||||
self.assertEqual(str(cm.exception), 'Expected bytes, not str')
|
||||
with self.assertRaises(TypeError):
|
||||
self.assertNotStartsWith('ababahalamaha', ord('a'))
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotStartsWith('ababahalamaha', 'ababa', 'abracadabra')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotStartsWith('ababahalamaha', 'ababa', msg='abracadabra')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
|
||||
def testAssertEndswith(self):
|
||||
self.assertEndsWith('ababahalamaha', 'amaha')
|
||||
self.assertEndsWith('ababahalamaha', ('x', 'amaha', 'y'))
|
||||
self.assertEndsWith(UserString('ababahalamaha'), 'amaha')
|
||||
self.assertEndsWith(UserString('ababahalamaha'), ('x', 'amaha', 'y'))
|
||||
self.assertEndsWith(bytearray(b'ababahalamaha'), b'amaha')
|
||||
self.assertEndsWith(bytearray(b'ababahalamaha'), (b'x', b'amaha', b'y'))
|
||||
self.assertEndsWith(b'ababahalamaha', bytearray(b'amaha'))
|
||||
self.assertEndsWith(b'ababahalamaha',
|
||||
(bytearray(b'x'), bytearray(b'amaha'), bytearray(b'y')))
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertEndsWith('ababahalamaha', 'ababa')
|
||||
self.assertEqual(str(cm.exception),
|
||||
"'ababahalamaha' doesn't end with 'ababa'")
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertEndsWith('ababahalamaha', ('x', 'y'))
|
||||
self.assertEqual(str(cm.exception),
|
||||
"'ababahalamaha' doesn't end with any of ('x', 'y')")
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertEndsWith(b'ababahalamaha', 'amaha')
|
||||
self.assertEqual(str(cm.exception), 'Expected str, not bytes')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertEndsWith(b'ababahalamaha', ('ababa', 'amaha'))
|
||||
self.assertEqual(str(cm.exception), 'Expected str, not bytes')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertEndsWith([], 'amaha')
|
||||
self.assertEqual(str(cm.exception), 'Expected str, not list')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertEndsWith('ababahalamaha', b'amaha')
|
||||
self.assertEqual(str(cm.exception), 'Expected bytes, not str')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertEndsWith('ababahalamaha', (b'ababa', b'amaha'))
|
||||
self.assertEqual(str(cm.exception), 'Expected bytes, not str')
|
||||
with self.assertRaises(TypeError):
|
||||
self.assertEndsWith('ababahalamaha', ord('a'))
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertEndsWith('ababahalamaha', 'ababa', 'abracadabra')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertEndsWith('ababahalamaha', 'ababa', msg='abracadabra')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
|
||||
def testAssertNotEndswith(self):
|
||||
self.assertNotEndsWith('ababahalamaha', 'ababa')
|
||||
self.assertNotEndsWith('ababahalamaha', ('x', 'ababa', 'y'))
|
||||
self.assertNotEndsWith(UserString('ababahalamaha'), 'ababa')
|
||||
self.assertNotEndsWith(UserString('ababahalamaha'), ('x', 'ababa', 'y'))
|
||||
self.assertNotEndsWith(bytearray(b'ababahalamaha'), b'ababa')
|
||||
self.assertNotEndsWith(bytearray(b'ababahalamaha'), (b'x', b'ababa', b'y'))
|
||||
self.assertNotEndsWith(b'ababahalamaha', bytearray(b'ababa'))
|
||||
self.assertNotEndsWith(b'ababahalamaha',
|
||||
(bytearray(b'x'), bytearray(b'ababa'), bytearray(b'y')))
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotEndsWith('ababahalamaha', 'amaha')
|
||||
self.assertEqual(str(cm.exception),
|
||||
"'ababahalamaha' ends with 'amaha'")
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotEndsWith('ababahalamaha', ('x', 'amaha', 'y'))
|
||||
self.assertEqual(str(cm.exception),
|
||||
"'ababahalamaha' ends with 'amaha'")
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotEndsWith(b'ababahalamaha', 'amaha')
|
||||
self.assertEqual(str(cm.exception), 'Expected str, not bytes')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotEndsWith(b'ababahalamaha', ('ababa', 'amaha'))
|
||||
self.assertEqual(str(cm.exception), 'Expected str, not bytes')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotEndsWith([], 'amaha')
|
||||
self.assertEqual(str(cm.exception), 'Expected str, not list')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotEndsWith('ababahalamaha', b'amaha')
|
||||
self.assertEqual(str(cm.exception), 'Expected bytes, not str')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotEndsWith('ababahalamaha', (b'ababa', b'amaha'))
|
||||
self.assertEqual(str(cm.exception), 'Expected bytes, not str')
|
||||
with self.assertRaises(TypeError):
|
||||
self.assertNotEndsWith('ababahalamaha', ord('a'))
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotEndsWith('ababahalamaha', 'amaha', 'abracadabra')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotEndsWith('ababahalamaha', 'amaha', msg='abracadabra')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
|
||||
def testDeprecatedFailMethods(self):
|
||||
"""Test that the deprecated fail* methods get removed in 3.12"""
|
||||
deprecated_names = [
|
||||
|
|
|
@ -76,7 +76,7 @@ class Test_TestLoader(unittest.TestCase):
|
|||
|
||||
loader = unittest.TestLoader()
|
||||
# This has to be false for the test to succeed
|
||||
self.assertFalse('runTest'.startswith(loader.testMethodPrefix))
|
||||
self.assertNotStartsWith('runTest', loader.testMethodPrefix)
|
||||
|
||||
suite = loader.loadTestsFromTestCase(Foo)
|
||||
self.assertIsInstance(suite, loader.suiteClass)
|
||||
|
|
|
@ -128,14 +128,14 @@ class Test_TestProgram(unittest.TestCase):
|
|||
argv=["foobar"],
|
||||
testRunner=unittest.TextTestRunner(stream=stream),
|
||||
testLoader=self.TestLoader(self.FooBar))
|
||||
self.assertTrue(hasattr(program, 'result'))
|
||||
self.assertHasAttr(program, 'result')
|
||||
out = stream.getvalue()
|
||||
self.assertIn('\nFAIL: testFail ', out)
|
||||
self.assertIn('\nERROR: testError ', out)
|
||||
self.assertIn('\nUNEXPECTED SUCCESS: testUnexpectedSuccess ', out)
|
||||
expected = ('\n\nFAILED (failures=1, errors=1, skipped=1, '
|
||||
'expected failures=1, unexpected successes=1)\n')
|
||||
self.assertTrue(out.endswith(expected))
|
||||
self.assertEndsWith(out, expected)
|
||||
|
||||
@force_not_colorized
|
||||
def test_Exit(self):
|
||||
|
@ -153,7 +153,7 @@ class Test_TestProgram(unittest.TestCase):
|
|||
self.assertIn('\nUNEXPECTED SUCCESS: testUnexpectedSuccess ', out)
|
||||
expected = ('\n\nFAILED (failures=1, errors=1, skipped=1, '
|
||||
'expected failures=1, unexpected successes=1)\n')
|
||||
self.assertTrue(out.endswith(expected))
|
||||
self.assertEndsWith(out, expected)
|
||||
|
||||
@force_not_colorized
|
||||
def test_ExitAsDefault(self):
|
||||
|
@ -169,7 +169,7 @@ class Test_TestProgram(unittest.TestCase):
|
|||
self.assertIn('\nUNEXPECTED SUCCESS: testUnexpectedSuccess ', out)
|
||||
expected = ('\n\nFAILED (failures=1, errors=1, skipped=1, '
|
||||
'expected failures=1, unexpected successes=1)\n')
|
||||
self.assertTrue(out.endswith(expected))
|
||||
self.assertEndsWith(out, expected)
|
||||
|
||||
@force_not_colorized
|
||||
def test_ExitSkippedSuite(self):
|
||||
|
@ -182,7 +182,7 @@ class Test_TestProgram(unittest.TestCase):
|
|||
self.assertEqual(cm.exception.code, 0)
|
||||
out = stream.getvalue()
|
||||
expected = '\n\nOK (skipped=1)\n'
|
||||
self.assertTrue(out.endswith(expected))
|
||||
self.assertEndsWith(out, expected)
|
||||
|
||||
@force_not_colorized
|
||||
def test_ExitEmptySuite(self):
|
||||
|
|
|
@ -462,7 +462,7 @@ class Test_TestResult(unittest.TestCase):
|
|||
self.assertTrue(result.failfast)
|
||||
result = runner.run(test)
|
||||
stream.flush()
|
||||
self.assertTrue(stream.getvalue().endswith('\n\nOK\n'))
|
||||
self.assertEndsWith(stream.getvalue(), '\n\nOK\n')
|
||||
|
||||
|
||||
class Test_TextTestResult(unittest.TestCase):
|
||||
|
|
|
@ -586,16 +586,16 @@ class AsyncMagicMethods(unittest.TestCase):
|
|||
|
||||
def test_magicmock_has_async_magic_methods(self):
|
||||
m_mock = MagicMock()
|
||||
self.assertTrue(hasattr(m_mock, "__aenter__"))
|
||||
self.assertTrue(hasattr(m_mock, "__aexit__"))
|
||||
self.assertTrue(hasattr(m_mock, "__anext__"))
|
||||
self.assertHasAttr(m_mock, "__aenter__")
|
||||
self.assertHasAttr(m_mock, "__aexit__")
|
||||
self.assertHasAttr(m_mock, "__anext__")
|
||||
|
||||
def test_asyncmock_has_sync_magic_methods(self):
|
||||
a_mock = AsyncMock()
|
||||
self.assertTrue(hasattr(a_mock, "__enter__"))
|
||||
self.assertTrue(hasattr(a_mock, "__exit__"))
|
||||
self.assertTrue(hasattr(a_mock, "__next__"))
|
||||
self.assertTrue(hasattr(a_mock, "__len__"))
|
||||
self.assertHasAttr(a_mock, "__enter__")
|
||||
self.assertHasAttr(a_mock, "__exit__")
|
||||
self.assertHasAttr(a_mock, "__next__")
|
||||
self.assertHasAttr(a_mock, "__len__")
|
||||
|
||||
def test_magic_methods_are_async_functions(self):
|
||||
m_mock = MagicMock()
|
||||
|
|
|
@ -23,21 +23,21 @@ class TestCallable(unittest.TestCase):
|
|||
def test_non_callable(self):
|
||||
for mock in NonCallableMagicMock(), NonCallableMock():
|
||||
self.assertRaises(TypeError, mock)
|
||||
self.assertFalse(hasattr(mock, '__call__'))
|
||||
self.assertNotHasAttr(mock, '__call__')
|
||||
self.assertIn(mock.__class__.__name__, repr(mock))
|
||||
|
||||
|
||||
def test_hierarchy(self):
|
||||
self.assertTrue(issubclass(MagicMock, Mock))
|
||||
self.assertTrue(issubclass(NonCallableMagicMock, NonCallableMock))
|
||||
self.assertIsSubclass(MagicMock, Mock)
|
||||
self.assertIsSubclass(NonCallableMagicMock, NonCallableMock)
|
||||
|
||||
|
||||
def test_attributes(self):
|
||||
one = NonCallableMock()
|
||||
self.assertTrue(issubclass(type(one.one), Mock))
|
||||
self.assertIsSubclass(type(one.one), Mock)
|
||||
|
||||
two = NonCallableMagicMock()
|
||||
self.assertTrue(issubclass(type(two.two), MagicMock))
|
||||
self.assertIsSubclass(type(two.two), MagicMock)
|
||||
|
||||
|
||||
def test_subclasses(self):
|
||||
|
@ -45,13 +45,13 @@ class TestCallable(unittest.TestCase):
|
|||
pass
|
||||
|
||||
one = MockSub()
|
||||
self.assertTrue(issubclass(type(one.one), MockSub))
|
||||
self.assertIsSubclass(type(one.one), MockSub)
|
||||
|
||||
class MagicSub(MagicMock):
|
||||
pass
|
||||
|
||||
two = MagicSub()
|
||||
self.assertTrue(issubclass(type(two.two), MagicSub))
|
||||
self.assertIsSubclass(type(two.two), MagicSub)
|
||||
|
||||
|
||||
def test_patch_spec(self):
|
||||
|
|
|
@ -951,7 +951,7 @@ class SpecSignatureTest(unittest.TestCase):
|
|||
|
||||
proxy = Foo()
|
||||
autospec = create_autospec(proxy)
|
||||
self.assertFalse(hasattr(autospec, '__name__'))
|
||||
self.assertNotHasAttr(autospec, '__name__')
|
||||
|
||||
|
||||
def test_autospec_signature_staticmethod(self):
|
||||
|
|
|
@ -10,13 +10,13 @@ class TestMockingMagicMethods(unittest.TestCase):
|
|||
|
||||
def test_deleting_magic_methods(self):
|
||||
mock = Mock()
|
||||
self.assertFalse(hasattr(mock, '__getitem__'))
|
||||
self.assertNotHasAttr(mock, '__getitem__')
|
||||
|
||||
mock.__getitem__ = Mock()
|
||||
self.assertTrue(hasattr(mock, '__getitem__'))
|
||||
self.assertHasAttr(mock, '__getitem__')
|
||||
|
||||
del mock.__getitem__
|
||||
self.assertFalse(hasattr(mock, '__getitem__'))
|
||||
self.assertNotHasAttr(mock, '__getitem__')
|
||||
|
||||
|
||||
def test_magicmock_del(self):
|
||||
|
@ -252,12 +252,12 @@ class TestMockingMagicMethods(unittest.TestCase):
|
|||
self.assertEqual(list(mock), [1, 2, 3])
|
||||
|
||||
getattr(mock, '__bool__').return_value = False
|
||||
self.assertFalse(hasattr(mock, '__nonzero__'))
|
||||
self.assertNotHasAttr(mock, '__nonzero__')
|
||||
self.assertFalse(bool(mock))
|
||||
|
||||
for entry in _magics:
|
||||
self.assertTrue(hasattr(mock, entry))
|
||||
self.assertFalse(hasattr(mock, '__imaginary__'))
|
||||
self.assertHasAttr(mock, entry)
|
||||
self.assertNotHasAttr(mock, '__imaginary__')
|
||||
|
||||
|
||||
def test_magic_mock_equality(self):
|
||||
|
|
|
@ -2215,13 +2215,13 @@ class MockTest(unittest.TestCase):
|
|||
def test_attribute_deletion(self):
|
||||
for mock in (Mock(), MagicMock(), NonCallableMagicMock(),
|
||||
NonCallableMock()):
|
||||
self.assertTrue(hasattr(mock, 'm'))
|
||||
self.assertHasAttr(mock, 'm')
|
||||
|
||||
del mock.m
|
||||
self.assertFalse(hasattr(mock, 'm'))
|
||||
self.assertNotHasAttr(mock, 'm')
|
||||
|
||||
del mock.f
|
||||
self.assertFalse(hasattr(mock, 'f'))
|
||||
self.assertNotHasAttr(mock, 'f')
|
||||
self.assertRaises(AttributeError, getattr, mock, 'f')
|
||||
|
||||
|
||||
|
@ -2230,18 +2230,18 @@ class MockTest(unittest.TestCase):
|
|||
for mock in (Mock(), MagicMock(), NonCallableMagicMock(),
|
||||
NonCallableMock()):
|
||||
mock.foo = 3
|
||||
self.assertTrue(hasattr(mock, 'foo'))
|
||||
self.assertHasAttr(mock, 'foo')
|
||||
self.assertEqual(mock.foo, 3)
|
||||
|
||||
del mock.foo
|
||||
self.assertFalse(hasattr(mock, 'foo'))
|
||||
self.assertNotHasAttr(mock, 'foo')
|
||||
|
||||
mock.foo = 4
|
||||
self.assertTrue(hasattr(mock, 'foo'))
|
||||
self.assertHasAttr(mock, 'foo')
|
||||
self.assertEqual(mock.foo, 4)
|
||||
|
||||
del mock.foo
|
||||
self.assertFalse(hasattr(mock, 'foo'))
|
||||
self.assertNotHasAttr(mock, 'foo')
|
||||
|
||||
|
||||
def test_mock_raises_when_deleting_nonexistent_attribute(self):
|
||||
|
@ -2259,7 +2259,7 @@ class MockTest(unittest.TestCase):
|
|||
mock.child = True
|
||||
del mock.child
|
||||
mock.reset_mock()
|
||||
self.assertFalse(hasattr(mock, 'child'))
|
||||
self.assertNotHasAttr(mock, 'child')
|
||||
|
||||
|
||||
def test_class_assignable(self):
|
||||
|
|
|
@ -366,7 +366,7 @@ class PatchTest(unittest.TestCase):
|
|||
self.assertEqual(SomeClass.frooble, sentinel.Frooble)
|
||||
|
||||
test()
|
||||
self.assertFalse(hasattr(SomeClass, 'frooble'))
|
||||
self.assertNotHasAttr(SomeClass, 'frooble')
|
||||
|
||||
|
||||
def test_patch_wont_create_by_default(self):
|
||||
|
@ -383,7 +383,7 @@ class PatchTest(unittest.TestCase):
|
|||
@patch.object(SomeClass, 'ord', sentinel.Frooble)
|
||||
def test(): pass
|
||||
test()
|
||||
self.assertFalse(hasattr(SomeClass, 'ord'))
|
||||
self.assertNotHasAttr(SomeClass, 'ord')
|
||||
|
||||
|
||||
def test_patch_builtins_without_create(self):
|
||||
|
@ -1477,7 +1477,7 @@ class PatchTest(unittest.TestCase):
|
|||
finally:
|
||||
patcher.stop()
|
||||
|
||||
self.assertFalse(hasattr(Foo, 'blam'))
|
||||
self.assertNotHasAttr(Foo, 'blam')
|
||||
|
||||
|
||||
def test_patch_multiple_spec_set(self):
|
||||
|
|
|
@ -111,10 +111,6 @@ class BaseTest(unittest.TestCase):
|
|||
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."""
|
||||
|
||||
|
|
|
@ -1321,13 +1321,67 @@ class TestCase(object):
|
|||
"""Same as self.assertTrue(isinstance(obj, cls)), with a nicer
|
||||
default message."""
|
||||
if not isinstance(obj, cls):
|
||||
standardMsg = '%s is not an instance of %r' % (safe_repr(obj), cls)
|
||||
if isinstance(cls, tuple):
|
||||
standardMsg = f'{safe_repr(obj)} is not an instance of any of {cls!r}'
|
||||
else:
|
||||
standardMsg = f'{safe_repr(obj)} is not an instance of {cls!r}'
|
||||
self.fail(self._formatMessage(msg, standardMsg))
|
||||
|
||||
def assertNotIsInstance(self, obj, cls, msg=None):
|
||||
"""Included for symmetry with assertIsInstance."""
|
||||
if isinstance(obj, cls):
|
||||
standardMsg = '%s is an instance of %r' % (safe_repr(obj), cls)
|
||||
if isinstance(cls, tuple):
|
||||
for x in cls:
|
||||
if isinstance(obj, x):
|
||||
cls = x
|
||||
break
|
||||
standardMsg = f'{safe_repr(obj)} is an instance of {cls!r}'
|
||||
self.fail(self._formatMessage(msg, standardMsg))
|
||||
|
||||
def assertIsSubclass(self, cls, superclass, msg=None):
|
||||
try:
|
||||
if issubclass(cls, superclass):
|
||||
return
|
||||
except TypeError:
|
||||
if not isinstance(cls, type):
|
||||
self.fail(self._formatMessage(msg, f'{cls!r} is not a class'))
|
||||
raise
|
||||
if isinstance(superclass, tuple):
|
||||
standardMsg = f'{cls!r} is not a subclass of any of {superclass!r}'
|
||||
else:
|
||||
standardMsg = f'{cls!r} is not a subclass of {superclass!r}'
|
||||
self.fail(self._formatMessage(msg, standardMsg))
|
||||
|
||||
def assertNotIsSubclass(self, cls, superclass, msg=None):
|
||||
try:
|
||||
if not issubclass(cls, superclass):
|
||||
return
|
||||
except TypeError:
|
||||
if not isinstance(cls, type):
|
||||
self.fail(self._formatMessage(msg, f'{cls!r} is not a class'))
|
||||
raise
|
||||
if isinstance(superclass, tuple):
|
||||
for x in superclass:
|
||||
if issubclass(cls, x):
|
||||
superclass = x
|
||||
break
|
||||
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}'
|
||||
else:
|
||||
standardMsg = f'{type(obj).__name__} instance 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}'
|
||||
else:
|
||||
standardMsg = f'{type(obj).__name__} instance has unexpected attribute {name!r}'
|
||||
self.fail(self._formatMessage(msg, standardMsg))
|
||||
|
||||
def assertRaisesRegex(self, expected_exception, expected_regex,
|
||||
|
@ -1391,6 +1445,80 @@ class TestCase(object):
|
|||
msg = self._formatMessage(msg, standardMsg)
|
||||
raise self.failureException(msg)
|
||||
|
||||
def _tail_type_check(self, s, tails, msg):
|
||||
if not isinstance(tails, tuple):
|
||||
tails = (tails,)
|
||||
for tail in tails:
|
||||
if isinstance(tail, str):
|
||||
if not isinstance(s, str):
|
||||
self.fail(self._formatMessage(msg,
|
||||
f'Expected str, not {type(s).__name__}'))
|
||||
elif isinstance(tail, (bytes, bytearray)):
|
||||
if not isinstance(s, (bytes, bytearray)):
|
||||
self.fail(self._formatMessage(msg,
|
||||
f'Expected bytes, not {type(s).__name__}'))
|
||||
|
||||
def assertStartsWith(self, s, prefix, msg=None):
|
||||
try:
|
||||
if s.startswith(prefix):
|
||||
return
|
||||
except (AttributeError, TypeError):
|
||||
self._tail_type_check(s, prefix, msg)
|
||||
raise
|
||||
a = safe_repr(s, short=True)
|
||||
b = safe_repr(prefix)
|
||||
if isinstance(prefix, tuple):
|
||||
standardMsg = f"{a} doesn't start with any of {b}"
|
||||
else:
|
||||
standardMsg = f"{a} doesn't start with {b}"
|
||||
self.fail(self._formatMessage(msg, standardMsg))
|
||||
|
||||
def assertNotStartsWith(self, s, prefix, msg=None):
|
||||
try:
|
||||
if not s.startswith(prefix):
|
||||
return
|
||||
except (AttributeError, TypeError):
|
||||
self._tail_type_check(s, prefix, msg)
|
||||
raise
|
||||
if isinstance(prefix, tuple):
|
||||
for x in prefix:
|
||||
if s.startswith(x):
|
||||
prefix = x
|
||||
break
|
||||
a = safe_repr(s, short=True)
|
||||
b = safe_repr(prefix)
|
||||
self.fail(self._formatMessage(msg, f"{a} starts with {b}"))
|
||||
|
||||
def assertEndsWith(self, s, suffix, msg=None):
|
||||
try:
|
||||
if s.endswith(suffix):
|
||||
return
|
||||
except (AttributeError, TypeError):
|
||||
self._tail_type_check(s, suffix, msg)
|
||||
raise
|
||||
a = safe_repr(s, short=True)
|
||||
b = safe_repr(suffix)
|
||||
if isinstance(suffix, tuple):
|
||||
standardMsg = f"{a} doesn't end with any of {b}"
|
||||
else:
|
||||
standardMsg = f"{a} doesn't end with {b}"
|
||||
self.fail(self._formatMessage(msg, standardMsg))
|
||||
|
||||
def assertNotEndsWith(self, s, suffix, msg=None):
|
||||
try:
|
||||
if not s.endswith(suffix):
|
||||
return
|
||||
except (AttributeError, TypeError):
|
||||
self._tail_type_check(s, suffix, msg)
|
||||
raise
|
||||
if isinstance(suffix, tuple):
|
||||
for x in suffix:
|
||||
if s.endswith(x):
|
||||
suffix = x
|
||||
break
|
||||
a = safe_repr(s, short=True)
|
||||
b = safe_repr(suffix)
|
||||
self.fail(self._formatMessage(msg, f"{a} ends with {b}"))
|
||||
|
||||
|
||||
class FunctionTestCase(TestCase):
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
Add new assertion methods for :mod:`unittest`:
|
||||
:meth:`~unittest.TestCase.assertHasAttr`,
|
||||
:meth:`~unittest.TestCase.assertNotHasAttr`,
|
||||
:meth:`~unittest.TestCase.assertIsSubclass`,
|
||||
:meth:`~unittest.TestCase.assertNotIsSubclass`
|
||||
:meth:`~unittest.TestCase.assertStartsWith`,
|
||||
:meth:`~unittest.TestCase.assertNotStartsWith`,
|
||||
:meth:`~unittest.TestCase.assertEndsWith` and
|
||||
:meth:`~unittest.TestCase.assertNotEndsWith`.
|
Loading…
Add table
Add a link
Reference in a new issue