mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2024-12-24 15:16:41 +00:00
117 lines
4.0 KiB
Python
117 lines
4.0 KiB
Python
|
|
||
|
import sys
|
||
|
from coverage import coverage
|
||
|
from coverage.results import Numbers
|
||
|
from coverage.summary import SummaryReporter
|
||
|
from twisted.python import usage
|
||
|
|
||
|
# this is an adaptation of the code behind "coverage report", modified to
|
||
|
# display+sortby "lines uncovered", which (IMHO) is more important of a
|
||
|
# metric than lines covered or percentage covered. Concentrating on the files
|
||
|
# with the most uncovered lines encourages getting the tree and test suite
|
||
|
# into a state that provides full line-coverage on all files.
|
||
|
|
||
|
# much of this code was adapted from coverage/summary.py in the 'coverage'
|
||
|
# distribution, and is used under their BSD license.
|
||
|
|
||
|
class Options(usage.Options):
|
||
|
optParameters = [
|
||
|
("sortby", "s", "uncovered", "how to sort: uncovered, covered, name"),
|
||
|
]
|
||
|
|
||
|
class MyReporter(SummaryReporter):
|
||
|
def report(self, outfile=None, sortby="uncovered"):
|
||
|
self.find_code_units(None, ["/System", "/Library", "/usr/lib",
|
||
|
"support/lib", "src/allmydata/test"])
|
||
|
|
||
|
# Prepare the formatting strings
|
||
|
max_name = max([len(cu.name) for cu in self.code_units] + [5])
|
||
|
fmt_name = "%%- %ds " % max_name
|
||
|
fmt_err = "%s %s: %s\n"
|
||
|
header1 = (fmt_name % "" ) + " Statements "
|
||
|
header2 = (fmt_name % "Name") + " Uncovered Covered"
|
||
|
fmt_coverage = fmt_name + "%9d %7d "
|
||
|
if self.branches:
|
||
|
header1 += " Branches "
|
||
|
header2 += " Found Excutd"
|
||
|
fmt_coverage += " %6d %6d"
|
||
|
header1 += " Percent"
|
||
|
header2 += " Covered"
|
||
|
fmt_coverage += " %7d%%"
|
||
|
if self.show_missing:
|
||
|
header1 += " "
|
||
|
header2 += " Missing"
|
||
|
fmt_coverage += " %s"
|
||
|
rule = "-" * len(header1) + "\n"
|
||
|
header1 += "\n"
|
||
|
header2 += "\n"
|
||
|
fmt_coverage += "\n"
|
||
|
|
||
|
if not outfile:
|
||
|
outfile = sys.stdout
|
||
|
|
||
|
# Write the header
|
||
|
outfile.write(header1)
|
||
|
outfile.write(header2)
|
||
|
outfile.write(rule)
|
||
|
|
||
|
total = Numbers()
|
||
|
total_uncovered = 0
|
||
|
|
||
|
lines = []
|
||
|
for cu in self.code_units:
|
||
|
try:
|
||
|
analysis = self.coverage._analyze(cu)
|
||
|
nums = analysis.numbers
|
||
|
uncovered = nums.n_statements - nums.n_executed
|
||
|
total_uncovered += uncovered
|
||
|
args = (cu.name, uncovered, nums.n_executed)
|
||
|
if self.branches:
|
||
|
args += (nums.n_branches, nums.n_executed_branches)
|
||
|
args += (nums.pc_covered,)
|
||
|
if self.show_missing:
|
||
|
args += (analysis.missing_formatted(),)
|
||
|
if sortby == "covered":
|
||
|
sortkey = nums.pc_covered
|
||
|
elif sortby == "uncovered":
|
||
|
sortkey = uncovered
|
||
|
else:
|
||
|
sortkey = cu.name
|
||
|
lines.append((sortkey, fmt_coverage % args))
|
||
|
total += nums
|
||
|
except KeyboardInterrupt: # pragma: no cover
|
||
|
raise
|
||
|
except:
|
||
|
if not self.ignore_errors:
|
||
|
typ, msg = sys.exc_info()[:2]
|
||
|
outfile.write(fmt_err % (cu.name, typ.__name__, msg))
|
||
|
lines.sort()
|
||
|
if sortby in ("uncovered", "covered"):
|
||
|
lines.reverse()
|
||
|
for sortkey,line in lines:
|
||
|
outfile.write(line)
|
||
|
|
||
|
if total.n_files > 1:
|
||
|
outfile.write(rule)
|
||
|
args = ("TOTAL", total_uncovered, total.n_executed)
|
||
|
if self.branches:
|
||
|
args += (total.n_branches, total.n_executed_branches)
|
||
|
args += (total.pc_covered,)
|
||
|
if self.show_missing:
|
||
|
args += ("",)
|
||
|
outfile.write(fmt_coverage % args)
|
||
|
|
||
|
def report(o):
|
||
|
c = coverage()
|
||
|
c.load()
|
||
|
r = MyReporter(c, show_missing=False, ignore_errors=False)
|
||
|
r.report(sortby=o['sortby'])
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
o = Options()
|
||
|
o.parseOptions()
|
||
|
report(o)
|
||
|
|
||
|
|
||
|
|