summaryrefslogtreecommitdiffstats
path: root/Lib/test/support/__init__.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/test/support/__init__.py')
-rw-r--r--Lib/test/support/__init__.py67
1 files changed, 55 insertions, 12 deletions
diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
index 527cf7f..71d9c2c 100644
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -278,7 +278,6 @@ max_memuse = 0 # Disable bigmem tests (they will still be run with
# small sizes, to make sure they work.)
real_max_memuse = 0
failfast = False
-match_tests = None
# _original_stdout is meant to hold stdout at the time regrtest began.
# This may be "the real" stdout, or IDLE's emulation of stdout, or whatever.
@@ -1900,21 +1899,65 @@ def _run_suite(suite):
raise TestFailed(err)
-def _match_test(test):
- global match_tests
+# By default, don't filter tests
+_match_test_func = None
+_match_test_patterns = None
- if match_tests is None:
+
+def match_test(test):
+ # Function used by support.run_unittest() and regrtest --list-cases
+ if _match_test_func is None:
return True
- test_id = test.id()
+ else:
+ return _match_test_func(test.id())
- for match_test in match_tests:
- if fnmatch.fnmatchcase(test_id, match_test):
- return True
- for name in test_id.split("."):
- if fnmatch.fnmatchcase(name, match_test):
+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'.
+ #
+ # Reject patterns which contain fnmatch patterns: '*', '?', '[...]'
+ # or '[!...]'. For example, reject 'test_access*'.
+ return ('.' in pattern) and (not re.search(r'[?*\[\]]', pattern))
+
+
+def set_match_tests(patterns):
+ global _match_test_func, _match_test_patterns
+
+ if patterns == _match_test_patterns:
+ # No change: no need to recompile patterns.
+ return
+
+ if not patterns:
+ func = None
+ elif all(map(_is_full_match_test, patterns)):
+ # Simple case: all patterns are full test identifier.
+ # The test.bisect utility only uses such full test identifiers.
+ func = set(patterns).__contains__
+ else:
+ 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):
+ if regex_match(test_id):
+ # The regex matchs the whole identifier like
+ # 'test.test_os.FileTests.test_access'
return True
- return False
+ 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(".")))
+
+ func = match_test_regex
+
+ # Create a copy since patterns can be mutable and so modified later
+ _match_test_patterns = tuple(patterns)
+ _match_test_func = func
+
def run_unittest(*classes):
@@ -1931,7 +1974,7 @@ def run_unittest(*classes):
suite.addTest(cls)
else:
suite.addTest(unittest.makeSuite(cls))
- _filter_suite(suite, _match_test)
+ _filter_suite(suite, match_test)
_run_suite(suite)
#=======================================================================