gh-111165: Move test running code from test.support to libregrtest (GH-111166)

Remove no longer used functions run_unittest() and run_doctest() from
the test.support module.
This commit is contained in:
Serhiy Storchaka 2023-10-25 12:41:21 +03:00 committed by GitHub
parent a8a89fcd1f
commit f6a45a03d0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 266 additions and 342 deletions

View 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. 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() .. function:: get_pagesize()
Get size of a page in bytes. Get size of a page in bytes.

View file

@ -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

View file

@ -4,6 +4,7 @@ import unittest
from test import support from test import support
from .filter import match_test, set_match_tests
from .utils import ( from .utils import (
StrPath, TestName, TestTuple, TestList, TestFilter, StrPath, TestName, TestTuple, TestList, TestFilter,
abs_module_name, count, printlist) abs_module_name, count, printlist)
@ -79,14 +80,14 @@ def _list_cases(suite):
if isinstance(test, unittest.TestSuite): if isinstance(test, unittest.TestSuite):
_list_cases(test) _list_cases(test)
elif isinstance(test, unittest.TestCase): elif isinstance(test, unittest.TestCase):
if support.match_test(test): if match_test(test):
print(test.id()) print(test.id())
def list_cases(tests: TestTuple, *, def list_cases(tests: TestTuple, *,
match_tests: TestFilter | None = None, match_tests: TestFilter | None = None,
test_dir: StrPath | None = None): test_dir: StrPath | None = None):
support.verbose = False support.verbose = False
support.set_match_tests(match_tests) set_match_tests(match_tests)
skipped = [] skipped = []
for test_name in tests: for test_name in tests:

View file

