summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorBarry Warsaw <barry@python.org>2004-02-07 22:43:03 (GMT)
committerBarry Warsaw <barry@python.org>2004-02-07 22:43:03 (GMT)
commit3b6d025d9bc6a0109e9a2ebd28a4864e8007193a (patch)
treee4c2b4e57a475a1384868518ae832020e90f5870 /Lib
parent5c5eb8634703b7e463ade6707d2b6f1a80769286 (diff)
downloadcpython-3b6d025d9bc6a0109e9a2ebd28a4864e8007193a.zip
cpython-3b6d025d9bc6a0109e9a2ebd28a4864e8007193a.tar.gz
cpython-3b6d025d9bc6a0109e9a2ebd28a4864e8007193a.tar.bz2
Patch #868499, adds -T option for code coverage. The implementation is a
fairly simpleminded adaptation of Zope3's test.py -T flag. I also changed some booleans to use True/False where appropriate.
Diffstat (limited to 'Lib')
-rwxr-xr-xLib/test/regrtest.py81
1 files changed, 51 insertions, 30 deletions
diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py
index 1d4eaec..8f5da02 100755
--- a/Lib/test/regrtest.py
+++ b/Lib/test/regrtest.py
@@ -19,6 +19,7 @@ Command line options:
-u: use -- specify which special resource intensive tests to run
-h: help -- print this text and exit
-t: threshold -- call gc.set_threshold(N)
+-T: coverage -- turn on code coverage using the trace module
If non-option arguments are present, they are names for tests to run,
unless -x is given, in which case they are names for tests not to run.
@@ -26,6 +27,8 @@ If no test names are given, all tests are run.
-v is incompatible with -g and does not compare test output files.
+-T turns on code coverage tracing with the trace module.
+
-s means to run only a single test and exit. This is useful when
doing memory analysis on the Python interpreter (which tend to consume
too many resources to run the full regression test non-stop). The
@@ -68,13 +71,13 @@ example, to run all the tests except for the bsddb tests, give the
option '-uall,-bsddb'.
"""
-import sys
import os
+import sys
import getopt
-import traceback
import random
-import cStringIO
import warnings
+import cStringIO
+import traceback
# I see no other way to suppress these warnings;
# putting them in test_grammar.py has no effect:
@@ -113,9 +116,9 @@ def usage(code, msg=''):
sys.exit(code)
-def main(tests=None, testdir=None, verbose=0, quiet=0, generate=0,
- exclude=0, single=0, randomize=0, fromfile=None, findleaks=0,
- use_resources=None):
+def main(tests=None, testdir=None, verbose=0, quiet=False, generate=False,
+ exclude=False, single=False, randomize=False, fromfile=None,
+ findleaks=False, use_resources=None, trace=False):
"""Execute a test suite.
This also parses command-line options and modifies its behavior
@@ -132,19 +135,19 @@ def main(tests=None, testdir=None, verbose=0, quiet=0, generate=0,
command-line will be used. If that's empty, too, then all *.py
files beginning with test_ will be used.
- The other default arguments (verbose, quiet, generate, exclude,
- single, randomize, findleaks, and use_resources) allow programmers
- calling main() directly to set the values that would normally be
- set by flags on the command line.
-
+ The other default arguments (verbose, quiet, generate, exclude, single,
+ randomize, findleaks, use_resources, and trace) allow programmers calling
+ main() directly to set the values that would normally be set by flags on
+ the command line.
"""
test_support.record_original_stdout(sys.stdout)
try:
- opts, args = getopt.getopt(sys.argv[1:], 'hvgqxsrf:lu:t:',
+ opts, args = getopt.getopt(sys.argv[1:], 'hvgqxsrf:lu:t:T',
['help', 'verbose', 'quiet', 'generate',
'exclude', 'single', 'random', 'fromfile',
- 'findleaks', 'use=', 'threshold='])
+ 'findleaks', 'use=', 'threshold=', 'trace',
+ ])
except getopt.error, msg:
usage(2, msg)
@@ -157,23 +160,25 @@ def main(tests=None, testdir=None, verbose=0, quiet=0, generate=0,
elif o in ('-v', '--verbose'):
verbose += 1
elif o in ('-q', '--quiet'):
- quiet = 1;
+ quiet = True;
verbose = 0
elif o in ('-g', '--generate'):
- generate = 1
+ generate = True
elif o in ('-x', '--exclude'):
- exclude = 1
+ exclude = True
elif o in ('-s', '--single'):
- single = 1
+ single = True
elif o in ('-r', '--randomize'):
- randomize = 1
+ randomize = True
elif o in ('-f', '--fromfile'):
fromfile = a
elif o in ('-l', '--findleaks'):
- findleaks = 1
+ findleaks = True
elif o in ('-t', '--threshold'):
import gc
gc.set_threshold(int(a))
+ elif o in ('-T', '--coverage'):
+ trace = True
elif o in ('-u', '--use'):
u = [x.lower() for x in a.split(',')]
for r in u:
@@ -206,7 +211,7 @@ def main(tests=None, testdir=None, verbose=0, quiet=0, generate=0,
import gc
except ImportError:
print 'No GC available, disabling findleaks.'
- findleaks = 0
+ findleaks = False
else:
# Uncomment the line below to report garbage that is not
# freeable by reference counting alone. By default only
@@ -253,6 +258,11 @@ def main(tests=None, testdir=None, verbose=0, quiet=0, generate=0,
tests = tests[:1]
if randomize:
random.shuffle(tests)
+ if trace:
+ import trace
+ tracer = trace.Trace(ignoredirs=[sys.prefix, sys.exec_prefix],
+ trace=False, count=True)
+ coverdir = os.path.join(os.getcwd(), 'coverage')
test_support.verbose = verbose # Tell tests to be moderately quiet
test_support.use_resources = use_resources
save_modules = sys.modules.keys()
@@ -260,15 +270,21 @@ def main(tests=None, testdir=None, verbose=0, quiet=0, generate=0,
if not quiet:
print test
sys.stdout.flush()
- ok = runtest(test, generate, verbose, quiet, testdir)
- if ok > 0:
- good.append(test)
- elif ok == 0:
- bad.append(test)
+ if trace:
+ # If we're tracing code coverage, then we don't exit with status
+ # if on a false return value from main.
+ tracer.runctx('runtest(test, generate, verbose, quiet, testdir)',
+ globals=globals(), locals=vars())
else:
- skipped.append(test)
- if ok == -2:
- resource_denieds.append(test)
+ ok = runtest(test, generate, verbose, quiet, testdir)
+ if ok > 0:
+ good.append(test)
+ elif ok == 0:
+ bad.append(test)
+ else:
+ skipped.append(test)
+ if ok == -2:
+ resource_denieds.append(test)
if findleaks:
gc.collect()
if gc.garbage:
@@ -330,6 +346,10 @@ def main(tests=None, testdir=None, verbose=0, quiet=0, generate=0,
else:
os.unlink(filename)
+ if trace:
+ r = tracer.results()
+ r.write_results(show_missing=True, summary=True, coverdir=coverdir)
+
sys.exit(len(bad) > 0)
@@ -362,7 +382,7 @@ def findtests(testdir=None, stdtests=STDTESTS, nottests=NOTTESTS):
tests.sort()
return stdtests + tests
-def runtest(test, generate, verbose, quiet, testdir = None):
+def runtest(test, generate, verbose, quiet, testdir=None):
"""Run a single test.
test -- the name of the test
generate -- if true, generate output, instead of running the test
@@ -372,7 +392,8 @@ def runtest(test, generate, verbose, quiet, testdir = None):
testdir -- test directory
"""
test_support.unload(test)
- if not testdir: testdir = findtestdir()
+ if not testdir:
+ testdir = findtestdir()
outputdir = os.path.join(testdir, "output")
outputfile = os.path.join(outputdir, test)
if verbose: