Issue #12626: In regrtest, allow to filter tests using a glob filter
with the `-m` (or `--match`) option. This works with all test cases using the unittest module. This is useful with long test suites such as test_io or test_subprocess.
This commit is contained in:
parent
def35435ee
commit
b9c73e8cf0
|
@ -38,6 +38,7 @@ Selecting tests
|
||||||
-f/--fromfile -- read names of tests to run from a file (see below)
|
-f/--fromfile -- read names of tests to run from a file (see below)
|
||||||
-x/--exclude -- arguments are tests to *exclude*
|
-x/--exclude -- arguments are tests to *exclude*
|
||||||
-s/--single -- single step through a set of tests (see below)
|
-s/--single -- single step through a set of tests (see below)
|
||||||
|
-m/--match PAT -- match test cases and methods with glob pattern PAT
|
||||||
-G/--failfast -- fail as soon as a test fails (only with -v or -W)
|
-G/--failfast -- fail as soon as a test fails (only with -v or -W)
|
||||||
-u/--use RES1,RES2,...
|
-u/--use RES1,RES2,...
|
||||||
-- specify which special resource intensive tests to run
|
-- specify which special resource intensive tests to run
|
||||||
|
@ -242,7 +243,7 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
|
||||||
findleaks=False, use_resources=None, trace=False, coverdir='coverage',
|
findleaks=False, use_resources=None, trace=False, coverdir='coverage',
|
||||||
runleaks=False, huntrleaks=False, verbose2=False, print_slow=False,
|
runleaks=False, huntrleaks=False, verbose2=False, print_slow=False,
|
||||||
random_seed=None, use_mp=None, verbose3=False, forever=False,
|
random_seed=None, use_mp=None, verbose3=False, forever=False,
|
||||||
header=False, failfast=False):
|
header=False, failfast=False, match_tests=None):
|
||||||
"""Execute a test suite.
|
"""Execute a test suite.
|
||||||
|
|
||||||
This also parses command-line options and modifies its behavior
|
This also parses command-line options and modifies its behavior
|
||||||
|
@ -270,13 +271,13 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
|
||||||
|
|
||||||
support.record_original_stdout(sys.stdout)
|
support.record_original_stdout(sys.stdout)
|
||||||
try:
|
try:
|
||||||
opts, args = getopt.getopt(sys.argv[1:], 'hvqxsSrf:lu:t:TD:NLR:FwWM:nj:G',
|
opts, args = getopt.getopt(sys.argv[1:], 'hvqxsSrf:lu:t:TD:NLR:FwWM:nj:Gm:',
|
||||||
['help', 'verbose', 'verbose2', 'verbose3', 'quiet',
|
['help', 'verbose', 'verbose2', 'verbose3', 'quiet',
|
||||||
'exclude', 'single', 'slow', 'random', 'fromfile', 'findleaks',
|
'exclude', 'single', 'slow', 'random', 'fromfile', 'findleaks',
|
||||||
'use=', 'threshold=', 'trace', 'coverdir=', 'nocoverdir',
|
'use=', 'threshold=', 'trace', 'coverdir=', 'nocoverdir',
|
||||||
'runleaks', 'huntrleaks=', 'memlimit=', 'randseed=',
|
'runleaks', 'huntrleaks=', 'memlimit=', 'randseed=',
|
||||||
'multiprocess=', 'coverage', 'slaveargs=', 'forever', 'debug',
|
'multiprocess=', 'coverage', 'slaveargs=', 'forever', 'debug',
|
||||||
'start=', 'nowindows', 'header', 'failfast'])
|
'start=', 'nowindows', 'header', 'failfast', 'match'])
|
||||||
except getopt.error as msg:
|
except getopt.error as msg:
|
||||||
usage(msg)
|
usage(msg)
|
||||||
|
|
||||||
|
@ -318,6 +319,8 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
|
||||||
random_seed = int(a)
|
random_seed = int(a)
|
||||||
elif o in ('-f', '--fromfile'):
|
elif o in ('-f', '--fromfile'):
|
||||||
fromfile = a
|
fromfile = a
|
||||||
|
elif o in ('-m', '--match'):
|
||||||
|
match_tests = a
|
||||||
elif o in ('-l', '--findleaks'):
|
elif o in ('-l', '--findleaks'):
|
||||||
findleaks = True
|
findleaks = True
|
||||||
elif o in ('-L', '--runleaks'):
|
elif o in ('-L', '--runleaks'):
|
||||||
|
@ -551,7 +554,7 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
|
||||||
(test, verbose, quiet),
|
(test, verbose, quiet),
|
||||||
dict(huntrleaks=huntrleaks, use_resources=use_resources,
|
dict(huntrleaks=huntrleaks, use_resources=use_resources,
|
||||||
debug=debug, output_on_failure=verbose3,
|
debug=debug, output_on_failure=verbose3,
|
||||||
failfast=failfast)
|
failfast=failfast, match_tests=match_tests)
|
||||||
)
|
)
|
||||||
yield (test, args_tuple)
|
yield (test, args_tuple)
|
||||||
pending = tests_and_args()
|
pending = tests_and_args()
|
||||||
|
@ -630,7 +633,7 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
|
||||||
try:
|
try:
|
||||||
result = runtest(test, verbose, quiet, huntrleaks, debug,
|
result = runtest(test, verbose, quiet, huntrleaks, debug,
|
||||||
output_on_failure=verbose3,
|
output_on_failure=verbose3,
|
||||||
failfast=failfast)
|
failfast=failfast, match_tests=match_tests)
|
||||||
accumulate_result(test, result)
|
accumulate_result(test, result)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
interrupted = True
|
interrupted = True
|
||||||
|
@ -777,7 +780,7 @@ def replace_stdout():
|
||||||
|
|
||||||
def runtest(test, verbose, quiet,
|
def runtest(test, verbose, quiet,
|
||||||
huntrleaks=False, debug=False, use_resources=None,
|
huntrleaks=False, debug=False, use_resources=None,
|
||||||
output_on_failure=False, failfast=False):
|
output_on_failure=False, failfast=False, match_tests=None):
|
||||||
"""Run a single test.
|
"""Run a single test.
|
||||||
|
|
||||||
test -- the name of the test
|
test -- the name of the test
|
||||||
|
@ -800,6 +803,7 @@ def runtest(test, verbose, quiet,
|
||||||
if use_resources is not None:
|
if use_resources is not None:
|
||||||
support.use_resources = use_resources
|
support.use_resources = use_resources
|
||||||
try:
|
try:
|
||||||
|
support.match_tests = match_tests
|
||||||
if failfast:
|
if failfast:
|
||||||
support.failfast = True
|
support.failfast = True
|
||||||
if output_on_failure:
|
if output_on_failure:
|
||||||
|
|
|
@ -21,6 +21,7 @@ import subprocess
|
||||||
import imp
|
import imp
|
||||||
import time
|
import time
|
||||||
import sysconfig
|
import sysconfig
|
||||||
|
import fnmatch
|
||||||
import logging.handlers
|
import logging.handlers
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -177,6 +178,7 @@ max_memuse = 0 # Disable bigmem tests (they will still be run with
|
||||||
# small sizes, to make sure they work.)
|
# small sizes, to make sure they work.)
|
||||||
real_max_memuse = 0
|
real_max_memuse = 0
|
||||||
failfast = False
|
failfast = False
|
||||||
|
match_tests = None
|
||||||
|
|
||||||
# _original_stdout is meant to hold stdout at the time regrtest began.
|
# _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.
|
# This may be "the real" stdout, or IDLE's emulation of stdout, or whatever.
|
||||||
|
@ -1183,6 +1185,18 @@ def check_impl_detail(**guards):
|
||||||
return guards.get(platform.python_implementation().lower(), default)
|
return guards.get(platform.python_implementation().lower(), default)
|
||||||
|
|
||||||
|
|
||||||
|
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):
|
def _run_suite(suite):
|
||||||
"""Run tests from a unittest.TestSuite-derived class."""
|
"""Run tests from a unittest.TestSuite-derived class."""
|
||||||
|
@ -1218,6 +1232,14 @@ def run_unittest(*classes):
|
||||||
suite.addTest(cls)
|
suite.addTest(cls)
|
||||||
else:
|
else:
|
||||||
suite.addTest(unittest.makeSuite(cls))
|
suite.addTest(unittest.makeSuite(cls))
|
||||||
|
def case_pred(test):
|
||||||
|
if match_tests is None:
|
||||||
|
return True
|
||||||
|
for name in test.id().split("."):
|
||||||
|
if fnmatch.fnmatchcase(name, match_tests):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
_filter_suite(suite, case_pred)
|
||||||
_run_suite(suite)
|
_run_suite(suite)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -137,6 +137,11 @@ Tools/Demos
|
||||||
Tests
|
Tests
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
- Issue #12626: In regrtest, allow to filter tests using a glob filter
|
||||||
|
with the ``-m`` (or ``--match``) option. This works with all test cases
|
||||||
|
using the unittest module. This is useful with long test suites
|
||||||
|
such as test_io or test_subprocess.
|
||||||
|
|
||||||
- Issue #12624: It is now possible to fail after the first failure when
|
- Issue #12624: It is now possible to fail after the first failure when
|
||||||
running in verbose mode (``-v`` or ``-W``), by using the ``--failfast``
|
running in verbose mode (``-v`` or ``-W``), by using the ``--failfast``
|
||||||
(or ``-G``) option to regrtest. This is useful with long test suites
|
(or ``-G``) option to regrtest. This is useful with long test suites
|
||||||
|
|
Loading…
Reference in New Issue