@ -2,13 +2,35 @@ import dataclasses
import json import json
from typing import Any from typing import Any
from test.support import TestStats
from .utils import ( from .utils import (
StrJSON, TestName, FilterTuple, StrJSON, TestName, FilterTuple,
format_duration, normalize_test_name, print_warning) 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 # Avoid enum.Enum to reduce the number of imports when tests are run
class State: class State:
PASSED = "PASSED" PASSED = "PASSED"

View file

@ -1,8 +1,7 @@
import sys import sys
from test.support import TestStats
from .runtests import RunTests from .runtests import RunTests
from .result import State, TestResult from .result import State, TestResult, TestStats
from .utils import ( from .utils import (
StrPath, TestName, TestTuple, TestList, FilterDict, StrPath, TestName, TestTuple, TestList, FilterDict,
printlist, count, format_duration) printlist, count, format_duration)

View file

@ -8,6 +8,7 @@ import unittest
from test import support from test import support
from test.support.os_helper import TESTFN_UNDECODABLE, FS_NONASCII from test.support.os_helper import TESTFN_UNDECODABLE, FS_NONASCII
from .filter import set_match_tests
from .runtests import RunTests from .runtests import RunTests
from .utils import ( from .utils import (
setup_unraisable_hook, setup_threading_excepthook, fix_umask, setup_unraisable_hook, setup_threading_excepthook, fix_umask,
@ -92,11 +93,11 @@ def setup_tests(runtests: RunTests):
support.PGO = runtests.pgo support.PGO = runtests.pgo
support.PGO_EXTENDED = runtests.pgo_extended support.PGO_EXTENDED = runtests.pgo_extended
support.set_match_tests(runtests.match_tests) set_match_tests(runtests.match_tests)
if runtests.use_junit: if runtests.use_junit:
support.junit_xml_list = [] support.junit_xml_list = []
from test.support.testresult import RegressionTestResult from .testresult import RegressionTestResult
RegressionTestResult.USE_XML = True RegressionTestResult.USE_XML = True
else: else:
support.junit_xml_list = None support.junit_xml_list = None

View file

@ -9,13 +9,14 @@ import traceback
import unittest import unittest
from test import support from test import support
from test.support import TestStats
from test.support import threading_helper 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 .runtests import RunTests
from .save_env import saved_test_environment from .save_env import saved_test_environment
from .setup import setup_tests from .setup import setup_tests
from .testresult import get_test_runner
from .utils import ( from .utils import (
TestName, TestName,
clear_caches, remove_testfn, abs_module_name, print_warning) clear_caches, remove_testfn, abs_module_name, print_warning)
@ -33,7 +34,47 @@ def run_unittest(test_mod):
print(error, file=sys.stderr) print(error, file=sys.stderr)
if loader.errors: if loader.errors:
raise Exception("errors while loading tests") 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: def regrtest_runner(result: TestResult, test_func, runtests: RunTests) -> None:

View file

@ -6,10 +6,8 @@ if __name__ != 'test.support':
import contextlib import contextlib
import dataclasses import dataclasses
import functools import functools
import itertools
import getpass import getpass
import _opcode import _opcode
import operator
import os import os
import re import re
import stat import stat
@ -21,8 +19,6 @@ import types
import unittest import unittest
import warnings import warnings
from .testresult import get_test_runner
__all__ = [ __all__ = [
# globals # globals
@ -36,7 +32,6 @@ __all__ = [
"is_resource_enabled", "requires", "requires_freebsd_version", "is_resource_enabled", "requires", "requires_freebsd_version",
"requires_linux_version", "requires_mac_ver", "requires_linux_version", "requires_mac_ver",
"check_syntax_error", "check_syntax_error",
"run_unittest", "run_doctest",
"requires_gzip", "requires_bz2", "requires_lzma", "requires_gzip", "requires_bz2", "requires_lzma",
"bigmemtest", "bigaddrspacetest", "cpython_only", "get_attribute", "bigmemtest", "bigaddrspacetest", "cpython_only", "get_attribute",
"requires_IEEE_754", "requires_zlib", "requires_IEEE_754", "requires_zlib",
@ -1120,156 +1115,6 @@ def requires_specialization(test):
return unittest.skipUnless( return unittest.skipUnless(
_opcode.ENABLE_SPECIALIZATION, "requires specialization")(test) _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. # Check for the presence of docstrings.
@ -1291,38 +1136,6 @@ requires_docstrings = unittest.skipUnless(HAVE_DOCSTRINGS,
"test requires 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. # Support for saving and restoring the imported modules.

View file

@ -22,11 +22,13 @@ import tempfile
import textwrap import textwrap
import unittest import unittest
from test import support 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 cmdline
from test.libregrtest import main from test.libregrtest import main
from test.libregrtest import setup from test.libregrtest import setup
from test.libregrtest import utils 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 from test.libregrtest.utils import normalize_test_name
if not support.has_subprocess_support: if not support.has_subprocess_support:
@ -2182,6 +2184,120 @@ class TestUtils(unittest.TestCase):
format_resources((*ALL_RESOURCES, "tzdata")), format_resources((*ALL_RESOURCES, "tzdata")),
'resources: all,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__': if __name__ == '__main__':
unittest.main() unittest.main()

View file

@ -547,120 +547,6 @@ class TestSupport(unittest.TestCase):
with self.subTest(opts=opts): with self.subTest(opts=opts):
self.check_options(opts, 'optim_args_from_interpreter_flags') 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_emscripten, "Unstable in Emscripten")
@unittest.skipIf(support.is_wasi, "Unavailable on WASI") @unittest.skipIf(support.is_wasi, "Unavailable on WASI")
def test_fd_count(self): def test_fd_count(self):
@ -861,7 +747,6 @@ class TestSupport(unittest.TestCase):
# precisionbigmemtest # precisionbigmemtest
# bigaddrspacetest # bigaddrspacetest
# requires_resource # requires_resource
# run_doctest
# threading_cleanup # threading_cleanup
# reap_threads # reap_threads
# can_symlink # can_symlink

View file

@ -0,0 +1,2 @@
Remove no longer used functions ``run_unittest()`` and ``run_doctest()``
from the :mod:`test.support` module.