Mercurial > hg
comparison tests/run-tests.py @ 10648:58128004cca1 stable
tests: use external coverage, mandate newer version
This removes the option for including the stdlib in coverage reports.
author | Dirkjan Ochtman <djc.ochtman@kentyde.com> |
---|---|
date | Thu, 11 Mar 2010 15:32:24 +0100 |
parents | e433002acb05 |
children | 92ff2d0b751a 4eb6311d217a |
comparison
equal
deleted
inserted
replaced
10646:86dc21148bdb | 10648:58128004cca1 |
---|---|
39 # (You could use any subset of the tests: test-s* happens to match | 39 # (You could use any subset of the tests: test-s* happens to match |
40 # enough that it's worth doing parallel runs, few enough that it | 40 # enough that it's worth doing parallel runs, few enough that it |
41 # completes fairly quickly, includes both shell and Python scripts, and | 41 # completes fairly quickly, includes both shell and Python scripts, and |
42 # includes some scripts that run daemon processes.) | 42 # includes some scripts that run daemon processes.) |
43 | 43 |
44 from distutils import version | |
44 import difflib | 45 import difflib |
45 import errno | 46 import errno |
46 import optparse | 47 import optparse |
47 import os | 48 import os |
48 import signal | 49 import signal |
108 parser.add_option("-p", "--port", type="int", | 109 parser.add_option("-p", "--port", type="int", |
109 help="port on which servers should listen" | 110 help="port on which servers should listen" |
110 " (default: $%s or %d)" % defaults['port']) | 111 " (default: $%s or %d)" % defaults['port']) |
111 parser.add_option("-r", "--retest", action="store_true", | 112 parser.add_option("-r", "--retest", action="store_true", |
112 help="retest failed tests") | 113 help="retest failed tests") |
113 parser.add_option("-s", "--cover_stdlib", action="store_true", | |
114 help="print a test coverage report inc. standard libraries") | |
115 parser.add_option("-S", "--noskips", action="store_true", | 114 parser.add_option("-S", "--noskips", action="store_true", |
116 help="don't report skip tests verbosely") | 115 help="don't report skip tests verbosely") |
117 parser.add_option("-t", "--timeout", type="int", | 116 parser.add_option("-t", "--timeout", type="int", |
118 help="kill errant tests after TIMEOUT seconds" | 117 help="kill errant tests after TIMEOUT seconds" |
119 " (default: $%s or %d)" % defaults['timeout']) | 118 " (default: $%s or %d)" % defaults['timeout']) |
153 if not os.access(hgbin, os.X_OK): | 152 if not os.access(hgbin, os.X_OK): |
154 parser.error('--local specified, but %r not found or not executable' | 153 parser.error('--local specified, but %r not found or not executable' |
155 % hgbin) | 154 % hgbin) |
156 options.with_hg = hgbin | 155 options.with_hg = hgbin |
157 | 156 |
158 options.anycoverage = (options.cover or | 157 options.anycoverage = options.cover or options.annotate |
159 options.cover_stdlib or | 158 if options.anycoverage: |
160 options.annotate) | 159 try: |
161 | 160 import coverage |
162 if options.anycoverage and options.with_hg: | 161 covver = version.StrictVersion(coverage.__version__).version |
163 # I'm not sure if this is a fundamental limitation or just a | 162 if covver < (3, 3): |
164 # bug. But I don't want to waste people's time and energy doing | 163 parser.error('coverage options require coverage 3.3 or later') |
165 # test runs that don't give the results they want. | 164 except ImportError: |
166 parser.error("sorry, coverage options do not work when --with-hg " | 165 parser.error('coverage options now require the coverage package') |
167 "or --local specified") | 166 |
167 if options.anycoverage and options.local: | |
168 # this needs some path mangling somewhere, I guess | |
169 parser.error("sorry, coverage options do not work when --local " | |
170 "is specified") | |
168 | 171 |
169 global vlog | 172 global vlog |
170 if options.verbose: | 173 if options.verbose: |
171 if options.jobs > 1 or options.child is not None: | 174 if options.jobs > 1 or options.child is not None: |
172 pid = "[%d]" % os.getpid() | 175 pid = "[%d]" % os.getpid() |
388 for line in lines: | 391 for line in lines: |
389 f.write(line + '\n') | 392 f.write(line + '\n') |
390 f.close() | 393 f.close() |
391 | 394 |
392 if options.anycoverage: | 395 if options.anycoverage: |
393 vlog("# Installing coverage wrapper") | 396 custom = os.path.join(TESTDIR, 'sitecustomize.py') |
394 os.environ['COVERAGE_FILE'] = COVERAGE_FILE | 397 target = os.path.join(PYTHONDIR, 'sitecustomize.py') |
395 if os.path.exists(COVERAGE_FILE): | 398 vlog('# Installing coverage trigger to %s' % target) |
396 os.unlink(COVERAGE_FILE) | 399 shutil.copyfile(custom, target) |
397 # Create a wrapper script to invoke hg via coverage.py | 400 rc = os.path.join(TESTDIR, '.coveragerc') |
398 os.rename(os.path.join(BINDIR, "hg"), os.path.join(BINDIR, "_hg.py")) | 401 vlog('# Installing coverage rc to %s' % rc) |
399 f = open(os.path.join(BINDIR, 'hg'), 'w') | 402 os.environ['COVERAGE_PROCESS_START'] = rc |
400 f.write('#!' + sys.executable + '\n') | 403 fn = os.path.join(INST, '..', '.coverage') |
401 f.write('import sys, os; os.execv(sys.executable, [sys.executable, ' | 404 os.environ['COVERAGE_FILE'] = fn |
402 '"%s", "-x", "-p", "%s"] + sys.argv[1:])\n' % | |
403 (os.path.join(TESTDIR, 'coverage.py'), | |
404 os.path.join(BINDIR, '_hg.py'))) | |
405 f.close() | |
406 os.chmod(os.path.join(BINDIR, 'hg'), 0700) | |
407 | 405 |
408 def outputcoverage(options): | 406 def outputcoverage(options): |
409 | 407 |
410 vlog('# Producing coverage report') | 408 vlog('# Producing coverage report') |
411 os.chdir(PYTHONDIR) | 409 os.chdir(PYTHONDIR) |
412 | 410 |
413 def covrun(*args): | 411 def covrun(*args): |
414 start = sys.executable, os.path.join(TESTDIR, 'coverage.py') | 412 cmd = 'coverage %s' % ' '.join(args) |
415 cmd = '"%s" "%s" %s' % (start[0], start[1], ' '.join(args)) | |
416 vlog('# Running: %s' % cmd) | 413 vlog('# Running: %s' % cmd) |
417 os.system(cmd) | 414 os.system(cmd) |
418 | 415 |
419 omit = [BINDIR, TESTDIR, PYTHONDIR] | 416 if options.child: |
420 if not options.cover_stdlib: | 417 return |
421 # Exclude as system paths (ignoring empty strings seen on win) | 418 |
422 omit += [x for x in sys.path if x != ''] | 419 covrun('-c') |
423 omit = ','.join(omit) | 420 omit = ','.join([BINDIR, TESTDIR]) |
424 | |
425 covrun('-c') # combine from parallel processes | |
426 for fn in os.listdir(TESTDIR): | |
427 if fn.startswith('.coverage.'): | |
428 os.unlink(os.path.join(TESTDIR, fn)) | |
429 | |
430 covrun('-i', '-r', '"--omit=%s"' % omit) # report | 421 covrun('-i', '-r', '"--omit=%s"' % omit) # report |
431 if options.annotate: | 422 if options.annotate: |
432 adir = os.path.join(TESTDIR, 'annotated') | 423 adir = os.path.join(TESTDIR, 'annotated') |
433 if not os.path.isdir(adir): | 424 if not os.path.isdir(adir): |
434 os.mkdir(adir) | 425 os.mkdir(adir) |
666 | 657 |
667 optcopy = dict(options.__dict__) | 658 optcopy = dict(options.__dict__) |
668 optcopy['jobs'] = 1 | 659 optcopy['jobs'] = 1 |
669 if optcopy['with_hg'] is None: | 660 if optcopy['with_hg'] is None: |
670 optcopy['with_hg'] = os.path.join(BINDIR, "hg") | 661 optcopy['with_hg'] = os.path.join(BINDIR, "hg") |
662 optcopy.pop('anycoverage', None) | |
663 | |
671 opts = [] | 664 opts = [] |
672 for opt, value in optcopy.iteritems(): | 665 for opt, value in optcopy.iteritems(): |
673 name = '--' + opt.replace('_', '-') | 666 name = '--' + opt.replace('_', '-') |
674 if value is True: | 667 if value is True: |
675 opts.append(name) | 668 opts.append(name) |
727 print "Failed %s: %s" % (s[0], s[1]) | 720 print "Failed %s: %s" % (s[0], s[1]) |
728 | 721 |
729 _checkhglib("Tested") | 722 _checkhglib("Tested") |
730 print "# Ran %d tests, %d skipped, %d failed." % ( | 723 print "# Ran %d tests, %d skipped, %d failed." % ( |
731 tested, skipped, failed) | 724 tested, skipped, failed) |
725 | |
726 if options.anycoverage: | |
727 outputcoverage(options) | |
732 sys.exit(failures != 0) | 728 sys.exit(failures != 0) |
733 | 729 |
734 def runtests(options, tests): | 730 def runtests(options, tests): |
735 global DAEMON_PIDS, HGRCPATH | 731 global DAEMON_PIDS, HGRCPATH |
736 DAEMON_PIDS = os.environ["DAEMON_PIDS"] = os.path.join(HGTMP, 'daemon.pids') | 732 DAEMON_PIDS = os.environ["DAEMON_PIDS"] = os.path.join(HGTMP, 'daemon.pids') |