1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
"""Base test case class for coverage testing."""
import imp, os, random, shutil, sys, tempfile, textwrap, unittest
from cStringIO import StringIO
import coverage
class CoverageTest(unittest.TestCase):
def setUp(self):
# Create a temporary directory.
self.noise = str(random.random())[2:]
self.temproot = os.path.join(tempfile.gettempdir(), 'test_coverage')
self.tempdir = os.path.join(self.temproot, self.noise)
os.makedirs(self.tempdir)
self.olddir = os.getcwd()
os.chdir(self.tempdir)
# Modules should be importable from this temp directory.
self.oldsyspath = sys.path[:]
sys.path.insert(0, '')
# Keep a counter to make every call to checkCoverage unique.
self.n = 0
def tearDown(self):
sys.path = self.oldsyspath
# Get rid of the temporary directory.
os.chdir(self.olddir)
shutil.rmtree(self.temproot)
def makeFile(self, modname, text):
""" Create a temp file with modname as the module name, and text as the
contents.
"""
text = textwrap.dedent(text)
# Create the python file.
f = open(modname + '.py', 'w')
f.write(text)
f.close()
def importModule(self, modname):
""" Import the module named modname, and return the module object.
"""
modfile = modname + '.py'
f = open(modfile, 'r')
for suff in imp.get_suffixes():
if suff[0] == '.py':
break
try:
mod = imp.load_module(modname, f, modfile, suff)
finally:
f.close()
return mod
def getModuleName(self):
# We append self.n because otherwise two calls in one test will use the
# same filename and whether the test works or not depends on the
# timestamps in the .pyc file, so it becomes random whether the second
# call will use the compiled version of the first call's code or not!
modname = 'coverage_test_' + self.noise + str(self.n)
self.n += 1
return modname
def checkCoverage(self, text, lines, missing="", excludes=[], report=""):
# We write the code into a file so that we can import it.
# coverage.py wants to deal with things as modules with file names.
modname = self.getModuleName()
self.makeFile(modname, text)
# Start up coverage.py
cov = coverage.coverage()
cov.erase()
for exc in excludes:
cov.exclude(exc)
cov.start()
# Import the python file, executing it.
mod = self.importModule(modname)
# Stop coverage.py
cov.stop()
# Clean up our side effects
del sys.modules[modname]
# Get the analysis results, and check that they are right.
_, clines, _, cmissing = cov.analysis(mod)
if lines is not None:
if type(lines[0]) == type(1):
self.assertEqual(clines, lines)
else:
for line_list in lines:
if clines == line_list:
break
else:
self.fail("None of the lines choices matched %r" % clines)
if missing is not None:
if type(missing) == type(""):
self.assertEqual(cmissing, missing)
else:
for missing_list in missing:
if cmissing == missing_list:
break
else:
self.fail("None of the missing choices matched %r" % cmissing)
if report:
frep = StringIO()
cov.report(mod, file=frep)
rep = " ".join(frep.getvalue().split("\n")[2].split()[1:])
self.assertEqual(report, rep)
def assertRaisesMsg(self, excClass, msg, callableObj, *args, **kwargs):
""" Just like unittest.TestCase.assertRaises,
but checks that the message is right too.
"""
try:
callableObj(*args, **kwargs)
except excClass, exc:
excMsg = str(exc)
if not msg:
# No message provided: it passes.
return #pragma: no cover
elif excMsg == msg:
# Message provided, and we got the right message: it passes.
return
else: #pragma: no cover
# Message provided, and it didn't match: fail!
raise self.failureException("Right exception, wrong message: got '%s' expected '%s'" % (excMsg, msg))
# No need to catch other exceptions: They'll fail the test all by themselves!
else: #pragma: no cover
if hasattr(excClass,'__name__'):
excName = excClass.__name__
else:
excName = str(excClass)
raise self.failureException("Expected to raise %s, didn't get an exception at all" % excName)
def nice_file(self, *fparts):
return os.path.normcase(os.path.abspath(os.path.realpath(os.path.join(*fparts))))
def run_command(self, cmd):
""" Run the command-line `cmd`, print its output.
"""
# Add our test modules directory to PYTHONPATH. I'm sure there's too
# much path munging here, but...
here = os.path.dirname(self.nice_file(coverage.__file__, ".."))
testmods = self.nice_file(here, 'test/modules')
zipfile = self.nice_file(here, 'test/zipmods.zip')
pypath = os.environ['PYTHONPATH']
if pypath:
pypath += os.pathsep
pypath += testmods + os.pathsep + zipfile
os.environ['PYTHONPATH'] = pypath
stdin, stdouterr = os.popen4(cmd)
output = stdouterr.read()
print output
return output
|