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

Side by Side Diff: build/android/coverage_test.py

Issue 1211243016: Added coverage script and tests. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed nits. Created 5 years, 5 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
« build/android/coverage.py ('K') | « build/android/coverage.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/python
2 # Copyright 2015 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 from lxml import etree
7 from lxml import html
8 import os
9 import sys
10 import unittest
11
12 import coverage
13 from pylib import constants
14
15 sys.path.append(os.path.join(
16 constants.DIR_SOURCE_ROOT, 'third_party', 'pymock'))
17 import mock # pylint: disable=F0401
18
19
20 class LineCoverageTest(unittest.TestCase):
21 """Tests for LineCoverage."""
22
23 def testInit(self):
24 line_coverage = coverage.LineCoverage(10, 'i++;',
25 coverage.LineCoverage.COVERED, 1.0)
26 self.assertEqual(line_coverage.lineno, 10)
27 self.assertEqual(line_coverage.source, 'i++;')
28 self.assertEqual(line_coverage.covered_status,
29 coverage.LineCoverage.COVERED)
30 self.assertEqual(line_coverage.fractional_line_coverage, 1.0)
31
32
33 class _EmmaHtmlParserTest(unittest.TestCase):
34 """Tests for _EmmaHtmlParser.
35
36 Uses modified EMMA report HTML that contains only the subset of tags needed
37 for test verification.
38 """
39
40 def setUp(self):
41 self.emma_dir = 'fake/dir/'
42 self.parser = coverage._EmmaHtmlParser(self.emma_dir)
43 self.simple_html = '<td class="p">Test HTML</td>'
44 self.index_html = """
45 <HTML>
46 <BODY>
47 <TABLE CLASS="hdft" CELLSPACING="0" WIDTH="100%">
48 </TABLE>
49 <TABLE CELLSPACING="0" WIDTH="100%">
50 </TABLE>
51 <TABLE CLASS="it" CELLSPACING="0">
52 </TABLE>
53 <TABLE CELLSPACING="0" WIDTH="100%">
54 <TR>
55 <TH CLASS="f">name</TH>
56 <TH>class, %</TH>
57 <TH>method, %</TH>
58 <TH>block, %</TH>
59 <TH>line, %</TH>
60 </TR>
61 <TR CLASS="o">
62 <TD><A HREF="_files/0.html"
63 >org.chromium.chrome.browser</A></TD>
64 <TD CLASS="h">0% (0/3)</TD>
65 </TR>
66 <TR>
67 <TD><A HREF="_files/1.html"
68 >org.chromium.chrome.browser.tabmodel</A></TD>
69 <TD CLASS="h">0% (0/8)</TD>
70 </TR>
71 </TABLE>
72 <TABLE CLASS="hdft" CELLSPACING="0" WIDTH="100%">
73 </TABLE>
74 </BODY>
75 </HTML>"""
76 self.package_1_class_list_html = """
77 <HTML>
78 <BODY>
79 <TABLE CLASS="hdft" CELLSPACING="0" WIDTH="100%">
80 </TABLE>
81 <TABLE CELLSPACING="0" WIDTH="100%">
82 </TABLE>
83 <TABLE CELLSPACING="0" WIDTH="100%">
84 <TR>
85 <TH CLASS="f">name</TH>
86 <TH>class, %</TH>
87 <TH>method, %</TH>
88 <TH>block, %</TH>
89 <TH>line, %</TH>
90 </TR>
91 <TR CLASS="o">
92 <TD><A HREF="1e.html">IntentHelper.java</A></TD>
93 <TD CLASS="h">0% (0/3)</TD>
94 <TD CLASS="h">0% (0/9)</TD>
95 <TD CLASS="h">0% (0/97)</TD>
96 <TD CLASS="h">0% (0/26)</TD>
97 </TR>
98 </TABLE>
99 <TABLE CLASS="hdft" CELLSPACING="0" WIDTH="100%">
100 </TABLE>
101 </BODY>
102 </HTML>"""
103 self.package_2_class_list_html = """
104 <HTML>
105 <BODY>
106 <TABLE CLASS="hdft" CELLSPACING="0" WIDTH="100%">
107 </TABLE>
108 <TABLE CELLSPACING="0" WIDTH="100%">
109 </TABLE>
110 <TABLE CELLSPACING="0" WIDTH="100%">
111 <TR>
112 <TH CLASS="f">name</TH>
113 <TH>class, %</TH>
114 <TH>method, %</TH>
115 <TH>block, %</TH>
116 <TH>line, %</TH>
117 </TR>
118 <TR CLASS="o">
119 <TD><A HREF="1f.html">ContentSetting.java</A></TD>
120 <TD CLASS="h">0% (0/1)</TD>
121 </TR>
122 <TR>
123 <TD><A HREF="20.html">DevToolsServer.java</A></TD>
124 </TR>
125 <TR CLASS="o">
126 <TD><A HREF="21.html">FileProviderHelper.java</A></TD>
127 </TR>
128 <TR>
129 <TD><A HREF="22.html">ContextualMenuBar.java</A></TD>
130 </TR>
131 <TR CLASS="o">
132 <TD><A HREF="23.html">AccessibilityUtil.java</A></TD>
133 </TR>
134 <TR>
135 <TD><A HREF="24.html">NavigationPopup.java</A></TD>
136 </TR>
137 </TABLE>
138 <TABLE CLASS="hdft" CELLSPACING="0" WIDTH="100%">
139 </TABLE>
140 </BODY>
141 </HTML>"""
142 self.partially_covered_tr_html = """
143 <tr class="p">
144 <td class="l" title="78% line coverage (7 out of 9)">108</td>
145 <td title="78% line coverage (7 out of 9 instructions)">
146 if (index < 0 || index = mSelectors.size()) index = 0;</td>
147 </tr>"""
148 self.covered_tr_html = """
149 <tr class="c">
150 <td class="l">110</td>
151 <td> if (mSelectors.get(index) != null) {</td>
152 </tr>"""
153 self.not_executable_tr_html = """
154 <tr>
155 <td class="l">109</td>
156 <td> </td>
157 </tr>"""
158 self.tr_with_extra_a_tag = """
159 <tr class="z">
160 <td class="l">
161 <a name="1f">54</a>
162 </td>
163 <td> }</td>
164 </tr>"""
165
166 def testInit(self):
167 emma_dir = self.emma_dir
168 parser = coverage._EmmaHtmlParser(emma_dir)
169 self.assertEqual(parser._base_dir, emma_dir)
170 self.assertEqual(parser._emma_files_path, 'fake/dir/_files')
171 self.assertEqual(parser._index_path, 'fake/dir/index.html')
172
173 def testFindElements_basic(self):
174 read_values = [self.simple_html]
175 found, _ = MockOpenForFunction(self.parser._FindElements, read_values,
176 file_path='fake', xpath_selector='//td')
177 self.assertIs(type(found), list)
178 self.assertIs(type(found[0]), html.HtmlElement)
179 self.assertEqual(found[0].text, 'Test HTML')
180
181 def testFindElements_noMatch(self):
182 read_values = [self.simple_html]
183 found, _ = MockOpenForFunction(self.parser._FindElements, read_values,
184 file_path='fake', xpath_selector='//tr')
185 self.assertEqual(found, [])
186
187 def testFindElements_badFilePath(self):
188 with self.assertRaises(IOError):
189 with mock.patch('os.path.exists', return_value=False):
190 self.parser._FindElements('fake', xpath_selector='//tr')
191
192 def testGetPackageNameToEmmaFileDict_basic(self):
193 expected_dict = {
194 'org.chromium.chrome.browser.AccessibilityUtil.java':
195 'fake/dir/_files/23.html',
196 'org.chromium.chrome.browser.ContextualMenuBar.java':
197 'fake/dir/_files/22.html',
198 'org.chromium.chrome.browser.tabmodel.IntentHelper.java':
199 'fake/dir/_files/1e.html',
200 'org.chromium.chrome.browser.ContentSetting.java':
201 'fake/dir/_files/1f.html',
202 'org.chromium.chrome.browser.DevToolsServer.java':
203 'fake/dir/_files/20.html',
204 'org.chromium.chrome.browser.NavigationPopup.java':
205 'fake/dir/_files/24.html',
206 'org.chromium.chrome.browser.FileProviderHelper.java':
207 'fake/dir/_files/21.html'}
208
209 read_values = [self.index_html, self.package_1_class_list_html,
210 self.package_2_class_list_html]
211 return_dict, mock_open = MockOpenForFunction(
212 self.parser.GetPackageNameToEmmaFileDict, read_values)
213
214 self.assertDictEqual(return_dict, expected_dict)
215 self.assertEqual(mock_open.call_count, 3)
216 calls = [mock.call('fake/dir/index.html'),
217 mock.call('fake/dir/_files/1.html'),
218 mock.call('fake/dir/_files/0.html')]
219 mock_open.assert_has_calls(calls)
220
221 def testGetPackageNameToEmmaFileDict_badFilePath(self):
222 with self.assertRaises(IOError):
223 with mock.patch('os.path.exists', return_value=False):
224 self.parser.GetPackageNameToEmmaFileDict()
225
226 def testGetLineCoverage_status_basic(self):
227 line_coverage = self.GetLineCoverageWithFakeElements([self.covered_tr_html])
228 self.assertEqual(line_coverage[0].covered_status,
229 coverage.LineCoverage.COVERED)
230
231 def testGetLineCoverage_status_statusMissing(self):
232 line_coverage = self.GetLineCoverageWithFakeElements(
233 [self.not_executable_tr_html])
234 self.assertEqual(line_coverage[0].covered_status,
235 coverage.LineCoverage.NOT_EXECUTABLE)
236
237 def testGetLineCoverage_fractionalCoverage_basic(self):
238 line_coverage = self.GetLineCoverageWithFakeElements([self.covered_tr_html])
239 self.assertEqual(line_coverage[0].fractional_line_coverage, 1.0)
240
241 def testGetLineCoverage_fractionalCoverage_partial(self):
242 line_coverage = self.GetLineCoverageWithFakeElements(
243 [self.partially_covered_tr_html])
244 self.assertEqual(line_coverage[0].fractional_line_coverage, 0.78)
245
246 def testGetLineCoverage_lineno_basic(self):
247 line_coverage = self.GetLineCoverageWithFakeElements([self.covered_tr_html])
248 self.assertEqual(line_coverage[0].lineno, 110)
249
250 def testGetLineCoverage_lineno_withAlternativeHtml(self):
251 line_coverage = self.GetLineCoverageWithFakeElements(
252 [self.tr_with_extra_a_tag])
253 self.assertEqual(line_coverage[0].lineno, 54)
254
255 def testGetLineCoverage_source(self):
256 self.parser._FindElements = mock.Mock(
257 return_value=[html.fromstring(self.covered_tr_html)])
258 line_coverage = self.parser.GetLineCoverage('fake_path')
259 self.assertEqual(line_coverage[0].source,
260 ' if (mSelectors.get(index) != null) {')
261
262 def testGetLineCoverage_multipleElements(self):
263 line_coverage = self.GetLineCoverageWithFakeElements(
264 [self.covered_tr_html, self.partially_covered_tr_html,
265 self.tr_with_extra_a_tag])
266 self.assertEqual(len(line_coverage), 3)
267
268 def GetLineCoverageWithFakeElements(self, html_elements):
269 """Wraps GetLineCoverage to work with extra whitespace characters.
270
271 The test HTML strings include extra whitespace characters to make the HTML
272 human readable. This isn't the case with EMMA HTML files, so we need to
273 remove all the unnecessary whitespace.
274
275 Args:
276 html_elements: List of strings each representing an HTML element.
277
278 Returns:
279 A list of LineCoverage objects.
280 """
281 elements = [self.MakeElementsWithoutWhitespace(string)
282 for string in html_elements]
283 with mock.patch('coverage._EmmaHtmlParser._FindElements',
284 return_value=elements):
285 return self.parser.GetLineCoverage('fake_path')
286
287 def MakeElementsWithoutWhitespace(self, html_string):
mikecase (-- gone --) 2015/07/13 16:50:07 This seems a little weird. You could have you Html
estevenson1 2015/07/21 00:01:15 Done.
288 """Helper to make HtmlElements with excess whitespace removed.
289
290 Args:
291 html_string: String representing HTML to be used to create elements.
292
293 Returns:
294 The root element of |html_string| with all extra whitespace removed.
295 """
296 parser = etree.HTMLParser(remove_blank_text=True)
297 root = html.fromstring(html_string, parser=parser)
298 for element in root.iter('*'):
299 if element.text is not None:
300 element.text = element.text.strip()
301 return root
302
303
304 def MockOpenForFunction(func, side_effects, **kwargs):
305 """Allows easy mock open and read for callables that open multiple files.
306
307 Args:
308 func: The callable to invoke once mock files are setup.
309 side_effects: A list of return values for each file to return once read.
310 Length of list should be equal to the number calls to open in |func|.
311 **kwargs: Keyword arguments to be passed to |func|.
312
313 Returns:
314 A tuple containing the return value of |func| and the MagicMock object used
315 to mock all calls to open respectively.
316 """
317 mock_open = mock.mock_open()
318 mock_open.side_effect = [mock.mock_open(read_data=side_effect).return_value
319 for side_effect in side_effects]
320 with mock.patch('__builtin__.open', mock_open):
321 return func(**kwargs), mock_open
322
323
324 if __name__ == '__main__':
325 unittest.main()
OLDNEW
« build/android/coverage.py ('K') | « build/android/coverage.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698