diff options
author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2023-09-12 14:05:58 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-12 14:05:58 (GMT) |
commit | b4c1cf93c782bb95980420754d2855a903f5aad1 (patch) | |
tree | aea29c0af67c364413903d7b25e8982551f9c8d7 | |
parent | 1e8696133c6c83323e448238924fc94d462e36f0 (diff) | |
download | cpython-b4c1cf93c782bb95980420754d2855a903f5aad1.zip cpython-b4c1cf93c782bb95980420754d2855a903f5aad1.tar.gz cpython-b4c1cf93c782bb95980420754d2855a903f5aad1.tar.bz2 |
[3.11] gh-84867: Do not load tests from TestCase and FunctionTestCase (GH-100497) (GH-109328)
(cherry picked from commit 66d1d7eb067d445f1ade151f4a6db3864dd9109f)
Co-authored-by: Nikita Sobolev <mail@sobolevn.me>
-rw-r--r-- | Lib/unittest/loader.py | 22 | ||||
-rw-r--r-- | Lib/unittest/test/test_loader.py | 29 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2022-12-24-12-50-54.gh-issue-84867.OhaLbU.rst | 2 |
3 files changed, 48 insertions, 5 deletions
diff --git a/Lib/unittest/loader.py b/Lib/unittest/loader.py index 7e6ce2f..f4e3d6e 100644 --- a/Lib/unittest/loader.py +++ b/Lib/unittest/loader.py @@ -87,9 +87,13 @@ class TestLoader(object): raise TypeError("Test cases should not be derived from " "TestSuite. Maybe you meant to derive from " "TestCase?") - testCaseNames = self.getTestCaseNames(testCaseClass) - if not testCaseNames and hasattr(testCaseClass, 'runTest'): - testCaseNames = ['runTest'] + if testCaseClass in (case.TestCase, case.FunctionTestCase): + # We don't load any tests from base types that should not be loaded. + testCaseNames = [] + else: + testCaseNames = self.getTestCaseNames(testCaseClass) + if not testCaseNames and hasattr(testCaseClass, 'runTest'): + testCaseNames = ['runTest'] loaded_suite = self.suiteClass(map(testCaseClass, testCaseNames)) return loaded_suite @@ -120,7 +124,11 @@ class TestLoader(object): tests = [] for name in dir(module): obj = getattr(module, name) - if isinstance(obj, type) and issubclass(obj, case.TestCase): + if ( + isinstance(obj, type) + and issubclass(obj, case.TestCase) + and obj not in (case.TestCase, case.FunctionTestCase) + ): tests.append(self.loadTestsFromTestCase(obj)) load_tests = getattr(module, 'load_tests', None) @@ -189,7 +197,11 @@ class TestLoader(object): if isinstance(obj, types.ModuleType): return self.loadTestsFromModule(obj) - elif isinstance(obj, type) and issubclass(obj, case.TestCase): + elif ( + isinstance(obj, type) + and issubclass(obj, case.TestCase) + and obj not in (case.TestCase, case.FunctionTestCase) + ): return self.loadTestsFromTestCase(obj) elif (isinstance(obj, types.FunctionType) and isinstance(parent, type) and diff --git a/Lib/unittest/test/test_loader.py b/Lib/unittest/test/test_loader.py index de2268c..2400182 100644 --- a/Lib/unittest/test/test_loader.py +++ b/Lib/unittest/test/test_loader.py @@ -102,6 +102,22 @@ class Test_TestLoader(unittest.TestCase): self.assertIsInstance(suite, loader.suiteClass) self.assertEqual(list(suite), [Foo('runTest')]) + # "Do not load any tests from `TestCase` class itself." + def test_loadTestsFromTestCase__from_TestCase(self): + loader = unittest.TestLoader() + + suite = loader.loadTestsFromTestCase(unittest.TestCase) + self.assertIsInstance(suite, loader.suiteClass) + self.assertEqual(list(suite), []) + + # "Do not load any tests from `FunctionTestCase` class." + def test_loadTestsFromTestCase__from_FunctionTestCase(self): + loader = unittest.TestLoader() + + suite = loader.loadTestsFromTestCase(unittest.FunctionTestCase) + self.assertIsInstance(suite, loader.suiteClass) + self.assertEqual(list(suite), []) + ################################################################ ### /Tests for TestLoader.loadTestsFromTestCase @@ -123,6 +139,19 @@ class Test_TestLoader(unittest.TestCase): expected = [loader.suiteClass([MyTestCase('test')])] self.assertEqual(list(suite), expected) + # "This test ensures that internal `TestCase` subclasses are not loaded" + def test_loadTestsFromModule__TestCase_subclass_internals(self): + # See https://github.com/python/cpython/issues/84867 + m = types.ModuleType('m') + # Simulate imported names: + m.TestCase = unittest.TestCase + m.FunctionTestCase = unittest.FunctionTestCase + + loader = unittest.TestLoader() + suite = loader.loadTestsFromModule(m) + self.assertIsInstance(suite, loader.suiteClass) + self.assertEqual(list(suite), []) + # "This method searches `module` for classes derived from TestCase" # # What happens if no tests are found (no TestCase instances)? diff --git a/Misc/NEWS.d/next/Library/2022-12-24-12-50-54.gh-issue-84867.OhaLbU.rst b/Misc/NEWS.d/next/Library/2022-12-24-12-50-54.gh-issue-84867.OhaLbU.rst new file mode 100644 index 0000000..8b45dce --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-12-24-12-50-54.gh-issue-84867.OhaLbU.rst @@ -0,0 +1,2 @@ +:class:`unittest.TestLoader` no longer loads test cases from exact +:class:`unittest.TestCase` and :class:`unittest.FunctionTestCase` classes. |