mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-01-26 14:19:32 +00:00
tests: add support for figleaf code-coverage gathering
This commit is contained in:
parent
8b96fabf52
commit
e5ba7f15d9
@ -46,3 +46,6 @@
|
||||
^(dapper|sid)/debian/files$
|
||||
^build($|/)
|
||||
^build-stamp$
|
||||
^\.figleaf$
|
||||
^coverage-html($|/)
|
||||
^twisted/plugins/dropin\.cache$
|
||||
|
5
Makefile
5
Makefile
@ -15,6 +15,11 @@ run-client3:
|
||||
test:
|
||||
trial allmydata
|
||||
|
||||
test-figleaf:
|
||||
trial --reporter=bwverbose-figleaf allmydata
|
||||
figleaf2html -d coverage-html -x allmydata/test/figleaf.excludes
|
||||
# after doing test-figleaf, point your browser at coverage-html/index.html
|
||||
|
||||
create_dirs:
|
||||
mkdir -p queen-basedir
|
||||
mkdir -p client-basedir
|
||||
|
2
allmydata/test/figleaf.excludes
Normal file
2
allmydata/test/figleaf.excludes
Normal file
@ -0,0 +1,2 @@
|
||||
^/home/warner/stuff/python/twisted/Twisted/
|
||||
^/var/lib
|
127
allmydata/test/trial_figleaf.py
Normal file
127
allmydata/test/trial_figleaf.py
Normal file
@ -0,0 +1,127 @@
|
||||
|
||||
"""A Trial IReporter plugin that gathers figleaf code-coverage information.
|
||||
|
||||
Once this plugin is installed, trial can be invoked with one of two new
|
||||
--reporter options:
|
||||
|
||||
trial --reporter=verbose-figleaf ARGS
|
||||
trial --reporter-bwverbose-figleaf ARGS
|
||||
|
||||
Once such a test run has finished, there will be a .figleaf file in the
|
||||
top-level directory. This file can be turned into a directory of .html files
|
||||
(with index.html as the starting point) by running:
|
||||
|
||||
figleaf2html -d OUTPUTDIR [-x EXCLUDEFILE]
|
||||
|
||||
Figleaf thinks of everyting in terms of absolute filenames rather than
|
||||
modules. The EXCLUDEFILE may be necessary to keep it from providing reports
|
||||
on non-Code-Under-Test files that live in unusual locations. In particular,
|
||||
if you use extra PYTHONPATH arguments to point at some alternate version of
|
||||
an upstream library (like Twisted), or if something like debian's
|
||||
python-support puts symlinks to .py files in sys.path but not the .py files
|
||||
themselves, figleaf will present coverage information on both of these. The
|
||||
EXCLUDEFILE option might help to inhibit these.
|
||||
|
||||
Other figleaf problems:
|
||||
|
||||
the annotated code files are written to BASENAME(file).html, which results
|
||||
in collisions between similarly-named source files.
|
||||
|
||||
The line-wise coverage information isn't quite right. Blank lines are
|
||||
counted as unreached code, lambdas aren't quite right, and some multiline
|
||||
comments (docstrings?) aren't quite right.
|
||||
|
||||
"""
|
||||
|
||||
# TODO: pull some of figleaf into our tree so we can customize it more
|
||||
# easily.
|
||||
|
||||
from twisted.trial.reporter import TreeReporter, VerboseTextReporter
|
||||
|
||||
# These plugins are registered via twisted/plugins/allmydata_trial.py . See
|
||||
# the notes there for an explanation of how that works.
|
||||
|
||||
|
||||
|
||||
# Reporters don't really get told about the suite starting and stopping.
|
||||
|
||||
# The Reporter class is imported before the test classes are.
|
||||
|
||||
# The test classes are imported before the Reporter is created. To get
|
||||
# control earlier than that requires modifying twisted/scripts/trial.py .
|
||||
|
||||
# Then Reporter.__init__ is called.
|
||||
|
||||
# Then tests run, calling things like write() and addSuccess(). Each test is
|
||||
# framed by a startTest/stopTest call.
|
||||
|
||||
# Then the results are emitted, calling things like printErrors,
|
||||
# printSummary, and wasSuccessful.
|
||||
|
||||
# So for code-coverage (not including import), start in __init__ and finish
|
||||
# in printSummary. To include import, we have to start in our own import and
|
||||
# finish in printSummary.
|
||||
|
||||
import figleaf
|
||||
figleaf.start()
|
||||
|
||||
class FigleafReporter(TreeReporter):
|
||||
def __init__(self, *args, **kwargs):
|
||||
TreeReporter.__init__(self, *args, **kwargs)
|
||||
|
||||
def printSummary(self):
|
||||
figleaf.stop()
|
||||
figleaf.write_coverage(".figleaf")
|
||||
print "Figleaf results written to .figleaf"
|
||||
return TreeReporter.printSummary(self)
|
||||
|
||||
class FigleafTextReporter(VerboseTextReporter):
|
||||
def __init__(self, *args, **kwargs):
|
||||
VerboseTextReporter.__init__(self, *args, **kwargs)
|
||||
|
||||
def printSummary(self):
|
||||
figleaf.stop()
|
||||
figleaf.write_coverage(".figleaf")
|
||||
print "Figleaf results written to .figleaf"
|
||||
return VerboseTextReporter.printSummary(self)
|
||||
|
||||
class not_FigleafReporter(object):
|
||||
# this class, used as a reporter on a fully-passing test suite, doesn't
|
||||
# trigger exceptions. So it is a guide to what methods are invoked on a
|
||||
# Reporter.
|
||||
def __init__(self, *args, **kwargs):
|
||||
print "FIGLEAF HERE"
|
||||
self.r = TreeReporter(*args, **kwargs)
|
||||
self.shouldStop = self.r.shouldStop
|
||||
self.separator = self.r.separator
|
||||
self.testsRun = self.r.testsRun
|
||||
self._starting2 = False
|
||||
|
||||
def write(self, *args):
|
||||
if not self._starting2:
|
||||
self._starting2 = True
|
||||
print "FIRST WRITE"
|
||||
return self.r.write(*args)
|
||||
|
||||
def startTest(self, *args, **kwargs):
|
||||
return self.r.startTest(*args, **kwargs)
|
||||
|
||||
def stopTest(self, *args, **kwargs):
|
||||
return self.r.stopTest(*args, **kwargs)
|
||||
|
||||
def addSuccess(self, *args, **kwargs):
|
||||
return self.r.addSuccess(*args, **kwargs)
|
||||
|
||||
def printErrors(self, *args, **kwargs):
|
||||
return self.r.printErrors(*args, **kwargs)
|
||||
|
||||
def writeln(self, *args, **kwargs):
|
||||
return self.r.writeln(*args, **kwargs)
|
||||
|
||||
def printSummary(self, *args, **kwargs):
|
||||
print "PRINT SUMMARY"
|
||||
return self.r.printSummary(*args, **kwargs)
|
||||
|
||||
def wasSuccessful(self, *args, **kwargs):
|
||||
return self.r.wasSuccessful(*args, **kwargs)
|
||||
|
48
twisted/plugins/allmydata_trial.py
Normal file
48
twisted/plugins/allmydata_trial.py
Normal file
@ -0,0 +1,48 @@
|
||||
#! /usr/bin/python
|
||||
|
||||
from zope.interface import implements
|
||||
from twisted.trial.itrial import IReporter
|
||||
from twisted.plugin import IPlugin
|
||||
|
||||
# register a plugin that can create our FigleafReporter. The reporter itself
|
||||
# lives in a separate place
|
||||
|
||||
# note that this .py file is *not* in a package: there is no __init__.py in
|
||||
# our parent directory. This is important, because otherwise ours would fight
|
||||
# with Twisted's. When trial looks for plugins, it merely executes all the
|
||||
# *.py files it finds in and twisted/plugins/ subdirectories of anything on
|
||||
# sys.path . The namespace that results from executing these .py files is
|
||||
# examined for instances which provide both IPlugin and the target interface
|
||||
# (in this case, trial is looking for IReporter instances). Each such
|
||||
# instance tells the application how to create a plugin by naming the module
|
||||
# and class that should be instantiated.
|
||||
|
||||
# When installing our package via setup.py, arrange for this file to be
|
||||
# installed to the system-wide twisted/plugins/ directory.
|
||||
|
||||
class _Reporter(object):
|
||||
implements(IPlugin, IReporter)
|
||||
|
||||
def __init__(self, name, module, description, longOpt, shortOpt, klass):
|
||||
self.name = name
|
||||
self.module = module
|
||||
self.description = description
|
||||
self.longOpt = longOpt
|
||||
self.shortOpt = shortOpt
|
||||
self.klass = klass
|
||||
|
||||
|
||||
fig = _Reporter("Figleaf Code-Coverage Reporter",
|
||||
"allmydata.test.trial_figleaf",
|
||||
description="verbose color output (with figleaf coverage)",
|
||||
longOpt="verbose-figleaf",
|
||||
shortOpt="f",
|
||||
klass="FigleafReporter")
|
||||
|
||||
bwfig = _Reporter("Figleaf Code-Coverage Reporter (colorless)",
|
||||
"allmydata.test.trial_figleaf",
|
||||
description="Colorless verbose output (with figleaf coverage)",
|
||||
longOpt="bwverbose-figleaf",
|
||||
shortOpt=None,
|
||||
klass="FigleafTextReporter")
|
||||
|
Loading…
x
Reference in New Issue
Block a user