]> granicus.if.org Git - python/commitdiff
[2.7] bpo-30236: Backported regrtest options -m and -G. (#1394)
authorSerhiy Storchaka <storchaka@gmail.com>
Wed, 3 May 2017 21:23:50 +0000 (00:23 +0300)
committerGitHub <noreply@github.com>
Wed, 3 May 2017 21:23:50 +0000 (00:23 +0300)
Lib/test/regrtest.py
Lib/test/support/__init__.py
Misc/NEWS

index e49bcb962fb8de2851a6af5e50dd25c2bdf35499..413d7f906490749bbaf149619d40dad0db822956 100755 (executable)
@@ -37,6 +37,8 @@ Selecting tests
 -f/--fromfile   -- read names of tests to run from a file (see below)
 -x/--exclude    -- arguments are tests to *exclude*
 -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,...
                 -- specify which special resource intensive tests to run
 -M/--memlimit LIMIT
@@ -242,7 +244,7 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
          findleaks=False, use_resources=None, trace=False, coverdir='coverage',
          runleaks=False, huntrleaks=False, verbose2=False, print_slow=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.
 
     This also parses command-line options and modifies its behavior
@@ -268,12 +270,13 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
 
     test_support.record_original_stdout(sys.stdout)
     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',
              'exclude', 'single', 'slow', 'randomize', 'fromfile=', 'findleaks',
              'use=', 'threshold=', 'trace', 'coverdir=', 'nocoverdir',
              'runleaks', 'huntrleaks=', 'memlimit=', 'randseed=',
-             'multiprocess=', 'slaveargs=', 'forever', 'header', 'pgo'])
+             'multiprocess=', 'slaveargs=', 'forever', 'header', 'pgo',
+             'failfast', 'match='])
     except getopt.error, msg:
         usage(2, msg)
 
@@ -291,6 +294,8 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
             verbose2 = True
         elif o in ('-W', '--verbose3'):
             verbose3 = True
+        elif o in ('-G', '--failfast'):
+            failfast = True
         elif o in ('-q', '--quiet'):
             quiet = True;
             verbose = 0
@@ -306,6 +311,8 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
             random_seed = int(a)
         elif o in ('-f', '--fromfile'):
             fromfile = a
+        elif o in ('-m', '--match'):
+            match_tests = a
         elif o in ('-l', '--findleaks'):
             findleaks = True
         elif o in ('-L', '--runleaks'):
@@ -380,6 +387,8 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
         usage(2, "-T and -j don't go together!")
     if use_mp and findleaks:
         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 = []
     bad = []
@@ -514,6 +523,8 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
                 args_tuple = (
                     (test, verbose, quiet),
                     dict(huntrleaks=huntrleaks, use_resources=use_resources,
+                         failfast=failfast,
+                         match_tests=match_tests,
                          pgo=pgo)
                 )
                 yield (test, args_tuple)
@@ -609,7 +620,9 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
                               globals=globals(), locals=vars())
             else:
                 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)
                     if verbose3 and result[0] == FAILED:
                         if not pgo:
@@ -743,7 +756,8 @@ def findtests(testdir=None, stdtests=STDTESTS, nottests=NOTTESTS):
     return stdtests + sorted(tests)
 
 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.
 
     test -- the name of the test
@@ -769,6 +783,9 @@ def runtest(test, verbose, quiet,
     if use_resources is not None:
         test_support.use_resources = use_resources
     try:
+        test_support.match_tests = match_tests
+        if failfast:
+            test_support.failfast = True
         return runtest_inner(test, verbose, quiet, huntrleaks, pgo)
     finally:
         cleanup_test_droppings(test, verbose)
index fa75ff881d92d7898d5908b03313883dbcefbf1b..ef0ced6fae4e57ab49ccb4fbe36348057fbf2d2d 100644 (file)
@@ -5,6 +5,7 @@ if __name__ != 'test.support':
 
 import contextlib
 import errno
+import fnmatch
 import functools
 import gc
 import socket
@@ -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
                          # 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.
@@ -1462,11 +1465,23 @@ def check_impl_detail(**guards):
     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):
     """Run tests from a unittest.TestSuite-derived class."""
     if verbose:
-        runner = unittest.TextTestRunner(sys.stdout, verbosity=2)
+        runner = unittest.TextTestRunner(sys.stdout, verbosity=2,
+                                         failfast=failfast)
     else:
         runner = BasicTestRunner()
 
@@ -1497,6 +1512,14 @@ def run_unittest(*classes):
             suite.addTest(cls)
         else:
             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)
 
 #=======================================================================
index 50a2c78ac9e725b6cdb2aaac23d3bdbbe210c818..47a00a604278a23da11edd52aca61f6595a1b8b2 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -148,6 +148,9 @@ Build
 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
   package can be run as a script.  This is equivalent to running the
   test.regrtest module as a script.