]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - allmydata/test/trial_figleaf.py
allmydata.Crypto: fix all internal imports
[tahoe-lafs/tahoe-lafs.git] / allmydata / test / trial_figleaf.py
1
2 """A Trial IReporter plugin that gathers figleaf code-coverage information.
3
4 Once this plugin is installed, trial can be invoked with one of two new
5 --reporter options:
6
7   trial --reporter=verbose-figleaf ARGS
8   trial --reporter-bwverbose-figleaf ARGS
9
10 Once such a test run has finished, there will be a .figleaf file in the
11 top-level directory. This file can be turned into a directory of .html files
12 (with index.html as the starting point) by running:
13
14  figleaf2html -d OUTPUTDIR [-x EXCLUDEFILE]
15
16 Figleaf thinks of everyting in terms of absolute filenames rather than
17 modules. The EXCLUDEFILE may be necessary to keep it from providing reports
18 on non-Code-Under-Test files that live in unusual locations. In particular,
19 if you use extra PYTHONPATH arguments to point at some alternate version of
20 an upstream library (like Twisted), or if something like debian's
21 python-support puts symlinks to .py files in sys.path but not the .py files
22 themselves, figleaf will present coverage information on both of these. The
23 EXCLUDEFILE option might help to inhibit these.
24
25 Other figleaf problems:
26
27  the annotated code files are written to BASENAME(file).html, which results
28  in collisions between similarly-named source files.
29
30  The line-wise coverage information isn't quite right. Blank lines are
31  counted as unreached code, lambdas aren't quite right, and some multiline
32  comments (docstrings?) aren't quite right.
33
34 """
35
36 # TODO: pull some of figleaf into our tree so we can customize it more
37 # easily.
38
39 from twisted.trial.reporter import TreeReporter, VerboseTextReporter
40
41 # These plugins are registered via twisted/plugins/allmydata_trial.py . See
42 # the notes there for an explanation of how that works.
43
44
45
46 # Reporters don't really get told about the suite starting and stopping.
47
48 # The Reporter class is imported before the test classes are.
49
50 # The test classes are imported before the Reporter is created. To get
51 # control earlier than that requires modifying twisted/scripts/trial.py .
52
53 # Then Reporter.__init__ is called.
54
55 # Then tests run, calling things like write() and addSuccess(). Each test is
56 # framed by a startTest/stopTest call.
57
58 # Then the results are emitted, calling things like printErrors,
59 # printSummary, and wasSuccessful.
60
61 # So for code-coverage (not including import), start in __init__ and finish
62 # in printSummary. To include import, we have to start in our own import and
63 # finish in printSummary.
64
65 import figleaf
66 figleaf.start()
67
68 class FigleafReporter(TreeReporter):
69     def __init__(self, *args, **kwargs):
70         TreeReporter.__init__(self, *args, **kwargs)
71
72     def printSummary(self):
73         figleaf.stop()
74         figleaf.write_coverage(".figleaf")
75         print "Figleaf results written to .figleaf"
76         return TreeReporter.printSummary(self)
77
78 class FigleafTextReporter(VerboseTextReporter):
79     def __init__(self, *args, **kwargs):
80         VerboseTextReporter.__init__(self, *args, **kwargs)
81
82     def printSummary(self):
83         figleaf.stop()
84         figleaf.write_coverage(".figleaf")
85         print "Figleaf results written to .figleaf"
86         return VerboseTextReporter.printSummary(self)
87
88 class not_FigleafReporter(object):
89     # this class, used as a reporter on a fully-passing test suite, doesn't
90     # trigger exceptions. So it is a guide to what methods are invoked on a
91     # Reporter.
92     def __init__(self, *args, **kwargs):
93         print "FIGLEAF HERE"
94         self.r = TreeReporter(*args, **kwargs)
95         self.shouldStop = self.r.shouldStop
96         self.separator = self.r.separator
97         self.testsRun = self.r.testsRun
98         self._starting2 = False
99
100     def write(self, *args):
101         if not self._starting2:
102             self._starting2 = True
103             print "FIRST WRITE"
104         return self.r.write(*args)
105
106     def startTest(self, *args, **kwargs):
107         return self.r.startTest(*args, **kwargs)
108
109     def stopTest(self, *args, **kwargs):
110         return self.r.stopTest(*args, **kwargs)
111
112     def addSuccess(self, *args, **kwargs):
113         return self.r.addSuccess(*args, **kwargs)
114
115     def printErrors(self, *args, **kwargs):
116         return self.r.printErrors(*args, **kwargs)
117
118     def writeln(self, *args, **kwargs):
119         return self.r.writeln(*args, **kwargs)
120
121     def printSummary(self, *args, **kwargs):
122         print "PRINT SUMMARY"
123         return self.r.printSummary(*args, **kwargs)
124
125     def wasSuccessful(self, *args, **kwargs):
126         return self.r.wasSuccessful(*args, **kwargs)
127