Commit 74f0db88 authored by Serhiy Storchaka's avatar Serhiy Storchaka Committed by GitHub

[2.7] bpo-30236: Backported regrtest options -m and -G. (#1394)

parent 8cf7ea22
...@@ -37,6 +37,8 @@ Selecting tests ...@@ -37,6 +37,8 @@ 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)
-u/--use RES1,RES2,... -u/--use RES1,RES2,...
-- specify which special resource intensive tests to run -- specify which special resource intensive tests to run
-M/--memlimit LIMIT -M/--memlimit LIMIT
...@@ -242,7 +244,7 @@ def main(tests=None, testdir=None, verbose=0, quiet=False, ...@@ -242,7 +244,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, pgo=False): header=False, pgo=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
...@@ -268,12 +270,13 @@ def main(tests=None, testdir=None, verbose=0, quiet=False, ...@@ -268,12 +270,13 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
test_support.record_original_stdout(sys.stdout) test_support.record_original_stdout(sys.stdout)
try: try:
opts, args = getopt.getopt(sys.argv[1:], 'hvqxsSrf:lu:t:TD:NLR:FwWM:j:P', opts, args = getopt.getopt(sys.argv[1:], 'hvqxsSrf:lu:t:TD:NLR:FwWM:j:PGm:',
['help', 'verbose', 'verbose2', 'verbose3', 'quiet', ['help', 'verbose', 'verbose2', 'verbose3', 'quiet',
'exclude', 'single', 'slow', 'randomize', 'fromfile=', 'findleaks', 'exclude', 'single', 'slow', 'randomize', 'fromfile=', 'findleaks',
'use=', 'threshold=', 'trace', 'coverdir=', 'nocoverdir', 'use=', 'threshold=', 'trace', 'coverdir=', 'nocoverdir',
'runleaks', 'huntrleaks=', 'memlimit=', 'randseed=', 'runleaks', 'huntrleaks=', 'memlimit=', 'randseed=',
'multiprocess=', 'slaveargs=', 'forever', 'header', 'pgo']) 'multiprocess=', 'slaveargs=', 'forever', 'header', 'pgo',
'failfast', 'match='])
except getopt.error, msg: except getopt.error, msg:
usage(2, msg) usage(2, msg)
...@@ -291,6 +294,8 @@ def main(tests=None, testdir=None, verbose=0, quiet=False, ...@@ -291,6 +294,8 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
verbose2 = True verbose2 = True
elif o in ('-W', '--verbose3'): elif o in ('-W', '--verbose3'):
verbose3 = True verbose3 = True
elif o in ('-G', '--failfast'):
failfast = True
elif o in ('-q', '--quiet'): elif o in ('-q', '--quiet'):
quiet = True; quiet = True;
verbose = 0 verbose = 0
...@@ -306,6 +311,8 @@ def main(tests=None, testdir=None, verbose=0, quiet=False, ...@@ -306,6 +311,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'):
...@@ -380,6 +387,8 @@ def main(tests=None, testdir=None, verbose=0, quiet=False, ...@@ -380,6 +387,8 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
usage(2, "-T and -j don't go together!") usage(2, "-T and -j don't go together!")
if use_mp and findleaks: if use_mp and findleaks:
usage(2, "-l and -j don't go together!") usage(2, "-l and -j don't go together!")
if failfast and not (verbose or verbose3):
usage("-G/--failfast needs either -v or -W")
good = [] good = []
bad = [] bad = []
...@@ -514,6 +523,8 @@ def main(tests=None, testdir=None, verbose=0, quiet=False, ...@@ -514,6 +523,8 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
args_tuple = ( args_tuple = (
(test, verbose, quiet), (test, verbose, quiet),
dict(huntrleaks=huntrleaks, use_resources=use_resources, dict(huntrleaks=huntrleaks, use_resources=use_resources,
failfast=failfast,
match_tests=match_tests,
pgo=pgo) pgo=pgo)
) )
yield (test, args_tuple) yield (test, args_tuple)
...@@ -609,7 +620,9 @@ def main(tests=None, testdir=None, verbose=0, quiet=False, ...@@ -609,7 +620,9 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
globals=globals(), locals=vars()) globals=globals(), locals=vars())
else: else:
try: try:
result = runtest(test, verbose, quiet, huntrleaks, None, pgo) result = runtest(test, verbose, quiet, huntrleaks, None, pgo,
failfast=failfast,
match_tests=match_tests)
accumulate_result(test, result) accumulate_result(test, result)
if verbose3 and result[0] == FAILED: if verbose3 and result[0] == FAILED:
if not pgo: if not pgo:
...@@ -743,7 +756,8 @@ def findtests(testdir=None, stdtests=STDTESTS, nottests=NOTTESTS): ...@@ -743,7 +756,8 @@ def findtests(testdir=None, stdtests=STDTESTS, nottests=NOTTESTS):
return stdtests + sorted(tests) return stdtests + sorted(tests)
def runtest(test, verbose, quiet, def runtest(test, verbose, quiet,
huntrleaks=False, use_resources=None, pgo=False): huntrleaks=False, use_resources=None, pgo=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
...@@ -769,6 +783,9 @@ def runtest(test, verbose, quiet, ...@@ -769,6 +783,9 @@ def runtest(test, verbose, quiet,
if use_resources is not None: if use_resources is not None:
test_support.use_resources = use_resources test_support.use_resources = use_resources
try: try:
test_support.match_tests = match_tests
if failfast:
test_support.failfast = True
return runtest_inner(test, verbose, quiet, huntrleaks, pgo) return runtest_inner(test, verbose, quiet, huntrleaks, pgo)
finally: finally:
cleanup_test_droppings(test, verbose) cleanup_test_droppings(test, verbose)
......
...@@ -5,6 +5,7 @@ if __name__ != 'test.support': ...@@ -5,6 +5,7 @@ if __name__ != 'test.support':
import contextlib import contextlib
import errno import errno
import fnmatch
import functools import functools
import gc import gc
import socket import socket
...@@ -165,6 +166,8 @@ use_resources = None # Flag set to [] by regrtest.py ...@@ -165,6 +166,8 @@ use_resources = None # Flag set to [] by regrtest.py
max_memuse = 0 # Disable bigmem tests (they will still be run with 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
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.
...@@ -1462,11 +1465,23 @@ def check_impl_detail(**guards): ...@@ -1462,11 +1465,23 @@ 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."""
if verbose: if verbose:
runner = unittest.TextTestRunner(sys.stdout, verbosity=2) runner = unittest.TextTestRunner(sys.stdout, verbosity=2,
failfast=failfast)
else: else:
runner = BasicTestRunner() runner = BasicTestRunner()
...@@ -1497,6 +1512,14 @@ def run_unittest(*classes): ...@@ -1497,6 +1512,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)
#======================================================================= #=======================================================================
......
...@@ -148,6 +148,9 @@ Build ...@@ -148,6 +148,9 @@ Build
Tests Tests
----- -----
- bpo-30236: Backported test.regrtest options -m/--match and -G/--failfast
from Python 3.
- bpo-30223: To unify running tests in Python 2.7 and Python 3, the test - bpo-30223: To unify running tests in Python 2.7 and Python 3, the test
package can be run as a script. This is equivalent to running the package can be run as a script. This is equivalent to running the
test.regrtest module as a script. test.regrtest module as a script.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment