]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - src/allmydata/test/trial_coverage.py
Update .PHONY declarations in Makefile.
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / test / trial_coverage.py
1
2 """A Trial IReporter plugin that gathers coverage.py code-coverage information.
3
4 Once this plugin is installed, trial can be invoked a new --reporter option:
5
6   trial --reporter-bwverbose-coverage ARGS
7
8 Once such a test run has finished, there will be a .coverage file in the
9 top-level directory. This file can be turned into a directory of .html files
10 (with index.html as the starting point) by running:
11
12  coverage html -d OUTPUTDIR --omit=PREFIX1,PREFIX2,..
13
14 The 'coverage' tool thinks in terms of absolute filenames. 'coverage' doesn't
15 record data for files that come with Python, but it does record data for all
16 the various site-package directories. To show only information for Tahoe
17 source code files, you should provide --omit prefixes for everything else.
18 This probably means something like:
19
20   --omit=/System/,/Library/,support/,src/allmydata/test/
21
22 Before using this, you need to install the 'coverage' package, which will
23 provide an executable tool named 'coverage' (as well as an importable
24 library). 'coverage report' will produce a basic text summary of the coverage
25 data. Our 'misc/coverage2text.py' tool produces a slightly more useful
26 summary, and 'misc/coverage2html.py' will produce a more useful HTML report.
27
28 """
29
30 from twisted.trial.reporter import TreeReporter, VerboseTextReporter
31
32 # These plugins are registered via twisted/plugins/allmydata_trial.py . See
33 # the notes there for an explanation of how that works.
34
35 # Some notes about how trial Reporters are used:
36 # * Reporters don't really get told about the suite starting and stopping.
37 # * The Reporter class is imported before the test classes are.
38 # * The test classes are imported before the Reporter is created. To get
39 #   control earlier than that requires modifying twisted/scripts/trial.py
40 # * Then Reporter.__init__ is called.
41 # * Then tests run, calling things like write() and addSuccess(). Each test is
42 #   framed by a startTest/stopTest call.
43 # * Then the results are emitted, calling things like printErrors,
44 #   printSummary, and wasSuccessful.
45 # So for code-coverage (not including import), start in __init__ and finish
46 # in printSummary. To include import, we have to start in our own import and
47 # finish in printSummary.
48
49 import coverage
50 cov = coverage.coverage()
51 cov.start()
52
53
54 class CoverageTextReporter(VerboseTextReporter):
55     def __init__(self, *args, **kwargs):
56         VerboseTextReporter.__init__(self, *args, **kwargs)
57
58     def stop_coverage(self):
59         cov.stop()
60         cov.save()
61         print "Coverage results written to .coverage"
62     def printSummary(self):
63         # for twisted-2.5.x
64         self.stop_coverage()
65         return VerboseTextReporter.printSummary(self)
66     def done(self):
67         # for twisted-8.x
68         self.stop_coverage()
69         return VerboseTextReporter.done(self)
70
71 class sample_Reporter(object):
72     # this class, used as a reporter on a fully-passing test suite, doesn't
73     # trigger exceptions. So it is a guide to what methods are invoked on a
74     # Reporter.
75     def __init__(self, *args, **kwargs):
76         print "START HERE"
77         self.r = TreeReporter(*args, **kwargs)
78         self.shouldStop = self.r.shouldStop
79         self.separator = self.r.separator
80         self.testsRun = self.r.testsRun
81         self._starting2 = False
82
83     def write(self, *args):
84         if not self._starting2:
85             self._starting2 = True
86             print "FIRST WRITE"
87         return self.r.write(*args)
88
89     def startTest(self, *args, **kwargs):
90         return self.r.startTest(*args, **kwargs)
91
92     def stopTest(self, *args, **kwargs):
93         return self.r.stopTest(*args, **kwargs)
94
95     def addSuccess(self, *args, **kwargs):
96         return self.r.addSuccess(*args, **kwargs)
97
98     def printErrors(self, *args, **kwargs):
99         return self.r.printErrors(*args, **kwargs)
100
101     def writeln(self, *args, **kwargs):
102         return self.r.writeln(*args, **kwargs)
103
104     def printSummary(self, *args, **kwargs):
105         print "PRINT SUMMARY"
106         return self.r.printSummary(*args, **kwargs)
107
108     def wasSuccessful(self, *args, **kwargs):
109         return self.r.wasSuccessful(*args, **kwargs)
110