]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-111165: Move test running code from test.support to libregrtest (GH-111166)
authorSerhiy Storchaka <storchaka@gmail.com>
Wed, 25 Oct 2023 09:41:21 +0000 (12:41 +0300)
committerGitHub <noreply@github.com>
Wed, 25 Oct 2023 09:41:21 +0000 (12:41 +0300)
Remove no longer used functions run_unittest() and run_doctest() from
the test.support module.

12 files changed:
Doc/library/test.rst
Lib/test/libregrtest/filter.py [new file with mode: 0644]
Lib/test/libregrtest/findtests.py
Lib/test/libregrtest/result.py
Lib/test/libregrtest/results.py
Lib/test/libregrtest/setup.py
Lib/test/libregrtest/single.py
Lib/test/libregrtest/testresult.py [moved from Lib/test/support/testresult.py with 100% similarity]
Lib/test/support/__init__.py
Lib/test/test_regrtest.py
Lib/test/test_support.py
Misc/NEWS.d/next/Tests/2023-10-21-19-27-36.gh-issue-111165.FU6mUk.rst [new file with mode: 0644]

index 6be77260faa7ea765b7b1212c7fcf728c3ff5c41..6e962881f29c498514b74e5c3471f2a64a86e699 100644 (file)
@@ -508,34 +508,6 @@ The :mod:`test.support` module defines the following functions:
    Define match patterns on test filenames and test method names for filtering tests.
 
 
-.. function:: run_unittest(*classes)
-
-   Execute :class:`unittest.TestCase` subclasses passed to the function. The
-   function scans the classes for methods starting with the prefix ``test_``
-   and executes the tests individually.
-
-   It is also legal to pass strings as parameters; these should be keys in
-   ``sys.modules``. Each associated module will be scanned by
-   ``unittest.TestLoader.loadTestsFromModule()``. This is usually seen in the
-   following :func:`test_main` function::
-
-      def test_main():
-          support.run_unittest(__name__)
-
-   This will run all tests defined in the named module.
-
-
-.. function:: run_doctest(module, verbosity=None, optionflags=0)
-
-   Run :func:`doctest.testmod` on the given *module*.  Return
-   ``(failure_count, test_count)``.
-
-   If *verbosity* is ``None``, :func:`doctest.testmod` is run with verbosity
-   set to :data:`verbose`.  Otherwise, it is run with verbosity set to
-   ``None``.  *optionflags* is passed as ``optionflags`` to
-   :func:`doctest.testmod`.
-
-
 .. function:: get_pagesize()
 
    Get size of a page in bytes.
diff --git a/Lib/test/libregrtest/filter.py b/Lib/test/libregrtest/filter.py
new file mode 100644 (file)
index 0000000..817624d
--- /dev/null
@@ -0,0 +1,72 @@
+import itertools
+import operator
+import re
+
+
+# By default, don't filter tests
+_test_matchers = ()
+_test_patterns = ()
+
+
+def match_test(test):
+    # Function used by support.run_unittest() and regrtest --list-cases
+    result = False
+    for matcher, result in reversed(_test_matchers):
+        if matcher(test.id()):
+            return result
+    return not result
+
+
+def _is_full_match_test(pattern):
+    # If a pattern contains at least one dot, it's considered
+    # as a full test identifier.
+    # Example: 'test.test_os.FileTests.test_access'.
+    #
+    # ignore patterns which contain fnmatch patterns: '*', '?', '[...]'
+    # or '[!...]'. For example, ignore 'test_access*'.
+    return ('.' in pattern) and (not re.search(r'[?*\[\]]', pattern))
+
+
+def set_match_tests(patterns):
+    global _test_matchers, _test_patterns
+
+    if not patterns:
+        _test_matchers = ()
+        _test_patterns = ()
+    else:
+        itemgetter = operator.itemgetter
+        patterns = tuple(patterns)
+        if patterns != _test_patterns:
+            _test_matchers = [
+                (_compile_match_function(map(itemgetter(0), it)), result)
+                for result, it in itertools.groupby(patterns, itemgetter(1))
+            ]
+            _test_patterns = patterns
+
+
+def _compile_match_function(patterns):
+    patterns = list(patterns)
+
+    if all(map(_is_full_match_test, patterns)):
+        # Simple case: all patterns are full test identifier.
+        # The test.bisect_cmd utility only uses such full test identifiers.
+        return set(patterns).__contains__
+    else:
+        import fnmatch
+        regex = '|'.join(map(fnmatch.translate, patterns))
+        # The search *is* case sensitive on purpose:
+        # don't use flags=re.IGNORECASE
+        regex_match = re.compile(regex).match
+
+        def match_test_regex(test_id, regex_match=regex_match):
+            if regex_match(test_id):
+                # The regex matches the whole identifier, for example
+                # 'test.test_os.FileTests.test_access'.
+                return True
+            else:
+                # Try to match parts of the test identifier.
+                # For example, split 'test.test_os.FileTests.test_access'
+                # into: 'test', 'test_os', 'FileTests' and 'test_access'.
+                return any(map(regex_match, test_id.split(".")))
+
+        return match_test_regex
index f3ff3628bea1341db34d1b51f736c1d8ef55dce3..78343775bc5b998998bbf270793abf86c8efc4aa 100644 (file)
@@ -4,6 +4,7 @@ import unittest
 
 from test import support
 
