diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -387,6 +387,12 @@ class ABCTestCase(unittest.TestCase): def validate_abstract_methods(self, abc, *names): + ''' + Makes sure that class that extends from `abc` can be initalized with + the methods provided in `names`. Also makes sure that if any one of + those methods is not on the class, it will raise a TypeError when + creating + ''' methodstubs = dict.fromkeys(names, lambda s, *args: 0) # everything should work will all required methods are present @@ -398,19 +404,50 @@ stubs = methodstubs.copy() del stubs[name] C = type('C', (abc,), stubs) - self.assertRaises(TypeError, C, name) + self.assertRaises( + TypeError, + C, + name, + msg="{} without '{}' method" + " shouldn't initialize".format(abc, name)) - def validate_isinstance(self, abc, name): - stub = lambda s, *args: 0 + def validate_isinstance(self, abc, *names): + ''' + If class provides `name` method, should be instance and subclass of + `abc` + ''' + methodstubs = {'__hash__': None} + methodstubs.update(dict.fromkeys(names, lambda s, *args: 0)) - C = type('C', (object,), {'__hash__': None}) - setattr(C, name, stub) - self.assertIsInstance(C(), abc) - self.assertTrue(issubclass(C, abc)) + C = type('C', (object,), methodstubs) + self.assertIsInstance( + C(), + abc, + msg="Class with {} methods" + " should be instance of {}".format(names, abc)) + self.assertTrue( + issubclass(C, abc), + msg="Class with {} methods " + "should be subclass of {}".format(names, abc)) - C = type('C', (object,), {'__hash__': None}) - self.assertNotIsInstance(C(), abc) - self.assertFalse(issubclass(C, abc)) + for name in names: + stubs = methodstubs.copy() + if name == '__hash__': + stubs[name] = None + else: + del stubs[name] + C = type('C', (object,), stubs) + self.assertNotIsInstance( + C(), + abc, + "Class without {} method " + "shouldn't be instance of ".format(names, abc) + ) + self.assertFalse( + issubclass(C, abc), + "Class without {} method " + "shouldn't be subclass of ".format(names, abc) + ) def validate_comparison(self, instance): ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub'] @@ -944,8 +981,9 @@ self.assertIsInstance(memoryview(b""), Sequence) self.assertTrue(issubclass(memoryview, Sequence)) self.assertTrue(issubclass(str, Sequence)) - self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__', - '__getitem__') + required_methods = ['__contains__', '__iter__', '__len__', '__getitem__'] + self.validate_abstract_methods(Sequence, *required_methods) + self.validate_isinstance(Sequence, *required_methods) def test_ByteString(self): for sample in [bytes, bytearray]: