|
| 1 | +import abc |
1 | 2 | import functools |
2 | 3 | import sys |
3 | 4 | import types |
@@ -98,6 +99,22 @@ def test_loadTestsFromTestCase__from_FunctionTestCase(self): |
98 | 99 | self.assertIsInstance(suite, loader.suiteClass) |
99 | 100 | self.assertEqual(list(suite), []) |
100 | 101 |
|
| 102 | + # "Do not load any tests from a TestCase-derived class that is an abstract |
| 103 | + # base class." |
| 104 | + def test_loadTestsFromTestCase__from_abc_TestCase(self): |
| 105 | + class FooBase(unittest.TestCase, metaclass=abc.ABCMeta): |
| 106 | + @abc.abstractmethod |
| 107 | + def test(self): ... |
| 108 | + class Foo(FooBase): |
| 109 | + def test(self): pass |
| 110 | + |
| 111 | + empty_suite = unittest.TestSuite() |
| 112 | + |
| 113 | + loader = unittest.TestLoader() |
| 114 | + suite = loader.loadTestsFromTestCase(Foo) |
| 115 | + self.assertEqual(loader.loadTestsFromTestCase(FooBase), empty_suite) |
| 116 | + self.assertEqual(list(suite), [Foo('test')]) |
| 117 | + |
101 | 118 | ################################################################ |
102 | 119 | ### /Tests for TestLoader.loadTestsFromTestCase |
103 | 120 |
|
@@ -252,6 +269,24 @@ def load_tests(loader, tests, pattern): |
252 | 269 |
|
253 | 270 | self.assertRaisesRegex(TypeError, "some failure", test.m) |
254 | 271 |
|
| 272 | + # Check that loadTestsFromModule skips abstract base classes derived from |
| 273 | + # TestCase, which can't be instantiated. |
| 274 | + def test_loadTestsFromModule__skip_abc_TestCase(self): |
| 275 | + m = types.ModuleType('m') |
| 276 | + class MyTestCaseBase(unittest.TestCase, metaclass=abc.ABCMeta): |
| 277 | + @abc.abstractmethod |
| 278 | + def test(self): |
| 279 | + ... |
| 280 | + class MyTestCase(MyTestCaseBase): |
| 281 | + def test(self): |
| 282 | + pass |
| 283 | + m.testcase_1 = MyTestCaseBase |
| 284 | + m.testcase_2 = MyTestCase |
| 285 | + loader = unittest.TestLoader() |
| 286 | + suite = loader.loadTestsFromModule(m) |
| 287 | + expected = [loader.suiteClass([MyTestCase('test')])] |
| 288 | + self.assertEqual(list(suite), expected) |
| 289 | + |
255 | 290 | ################################################################ |
256 | 291 | ### /Tests for TestLoader.loadTestsFromModule() |
257 | 292 |
|
@@ -1052,6 +1087,22 @@ def test_loadTestsFromNames__module_not_loaded(self): |
1052 | 1087 | if module_name in sys.modules: |
1053 | 1088 | del sys.modules[module_name] |
1054 | 1089 |
|
| 1090 | + # "The specifier should not refer to a test method in a TestCase-derived |
| 1091 | + # subclass that is an abstract base class" |
| 1092 | + def test_loadTestsFromNames__testmethod_in_abc_TestCase(self): |
| 1093 | + m = types.ModuleType('m') |
| 1094 | + class Foo(unittest.TestCase, metaclass=abc.ABCMeta): |
| 1095 | + @abc.abstractmethod |
| 1096 | + def test_1(self): ... |
| 1097 | + def test_2(self): pass |
| 1098 | + m.Foo = Foo |
| 1099 | + |
| 1100 | + loader = unittest.TestLoader() |
| 1101 | + for name in 'Foo.test_1', 'Foo.test_2': |
| 1102 | + with self.subTest(name=name), self.assertRaisesRegex(TypeError, |
| 1103 | + "Cannot instantiate abstract test case Foo"): |
| 1104 | + loader.loadTestsFromNames([name], m) |
| 1105 | + |
1055 | 1106 | ################################################################ |
1056 | 1107 | ### /Tests for TestLoader.loadTestsFromNames() |
1057 | 1108 |
|
|
0 commit comments