+from .filter import match_test, set_match_tests
 from .utils import (
     StrPath, TestName, TestTuple, TestList, TestFilter,
     abs_module_name, count, printlist)
@@ -79,14 +80,14 @@ def _list_cases(suite):
         if isinstance(test, unittest.TestSuite):
             _list_cases(test)
         elif isinstance(test, unittest.TestCase):
-            if support.match_test(test):
+            if match_test(test):
                 print(test.id())
 
 def list_cases(tests: TestTuple, *,
                match_tests: TestFilter | None = None,
                test_dir: StrPath | None = None):
     support.verbose = False
-    support.set_match_tests(match_tests)
+    set_match_tests(match_tests)
 
     skipped = []
     for test_name in tests:
index d6b0d5ad383a5bc1e256ee21be1cc63d23cb7f4b..8bfd3665ac93d5290793ca1579d58c4f2b4429bf 100644 (file)
@@ -2,13 +2,35 @@ import dataclasses
 import json
 from typing import Any
 
-from test.support import TestStats
-
 from .utils import (
     StrJSON, TestName, FilterTuple,
     format_duration, normalize_test_name, print_warning)
 
 
+@dataclasses.dataclass(slots=True)
+class TestStats:
+    tests_run: int = 0
+    failures: int = 0
+    skipped: int = 0
+
+    @staticmethod
+    def from_unittest(result):
+        return TestStats(result.testsRun,
+                         len(result.failures),
+                         len(result.skipped))
+
+    @staticmethod
+    def from_doctest(results):
+        return TestStats(results.attempted,
+                         results.failed,
+                         results.skipped)
+
+    def accumulate(self, stats):
+        self.tests_run += stats.tests_run
+        self.failures += stats.failures
+        self.skipped += stats.skipped
+
+
 # Avoid enum.Enum to reduce the number of imports when tests are run
 class State:
     PASSED = "PASSED"
index 3708078ff0bf3a17577a083d14af6f9a43d9c84a..1feb43f8c074db6a4d4fecc68137844dd1476c46 100644 (file)
@@ -1,8 +1,7 @@
 import sys
-from test.support import TestStats
 
 from .runtests import RunTests
-from .result import State, TestResult
+from .result import State, TestResult, TestStats
 from .utils import (
     StrPath, TestName, TestTuple, TestList, FilterDict,
     printlist, count, format_duration)
index 6a96b051394d208848efbc3ab0608bc80449d11e..97edba9f87d7f9307062657dd04918aa96b16ce5 100644 (file)
@@ -8,6 +8,7 @@ import unittest
 from test import support
 from test.support.os_helper import TESTFN_UNDECODABLE, FS_NONASCII
 
