Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(18)

Side by Side Diff: tools/telemetry/third_party/coverage/tests/test_xml.py

Issue 1366913004: Add coverage Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
2 # For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt
3
4 """Tests for XML reports from coverage.py."""
5
6 import os
7 import re
8
9 import coverage
10
11 from tests.coveragetest import CoverageTest
12 from tests.goldtest import CoverageGoldTest
13 from tests.goldtest import change_dir, compare
14
15
16 class XmlTestHelpers(CoverageTest):
17 """Methods to use from XML tests."""
18
19 def run_mycode(self):
20 """Run mycode.py, so we can report on it."""
21 self.make_file("mycode.py", "print('hello')\n")
22 self.run_command("coverage run mycode.py")
23
24 def run_doit(self):
25 """Construct a simple sub-package."""
26 self.make_file("sub/__init__.py")
27 self.make_file("sub/doit.py", "print('doit!')")
28 self.make_file("main.py", "import sub.doit")
29 cov = coverage.Coverage()
30 self.start_import_stop(cov, "main")
31 return cov
32
33 def make_tree(self, width, depth, curdir="."):
34 """Make a tree of packages.
35
36 Makes `width` directories, named d0 .. d{width-1}. Each directory has
37 __init__.py, and `width` files, named f0.py .. f{width-1}.py. Each
38 directory also has `width` sub-directories, in the same fashion, until
39 a depth of `depth` is reached.
40
41 """
42 if depth == 0:
43 return
44
45 def here(p):
46 """A path for `p` in our currently interesting directory."""
47 return os.path.join(curdir, p)
48
49 for i in range(width):
50 next_dir = here("d{0}".format(i))
51 self.make_tree(width, depth-1, next_dir)
52 if curdir != ".":
53 self.make_file(here("__init__.py"), "")
54 for i in range(width):
55 filename = here("f{0}.py".format(i))
56 self.make_file(filename, "# {0}\n".format(filename))
57
58
59 class XmlReportTest(XmlTestHelpers, CoverageTest):
60 """Tests of the XML reports from coverage.py."""
61
62 def test_default_file_placement(self):
63 self.run_mycode()
64 self.run_command("coverage xml")
65 self.assert_exists("coverage.xml")
66
67 def test_argument_affects_xml_placement(self):
68 self.run_mycode()
69 self.run_command("coverage xml -o put_it_there.xml")
70 self.assert_doesnt_exist("coverage.xml")
71 self.assert_exists("put_it_there.xml")
72
73 def test_config_file_directory_does_not_exist(self):
74 self.run_mycode()
75 self.run_command("coverage xml -o nonexistent/put_it_there.xml")
76 self.assert_doesnt_exist("coverage.xml")
77 self.assert_doesnt_exist("put_it_there.xml")
78 self.assert_exists("nonexistent/put_it_there.xml")
79
80 def test_config_affects_xml_placement(self):
81 self.run_mycode()
82 self.make_file(".coveragerc", "[xml]\noutput = xml.out\n")
83 self.run_command("coverage xml")
84 self.assert_doesnt_exist("coverage.xml")
85 self.assert_exists("xml.out")
86
87 def test_no_data(self):
88 # https://bitbucket.org/ned/coveragepy/issue/210
89 self.run_command("coverage xml")
90 self.assert_doesnt_exist("coverage.xml")
91
92 def test_no_source(self):
93 # Written while investigating a bug, might as well keep it.
94 # https://bitbucket.org/ned/coveragepy/issue/208
95 self.make_file("innocuous.py", "a = 4")
96 cov = coverage.Coverage()
97 self.start_import_stop(cov, "innocuous")
98 os.remove("innocuous.py")
99 cov.xml_report(ignore_errors=True)
100 self.assert_exists("coverage.xml")
101
102 def test_filename_format_showing_everything(self):
103 cov = self.run_doit()
104 cov.xml_report(outfile="-")
105 xml = self.stdout()
106 doit_line = re_line(xml, "class.*doit")
107 self.assertIn('filename="sub/doit.py"', doit_line)
108
109 def test_filename_format_including_filename(self):
110 cov = self.run_doit()
111 cov.xml_report(["sub/doit.py"], outfile="-")
112 xml = self.stdout()
113 doit_line = re_line(xml, "class.*doit")
114 self.assertIn('filename="sub/doit.py"', doit_line)
115
116 def test_filename_format_including_module(self):
117 cov = self.run_doit()
118 import sub.doit # pylint: disable=import-error
119 cov.xml_report([sub.doit], outfile="-")
120 xml = self.stdout()
121 doit_line = re_line(xml, "class.*doit")
122 self.assertIn('filename="sub/doit.py"', doit_line)
123
124 def test_reporting_on_nothing(self):
125 # Used to raise a zero division error:
126 # https://bitbucket.org/ned/coveragepy/issue/250
127 self.make_file("empty.py", "")
128 cov = coverage.Coverage()
129 empty = self.start_import_stop(cov, "empty")
130 cov.xml_report([empty], outfile="-")
131 xml = self.stdout()
132 empty_line = re_line(xml, "class.*empty")
133 self.assertIn('filename="empty.py"', empty_line)
134 self.assertIn('line-rate="1"', empty_line)
135
136 def test_empty_file_is_100_not_0(self):
137 # https://bitbucket.org/ned/coveragepy/issue/345
138 cov = self.run_doit()
139 cov.xml_report(outfile="-")
140 xml = self.stdout()
141 init_line = re_line(xml, 'filename="sub/__init__.py"')
142 self.assertIn('line-rate="1"', init_line)
143
144
145 class XmlPackageStructureTest(XmlTestHelpers, CoverageTest):
146 """Tests about the package structure reported in the coverage.xml file."""
147
148 def package_and_class_tags(self, cov):
149 """Run an XML report on `cov`, and get the package and class tags."""
150 self.captured_stdout.truncate(0)
151 cov.xml_report(outfile="-")
152 packages_and_classes = re_lines(self.stdout(), r"<package |<class ")
153 scrubs = r' branch-rate="0"| complexity="0"| line-rate="[\d.]+"'
154 return clean("".join(packages_and_classes), scrubs)
155
156 def assert_package_and_class_tags(self, cov, result):
157 """Check the XML package and class tags from `cov` match `result`."""
158 self.assertMultiLineEqual(
159 self.package_and_class_tags(cov),
160 clean(result)
161 )
162
163 def test_package_names(self):
164 self.make_tree(width=1, depth=3)
165 self.make_file("main.py", """\
166 from d0.d0 import f0
167 """)
168 cov = coverage.Coverage(source=".")
169 self.start_import_stop(cov, "main")
170 self.assert_package_and_class_tags(cov, """\
171 <package name=".">
172 <class filename="main.py" name="main.py">
173 <package name="d0">
174 <class filename="d0/__init__.py" name="__init__.py">
175 <class filename="d0/f0.py" name="f0.py">
176 <package name="d0.d0">
177 <class filename="d0/d0/__init__.py" name="__init__.py">
178 <class filename="d0/d0/f0.py" name="f0.py">
179 """)
180
181 def test_package_depth(self):
182 self.make_tree(width=1, depth=4)
183 self.make_file("main.py", """\
184 from d0.d0 import f0
185 """)
186 cov = coverage.Coverage(source=".")
187 self.start_import_stop(cov, "main")
188
189 cov.set_option("xml:package_depth", 1)
190 self.assert_package_and_class_tags(cov, """\
191 <package name=".">
192 <class filename="main.py" name="main.py">
193 <package name="d0">
194 <class filename="d0/__init__.py" name="__init__.py">
195 <class filename="d0/d0/__init__.py" name="d0/__init__.py">
196 <class filename="d0/d0/d0/__init__.py" name="d0/d0/__init__.py">
197 <class filename="d0/d0/d0/f0.py" name="d0/d0/f0.py">
198 <class filename="d0/d0/f0.py" name="d0/f0.py">
199 <class filename="d0/f0.py" name="f0.py">
200 """)
201
202 cov.set_option("xml:package_depth", 2)
203 self.assert_package_and_class_tags(cov, """\
204 <package name=".">
205 <class filename="main.py" name="main.py">
206 <package name="d0">
207 <class filename="d0/__init__.py" name="__init__.py">
208 <class filename="d0/f0.py" name="f0.py">
209 <package name="d0.d0">
210 <class filename="d0/d0/__init__.py" name="__init__.py">
211 <class filename="d0/d0/d0/__init__.py" name="d0/__init__.py">
212 <class filename="d0/d0/d0/f0.py" name="d0/f0.py">
213 <class filename="d0/d0/f0.py" name="f0.py">
214 """)
215
216 cov.set_option("xml:package_depth", 3)
217 self.assert_package_and_class_tags(cov, """\
218 <package name=".">
219 <class filename="main.py" name="main.py">
220 <package name="d0">
221 <class filename="d0/__init__.py" name="__init__.py">
222 <class filename="d0/f0.py" name="f0.py">
223 <package name="d0.d0">
224 <class filename="d0/d0/__init__.py" name="__init__.py">
225 <class filename="d0/d0/f0.py" name="f0.py">
226 <package name="d0.d0.d0">
227 <class filename="d0/d0/d0/__init__.py" name="__init__.py">
228 <class filename="d0/d0/d0/f0.py" name="f0.py">
229 """)
230
231
232 def re_lines(text, pat):
233 """Return a list of lines that match `pat` in the string `text`."""
234 lines = [l for l in text.splitlines(True) if re.search(pat, l)]
235 return lines
236
237
238 def re_line(text, pat):
239 """Return the one line in `text` that matches regex `pat`."""
240 lines = re_lines(text, pat)
241 assert len(lines) == 1
242 return lines[0]
243
244
245 def clean(text, scrub=None):
246 """Clean text to prepare it for comparison.
247
248 Remove text matching `scrub`, and leading whitespace. Convert backslashes
249 to forward slashes.
250
251 """
252 if scrub:
253 text = re.sub(scrub, "", text)
254 text = re.sub(r"(?m)^\s+", "", text)
255 text = re.sub(r"\\", "/", text)
256 return text
257
258
259 class XmlGoldTest(CoverageGoldTest):
260 """Tests of XML reporting that use gold files."""
261
262 # TODO: this should move out of html.
263 root_dir = 'tests/farm/html'
264
265 def test_a_xml_1(self):
266 self.output_dir("out/xml_1")
267
268 with change_dir("src"):
269 # pylint: disable=import-error
270 cov = coverage.Coverage()
271 cov.start()
272 import a # pragma: nested
273 cov.stop() # pragma: nested
274 cov.xml_report(a, outfile="../out/xml_1/coverage.xml")
275 source_path = coverage.files.relative_directory().rstrip('/')
276
277 compare("gold_x_xml", "out/xml_1", scrubs=[
278 (r' timestamp="\d+"', ' timestamp="TIMESTAMP"'),
279 (r' version="[-.\w]+"', ' version="VERSION"'),
280 (r'<source>\s*.*?\s*</source>', '<source>%s</source>' % source_path) ,
281 (r'/coverage.readthedocs.org/?[-.\w/]*', '/coverage.readthedocs.org/ VER'),
282 ])
283
284 def test_a_xml_2(self):
285 self.output_dir("out/xml_2")
286
287 with change_dir("src"):
288 # pylint: disable=import-error
289 cov = coverage.Coverage(config_file="run_a_xml_2.ini")
290 cov.start()
291 import a # pragma: nested
292 cov.stop() # pragma: nested
293 cov.xml_report(a)
294 source_path = coverage.files.relative_directory().rstrip('/')
295
296 compare("gold_x_xml", "out/xml_2", scrubs=[
297 (r' timestamp="\d+"', ' timestamp="TIMESTAMP"'),
298 (r' version="[-.\w]+"', ' version="VERSION"'),
299 (r'<source>\s*.*?\s*</source>', '<source>%s</source>' % source_path) ,
300 (r'/coverage.readthedocs.org/?[-.\w/]*', '/coverage.readthedocs.org/ VER'),
301 ])
302
303 def test_y_xml_branch(self):
304 self.output_dir("out/y_xml_branch")
305
306 with change_dir("src"):
307 # pylint: disable=import-error
308 cov = coverage.Coverage(branch=True)
309 cov.start()
310 import y # pragma: nested
311 cov.stop() # pragma: nested
312 cov.xml_report(y, outfile="../out/y_xml_branch/coverage.xml")
313 source_path = coverage.files.relative_directory().rstrip('/')
314
315 compare("gold_y_xml_branch", "out/y_xml_branch", scrubs=[
316 (r' timestamp="\d+"', ' timestamp="TIMESTAMP"'),
317 (r' version="[-.\w]+"', ' version="VERSION"'),
318 (r'<source>\s*.*?\s*</source>', '<source>%s</source>' % source_path) ,
319 (r'/coverage.readthedocs.org/?[-.\w/]*', '/coverage.readthedocs.org/ VER'),
320 ])
OLDNEW
« no previous file with comments | « tools/telemetry/third_party/coverage/tests/test_testing.py ('k') | tools/telemetry/third_party/coverage/tests/try_execfile.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698