+from .filter import set_match_tests
 from .runtests import RunTests
 from .utils import (
     setup_unraisable_hook, setup_threading_excepthook, fix_umask,
@@ -92,11 +93,11 @@ def setup_tests(runtests: RunTests):
     support.PGO = runtests.pgo
     support.PGO_EXTENDED = runtests.pgo_extended
 
-    support.set_match_tests(runtests.match_tests)
+    set_match_tests(runtests.match_tests)
 
     if runtests.use_junit:
         support.junit_xml_list = []
-        from test.support.testresult import RegressionTestResult
+        from .testresult import RegressionTestResult
         RegressionTestResult.USE_XML = True
     else:
         support.junit_xml_list = None
index 0304f858edf42cc88ca3e08037c582e4182028c1..b4ae29905721dcdd1b5ff1c09ade3797286a9802 100644 (file)
@@ -9,13 +9,14 @@ import traceback
 import unittest
 
 from test import support
-from test.support import TestStats
 from test.support import threading_helper
 
-from .result import State, TestResult
+from .filter import match_test
+from .result import State, TestResult, TestStats
 from .runtests import RunTests
 from .save_env import saved_test_environment
 from .setup import setup_tests
+from .testresult import get_test_runner
 from .utils import (
     TestName,
     clear_caches, remove_testfn, abs_module_name, print_warning)
@@ -33,7 +34,47 @@ def run_unittest(test_mod):
         print(error, file=sys.stderr)
     if loader.errors:
         raise Exception("errors while loading tests")
-    return support.run_unittest(tests)
+    _filter_suite(tests, match_test)
+    return _run_suite(tests)
+
+def _filter_suite(suite, pred):
+    """Recursively filter test cases in a suite based on a predicate."""
+    newtests = []
+    for test in suite._tests:
+        if isinstance(test, unittest.TestSuite):
+            _filter_suite(test, pred)
+            newtests.append(test)
+        else:
+            if pred(test):
+                newtests.append(test)
+    suite._tests = newtests
+
+def _run_suite(suite):
+    """Run tests from a unittest.TestSuite-derived class."""
+    runner = get_test_runner(sys.stdout,
+                             verbosity=support.verbose,
+                             capture_output=(support.junit_xml_list is not None))
+
+    result = runner.run(suite)
+
+    if support.junit_xml_list is not None:
+        support.junit_xml_list.append(result.get_xml_element())
+
+    if not result.testsRun and not result.skipped and not result.errors:
+        raise support.TestDidNotRun
+    if not result.wasSuccessful():
+        stats = TestStats.from_unittest(result)
+        if len(result.errors) == 1 and not result.failures:
+            err = result.errors[0][1]
+        elif len(result.failures) == 1 and not result.errors:
+            err = result.failures[0][1]
+        else:
+            err = "multiple errors occurred"
+            if not verbose: err += "; run in verbose mode for details"
+        errors = [(str(tc), exc_str) for tc, exc_str in result.errors]
+        failures = [(str(tc), exc_str) for tc, exc_str in result.failures]
+        raise support.TestFailedWithDetails(err, errors, failures, stats=stats)
+    return result
 
 
 def regrtest_runner(result: TestResult, test_func, runtests: RunTests) -> None:
index 695ffd04e91fb2f9a8784f6d071b14f805b167b9..90fb1e670dfb38d2769c65125efe7d579d6bff79 100644 (file)
@@ -6,10 +6,8 @@ if __name__ != 'test.support':
 import contextlib
 import dataclasses
 import functools
-import itertools
 import getpass
 import _opcode
-import operator
 import os
 import re
 import stat
@@ -21,8 +19,6 @@ import types
 import unittest
 import warnings
 
-from .testresult import get_test_runner
-
 
 __all__ = [
     # globals
@@ -36,7 +32,6 @@ __all__ = [
     "is_resource_enabled", "requires", "requires_freebsd_version",
     "requires_linux_version", "requires_mac_ver",
     "check_syntax_error",
-    "run_unittest", "run_doctest",
     "requires_gzip", "requires_bz2", "requires_lzma",
     "bigmemtest", "bigaddrspacetest", "cpython_only", "get_attribute",
     "requires_IEEE_754", "requires_zlib",
@@ -1120,156 +1115,6 @@ def requires_specialization(test):
     return unittest.skipUnless(
         _opcode.ENABLE_SPECIALIZATION, "requires specialization")(test)
 
-def _filter_suite(suite, pred):
-    """Recursively filter test cases in a suite based on a predicate."""
-    newtests = []
-    for test in suite._tests:
-        if isinstance(test, unittest.TestSuite):
-            _filter_suite(test, pred)
-            newtests.append(test)
-        else:
-            if pred(test):
-                newtests.append(test)
-    suite._tests = newtests
-
-@dataclasses.dataclass(slots=True)
-class TestStats:
-    tests_run: int = 0
-    failures: int = 0
-    skipped: int = 0
-
-    @staticmethod
-    def from_unittest(result):
-        return TestStats(result.testsRun,
-                         len(result.failures),
-                         len(result.skipped))
-
-    @staticmethod
-    def from_doctest(results):
-        return TestStats(results.attempted,
-                         results.failed,
-                         results.skipped)
-
-    def accumulate(self, stats):
-        self.tests_run += stats.tests_run
-        self.failures += stats.failures
-        self.skipped += stats.skipped
-
-
-def _run_suite(suite):
-    """Run tests from a unittest.TestSuite-derived class."""
-    runner = get_test_runner(sys.stdout,
-                             verbosity=verbose,
-                             capture_output=(junit_xml_list is not None))
-
-    result = runner.run(suite)
-
-    if junit_xml_list is not None:
-        junit_xml_list.append(result.get_xml_element())
-
-    if not result.testsRun and not result.skipped and not result.errors:
-        raise TestDidNotRun
-    if not result.wasSuccessful():
-        stats = TestStats.from_unittest(result)
-        if len(result.errors) == 1 and not result.failures:
-            err = result.errors[0][1]
-        elif len(result.failures) == 1 and not result.errors:
-            err = result.failures[0][1]
-        else:
-            err = "multiple errors occurred"
-            if not verbose: err += "; run in verbose mode for details"
-        errors = [(str(tc), exc_str) for tc, exc_str in result.errors]
-        failures = [(str(tc), exc_str) for tc, exc_str in result.failures]
-        raise TestFailedWithDetails(err, errors, failures, stats=stats)
-    return result
-
-
-# By default, don't filter tests
-_test_matchers = ()
-_test_patterns = ()
-
-
-def match_test(test):
-    # Function used by support.run_unittest() and regrtest --list-cases
-    result = False
-    for matcher, result in reversed(_test_matchers):
-        if matcher(test.id()):
-            return result
-    return not result
-
-
-def _is_full_match_test(pattern):
-    # If a pattern contains at least one dot, it's considered
-    # as a full test identifier.
-    # Example: 'test.test_os.FileTests.test_access'.
-    #
-    # ignore patterns which contain fnmatch patterns: '*', '?', '[...]'
-    # or '[!...]'. For example, ignore 'test_access*'.
-    return ('.' in pattern) and (not re.search(r'[?*\[\]]', pattern))
-
-
-def set_match_tests(patterns):
-    global _test_matchers, _test_patterns
-
-    if not patterns:
-        _test_matchers = ()
-        _test_patterns = ()
-    else:
-        itemgetter = operator.itemgetter
-        patterns = tuple(patterns)
-        if patterns != _test_patterns:
-            _test_matchers = [
-                (_compile_match_function(map(itemgetter(0), it)), result)
-                for result, it in itertools.groupby(patterns, itemgetter(1))
-            ]
-            _test_patterns = patterns
-
-
-def _compile_match_function(patterns):
-    patterns = list(patterns)
-
-    if all(map(_is_full_match_test, patterns)):
-        # Simple case: all patterns are full test identifier.
-        # The test.bisect_cmd utility only uses such full test identifiers.
-        return set(patterns).__contains__
-    else:
-        import fnmatch
-        regex = '|'.join(map(fnmatch.translate, patterns))
-        # The search *is* case sensitive on purpose:
-        # don't use flags=re.IGNORECASE
-        regex_match = re.compile(regex).match
-
-        def match_test_regex(test_id, regex_match=regex_match):
-            if regex_match(test_id):
-                # The regex matches the whole identifier, for example
-                # 'test.test_os.FileTests.test_access'.
-                return True
-            else:
-                # Try to match parts of the test identifier.
-                # For example, split 'test.test_os.FileTests.test_access'
-                # into: 'test', 'test_os', 'FileTests' and 'test_access'.
-                return any(map(regex_match, test_id.split(".")))
-
-        return match_test_regex
-
-
-def run_unittest(*classes):
-    """Run tests from unittest.TestCase-derived classes."""
-    valid_types = (unittest.TestSuite, unittest.TestCase)
-    loader = unittest.TestLoader()
-    suite = unittest.TestSuite()
-    for cls in classes:
-        if isinstance(cls, str):
-            if cls in sys.modules:
-                suite.addTest(loader.loadTestsFromModule(sys.modules[cls]))
-            else:
-                raise ValueError("str arguments must be keys in sys.modules")
-        elif isinstance(cls, valid_types):
-            suite.addTest(cls)
-        else:
-            suite.addTest(loader.loadTestsFromTestCase(cls))
-    _filter_suite(suite, match_test)
-    return _run_suite(suite)
 
 #=======================================================================
 # Check for the presence of docstrings.
@@ -1291,38 +1136,6 @@ requires_docstrings = unittest.skipUnless(HAVE_DOCSTRINGS,
                                           "test requires docstrings")
 
 
-#=======================================================================
-# doctest driver.
-
-def run_doctest(module, verbosity=None, optionflags=0):
-    """Run doctest on the given module.  Return (#failures, #tests).
-
-    If optional argument verbosity is not specified (or is None), pass
-    support's belief about verbosity on to doctest.  Else doctest's
-    usual behavior is used (it searches sys.argv for -v).
-    """
-
-    import doctest
-
-    if verbosity is None:
-        verbosity = verbose
-    else:
-        verbosity = None
-
-    results = doctest.testmod(module,
-                             verbose=verbosity,
-                             optionflags=optionflags)
-    if results.failed:
-        stats = TestStats.from_doctest(results)
-        raise TestFailed(f"{results.failed} of {results.attempted} "
-                         f"doctests failed",
-                         stats=stats)
-    if verbose:
-        print('doctest (%s) ... %d tests with zero failures' %
-              (module.__name__, results.attempted))
-    return results
-
-
 #=======================================================================
 # Support for saving and restoring the imported modules.
 
index 22b38ac64393832999fb3950a1ffd7ff3e66fbd3..0c39af05eb5ea8bfe042932d6d8a387272f2e9fb 100644 (file)
@@ -22,11 +22,13 @@ import tempfile
 import textwrap
 import unittest
 from test import support
-from test.support import os_helper, TestStats, without_optimizer
+from test.support import os_helper, without_optimizer
 from test.libregrtest import cmdline
 from test.libregrtest import main
 from test.libregrtest import setup
 from test.libregrtest import utils
+from test.libregrtest.filter import set_match_tests, match_test
+from test.libregrtest.result import TestStats
 from test.libregrtest.utils import normalize_test_name
 
 if not support.has_subprocess_support:
@@ -2182,6 +2184,120 @@ class TestUtils(unittest.TestCase):
             format_resources((*ALL_RESOURCES, "tzdata")),
             'resources: all,tzdata')
 
+    def test_match_test(self):
+        class Test:
+            def __init__(self, test_id):
+                self.test_id = test_id
+
+            def id(self):
+                return self.test_id
+
+        test_access = Test('test.test_os.FileTests.test_access')
+        test_chdir = Test('test.test_os.Win32ErrorTests.test_chdir')
+        test_copy = Test('test.test_shutil.TestCopy.test_copy')
+
+        # Test acceptance
+        with support.swap_attr(support, '_test_matchers', ()):
+            # match all
+            set_match_tests([])
+            self.assertTrue(match_test(test_access))
+            self.assertTrue(match_test(test_chdir))
+
+            # match all using None
+            set_match_tests(None)
+            self.assertTrue(match_test(test_access))
+            self.assertTrue(match_test(test_chdir))
+
+            # match the full test identifier
+            set_match_tests([(test_access.id(), True)])
+            self.assertTrue(match_test(test_access))
+            self.assertFalse(match_test(test_chdir))
+
+            # match the module name
+            set_match_tests([('test_os', True)])
+            self.assertTrue(match_test(test_access))
+            self.assertTrue(match_test(test_chdir))
+            self.assertFalse(match_test(test_copy))
+
+            # Test '*' pattern
+            set_match_tests([('test_*', True)])
+            self.assertTrue(match_test(test_access))
+            self.assertTrue(match_test(test_chdir))
+
+            # Test case sensitivity
+            set_match_tests([('filetests', True)])
+            self.assertFalse(match_test(test_access))
+            set_match_tests([('FileTests', True)])
+            self.assertTrue(match_test(test_access))
+
+            # Test pattern containing '.' and a '*' metacharacter
+            set_match_tests([('*test_os.*.test_*', True)])
+            self.assertTrue(match_test(test_access))
+            self.assertTrue(match_test(test_chdir))
+            self.assertFalse(match_test(test_copy))
+
+            # Multiple patterns
+            set_match_tests([(test_access.id(), True), (test_chdir.id(), True)])
+            self.assertTrue(match_test(test_access))
+            self.assertTrue(match_test(test_chdir))
+            self.assertFalse(match_test(test_copy))
+
+            set_match_tests([('test_access', True), ('DONTMATCH', True)])
+            self.assertTrue(match_test(test_access))
+            self.assertFalse(match_test(test_chdir))
+
+        # Test rejection
+        with support.swap_attr(support, '_test_matchers', ()):
+            # match the full test identifier
+            set_match_tests([(test_access.id(), False)])
+            self.assertFalse(match_test(test_access))
+            self.assertTrue(match_test(test_chdir))
+
+            # match the module name
+            set_match_tests([('test_os', False)])
+            self.assertFalse(match_test(test_access))
+            self.assertFalse(match_test(test_chdir))
+            self.assertTrue(match_test(test_copy))
+
+            # Test '*' pattern
+            set_match_tests([('test_*', False)])
+            self.assertFalse(match_test(test_access))
+            self.assertFalse(match_test(test_chdir))
+
+            # Test case sensitivity
+            set_match_tests([('filetests', False)])
+            self.assertTrue(match_test(test_access))
+            set_match_tests([('FileTests', False)])
+            self.assertFalse(match_test(test_access))
+
+            # Test pattern containing '.' and a '*' metacharacter
+            set_match_tests([('*test_os.*.test_*', False)])
+            self.assertFalse(match_test(test_access))
+            self.assertFalse(match_test(test_chdir))
+            self.assertTrue(match_test(test_copy))
+
+            # Multiple patterns
+            set_match_tests([(test_access.id(), False), (test_chdir.id(), False)])
+            self.assertFalse(match_test(test_access))
+            self.assertFalse(match_test(test_chdir))
+            self.assertTrue(match_test(test_copy))
+
+            set_match_tests([('test_access', False), ('DONTMATCH', False)])
+            self.assertFalse(match_test(test_access))
+            self.assertTrue(match_test(test_chdir))
+
+        # Test mixed filters
+        with support.swap_attr(support, '_test_matchers', ()):
+            set_match_tests([('*test_os', False), ('test_access', True)])
+            self.assertTrue(match_test(test_access))
+            self.assertFalse(match_test(test_chdir))
+            self.assertTrue(match_test(test_copy))
+
+            set_match_tests([('*test_os', True), ('test_access', False)])
+            self.assertFalse(match_test(test_access))
+            self.assertTrue(match_test(test_chdir))
+            self.assertFalse(match_test(test_copy))
+
 
 if __name__ == '__main__':
     unittest.main()
index 41fcc9d5fd3f345b3a6b056f84fd7ddac716f81c..c34b0e5e015702021ea5c2d747f93f1bd2be4d0d 100644 (file)
@@ -547,120 +547,6 @@ class TestSupport(unittest.TestCase):
             with self.subTest(opts=opts):
                 self.check_options(opts, 'optim_args_from_interpreter_flags')
 
-    def test_match_test(self):
-        class Test:
-            def __init__(self, test_id):
-                self.test_id = test_id
-
-            def id(self):
-                return self.test_id
-
-        test_access = Test('test.test_os.FileTests.test_access')
-        test_chdir = Test('test.test_os.Win32ErrorTests.test_chdir')
-        test_copy = Test('test.test_shutil.TestCopy.test_copy')
-
-        # Test acceptance
-        with support.swap_attr(support, '_test_matchers', ()):
-            # match all
-            support.set_match_tests([])
-            self.assertTrue(support.match_test(test_access))
-            self.assertTrue(support.match_test(test_chdir))
-
-            # match all using None
-            support.set_match_tests(None)
-            self.assertTrue(support.match_test(test_access))
-            self.assertTrue(support.match_test(test_chdir))
-
-            # match the full test identifier
-            support.set_match_tests([(test_access.id(), True)])
-            self.assertTrue(support.match_test(test_access))
-            self.assertFalse(support.match_test(test_chdir))
-
-            # match the module name
-            support.set_match_tests([('test_os', True)])
-            self.assertTrue(support.match_test(test_access))
-            self.assertTrue(support.match_test(test_chdir))
-            self.assertFalse(support.match_test(test_copy))
-
-            # Test '*' pattern
-            support.set_match_tests([('test_*', True)])
-            self.assertTrue(support.match_test(test_access))
-            self.assertTrue(support.match_test(test_chdir))
-
-            # Test case sensitivity
-            support.set_match_tests([('filetests', True)])
-            self.assertFalse(support.match_test(test_access))
-            support.set_match_tests([('FileTests', True)])
-            self.assertTrue(support.match_test(test_access))
-
-            # Test pattern containing '.' and a '*' metacharacter
-            support.set_match_tests([('*test_os.*.test_*', True)])
-            self.assertTrue(support.match_test(test_access))
-            self.assertTrue(support.match_test(test_chdir))
-            self.assertFalse(support.match_test(test_copy))
-
-            # Multiple patterns
-            support.set_match_tests([(test_access.id(), True), (test_chdir.id(), True)])
-            self.assertTrue(support.match_test(test_access))
-            self.assertTrue(support.match_test(test_chdir))
-            self.assertFalse(support.match_test(test_copy))
-
-            support.set_match_tests([('test_access', True), ('DONTMATCH', True)])
-            self.assertTrue(support.match_test(test_access))
-            self.assertFalse(support.match_test(test_chdir))
-
-        # Test rejection
-        with support.swap_attr(support, '_test_matchers', ()):
-            # match the full test identifier
-            support.set_match_tests([(test_access.id(), False)])
-            self.assertFalse(support.match_test(test_access))
-            self.assertTrue(support.match_test(test_chdir))
-
-            # match the module name
-            support.set_match_tests([('test_os', False)])
-            self.assertFalse(support.match_test(test_access))
-            self.assertFalse(support.match_test(test_chdir))
-            self.assertTrue(support.match_test(test_copy))
-
-            # Test '*' pattern
-            support.set_match_tests([('test_*', False)])
-            self.assertFalse(support.match_test(test_access))
-            self.assertFalse(support.match_test(test_chdir))
-
-            # Test case sensitivity
-            support.set_match_tests([('filetests', False)])
-            self.assertTrue(support.match_test(test_access))
-            support.set_match_tests([('FileTests', False)])
-            self.assertFalse(support.match_test(test_access))
-
-            # Test pattern containing '.' and a '*' metacharacter
-            support.set_match_tests([('*test_os.*.test_*', False)])
-            self.assertFalse(support.match_test(test_access))
-            self.assertFalse(support.match_test(test_chdir))
-            self.assertTrue(support.match_test(test_copy))
-
-            # Multiple patterns
-            support.set_match_tests([(test_access.id(), False), (test_chdir.id(), False)])
-            self.assertFalse(support.match_test(test_access))
-            self.assertFalse(support.match_test(test_chdir))
-            self.assertTrue(support.match_test(test_copy))
-
-            support.set_match_tests([('test_access', False), ('DONTMATCH', False)])
-            self.assertFalse(support.match_test(test_access))
-            self.assertTrue(support.match_test(test_chdir))
-
-        # Test mixed filters
-        with support.swap_attr(support, '_test_matchers', ()):
-            support.set_match_tests([('*test_os', False), ('test_access', True)])
-            self.assertTrue(support.match_test(test_access))
-            self.assertFalse(support.match_test(test_chdir))
-            self.assertTrue(support.match_test(test_copy))
-
-            support.set_match_tests([('*test_os', True), ('test_access', False)])
-            self.assertFalse(support.match_test(test_access))
-            self.assertTrue(support.match_test(test_chdir))
-            self.assertFalse(support.match_test(test_copy))
-
     @unittest.skipIf(support.is_emscripten, "Unstable in Emscripten")
     @unittest.skipIf(support.is_wasi, "Unavailable on WASI")
     def test_fd_count(self):
@@ -861,7 +747,6 @@ class TestSupport(unittest.TestCase):
     # precisionbigmemtest
     # bigaddrspacetest
     # requires_resource
-    # run_doctest
     # threading_cleanup
     # reap_threads
     # can_symlink
diff --git a/Misc/NEWS.d/next/Tests/2023-10-21-19-27-36.gh-issue-111165.FU6mUk.rst b/Misc/NEWS.d/next/Tests/2023-10-21-19-27-36.gh-issue-111165.FU6mUk.rst
new file mode 100644 (file)
index 0000000..11f302d
--- /dev/null
@@ -0,0 +1,2 @@
+Remove no longer used functions ``run_unittest()`` and ``run_doctest()``
+from the :mod:`test.support` module.