Coverage for tests / test_json.py: 100.000%
65 statements
« prev ^ index » next coverage.py v7.12.1a0.dev1, created at 2025-11-30 17:57 +0000
« prev ^ index » next coverage.py v7.12.1a0.dev1, created at 2025-11-30 17:57 +0000
1# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
2# For details: https://github.com/coveragepy/coveragepy/blob/main/NOTICE.txt
4"""Test json-based summary reporting for coverage.py"""
6from __future__ import annotations 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
8import copy 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
9import json 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
10import os 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
12from datetime import datetime 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
13from typing import Any 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
15import coverage 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
16from coverage import Coverage 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
18from tests.coveragetest import UsingModulesMixin, CoverageTest 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
21class JsonReportTest(UsingModulesMixin, CoverageTest): 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
22 """Tests of the JSON reports from coverage.py."""
24 def _assert_expected_json_report( 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
25 self,
26 cov: Coverage,
27 expected_result: dict[str, Any],
28 ) -> None:
29 """
30 Helper that creates an example file for most tests.
31 """
32 self.make_file( 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
33 "a.py",
34 """\
35 a = {'b': 1}
36 if a.get('a'):
37 b = 3
38 elif a.get('b'):
39 b = 5
40 else:
41 b = 7
42 if not a:
43 b = 9
44 """,
45 )
46 self._compare_json_reports(cov, expected_result, "a") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
48 def _assert_expected_json_report_with_regions( 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
49 self,
50 cov: Coverage,
51 expected_result: dict[str, Any],
52 ) -> None:
53 """
54 Helper that creates an example file for regions tests.
55 """
56 self.make_file( 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
57 "b.py",
58 """\
59 a = {"b": 1}
61 def c():
62 return 4
64 class C:
65 pass
67 class D:
68 def e(self):
69 if a.get("a"):
70 return 12
71 return 13
72 def f(self):
73 return 15
74 """,
75 )
76 self._compare_json_reports(cov, expected_result, "b") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
78 def _compare_json_reports( 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
79 self,
80 cov: Coverage,
81 expected_result: dict[str, Any],
82 mod_name: str,
83 ) -> None:
84 """
85 Helper that handles common ceremonies, comparing JSON reports that
86 it creates to expected results, so tests can clearly show the
87 consequences of setting various arguments.
88 """
89 mod = self.start_import_stop(cov, mod_name) 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
90 output_path = os.path.join(self.temp_dir, f"{mod_name}.json") 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234
91 cov.json_report(mod, outfile=output_path) 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234
92 with open(output_path, encoding="utf-8") as result_file: 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234
93 parsed_result = json.load(result_file) 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234
94 self.assert_recent_datetime( 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234
95 datetime.strptime(parsed_result["meta"]["timestamp"], "%Y-%m-%dT%H:%M:%S.%f"),
96 )
97 del parsed_result["meta"]["timestamp"] 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234
98 expected_result["meta"].update( 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234
99 {
100 "version": coverage.__version__,
101 }
102 )
103 assert parsed_result == expected_result 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234
105 def test_branch_coverage(self) -> None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
106 cov = coverage.Coverage(branch=True) 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
107 a_py_result = { 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
108 "executed_lines": [1, 2, 4, 5, 8],
109 "missing_lines": [3, 7, 9],
110 "excluded_lines": [],
111 "executed_branches": [
112 [2, 4],
113 [4, 5],
114 [8, -1],
115 ],
116 "missing_branches": [
117 [2, 3],
118 [4, 7],
119 [8, 9],
120 ],
121 "summary": {
122 "missing_lines": 3,
123 "covered_lines": 5,
124 "num_statements": 8,
125 "num_branches": 6,
126 "excluded_lines": 0,
127 "num_partial_branches": 3,
128 "covered_branches": 3,
129 "missing_branches": 3,
130 "percent_covered": 57.142857142857146,
131 "percent_covered_display": "57",
132 "percent_statements_covered": 62.5,
133 "percent_statements_covered_display": "62",
134 "percent_branches_covered": 50.0,
135 "percent_branches_covered_display": "50",
136 },
137 }
138 expected_result = { 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
139 "meta": {
140 "branch_coverage": True,
141 "format": 3,
142 "show_contexts": False,
143 },
144 "files": {
145 "a.py": copy.deepcopy(a_py_result),
146 },
147 "totals": {
148 "missing_lines": 3,
149 "covered_lines": 5,
150 "num_statements": 8,
151 "num_branches": 6,
152 "excluded_lines": 0,
153 "num_partial_branches": 3,
154 "percent_covered": 57.142857142857146,
155 "percent_covered_display": "57",
156 "covered_branches": 3,
157 "missing_branches": 3,
158 "percent_statements_covered": 62.5,
159 "percent_statements_covered_display": "62",
160 "percent_branches_covered": 50.0,
161 "percent_branches_covered_display": "50",
162 },
163 }
164 # With regions, a lot of data is duplicated.
165 expected_result["files"]["a.py"]["classes"] = {"": a_py_result} # type: ignore[index] 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
166 expected_result["files"]["a.py"]["functions"] = {"": a_py_result} # type: ignore[index] 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
167 self._assert_expected_json_report(cov, expected_result) 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
169 def test_simple_line_coverage(self) -> None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
170 cov = coverage.Coverage() 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
171 a_py_result = { 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
172 "executed_lines": [1, 2, 4, 5, 8],
173 "missing_lines": [3, 7, 9],
174 "excluded_lines": [],
175 "summary": {
176 "excluded_lines": 0,
177 "missing_lines": 3,
178 "covered_lines": 5,
179 "num_statements": 8,
180 "percent_covered": 62.5,
181 "percent_covered_display": "62",
182 "percent_statements_covered": 62.5,
183 "percent_statements_covered_display": "62",
184 },
185 }
186 expected_result = { 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
187 "meta": {
188 "branch_coverage": False,
189 "format": 3,
190 "show_contexts": False,
191 },
192 "files": {
193 "a.py": copy.deepcopy(a_py_result),
194 },
195 "totals": {
196 "excluded_lines": 0,
197 "missing_lines": 3,
198 "covered_lines": 5,
199 "num_statements": 8,
200 "percent_covered": 62.5,
201 "percent_covered_display": "62",
202 "percent_statements_covered": 62.5,
203 "percent_statements_covered_display": "62",
204 },
205 }
206 # With regions, a lot of data is duplicated.
207 expected_result["files"]["a.py"]["classes"] = {"": a_py_result} # type: ignore[index] 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
208 expected_result["files"]["a.py"]["functions"] = {"": a_py_result} # type: ignore[index] 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
209 self._assert_expected_json_report(cov, expected_result) 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
211 def test_regions_coverage(self) -> None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
212 cov = coverage.Coverage() 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
213 expected_result = { 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
214 "files": {
215 "b.py": {
216 "classes": {
217 "": {
218 "excluded_lines": [],
219 "executed_lines": [1, 3, 6, 7, 9, 10, 14],
220 "missing_lines": [4],
221 "summary": {
222 "covered_lines": 7,
223 "excluded_lines": 0,
224 "missing_lines": 1,
225 "num_statements": 8,
226 "percent_covered": 87.5,
227 "percent_covered_display": "88",
228 "percent_statements_covered": 87.5,
229 "percent_statements_covered_display": "88",
230 },
231 },
232 "C": {
233 "excluded_lines": [],
234 "executed_lines": [],
235 "missing_lines": [],
236 "summary": {
237 "covered_lines": 0,
238 "excluded_lines": 0,
239 "missing_lines": 0,
240 "num_statements": 0,
241 "percent_covered": 100.0,
242 "percent_covered_display": "100",
243 "percent_statements_covered": 100.0,
244 "percent_statements_covered_display": "100",
245 },
246 },
247 "D": {
248 "executed_lines": [],
249 "excluded_lines": [],
250 "missing_lines": [11, 12, 13, 15],
251 "summary": {
252 "covered_lines": 0,
253 "excluded_lines": 0,
254 "missing_lines": 4,
255 "num_statements": 4,
256 "percent_covered": 0.0,
257 "percent_covered_display": "0",
258 "percent_statements_covered": 0.0,
259 "percent_statements_covered_display": "0",
260 },
261 },
262 },
263 "executed_lines": [1, 3, 6, 7, 9, 10, 14],
264 "excluded_lines": [],
265 "functions": {
266 "": {
267 "excluded_lines": [],
268 "executed_lines": [1, 3, 6, 7, 9, 10, 14],
269 "missing_lines": [],
270 "summary": {
271 "covered_lines": 7,
272 "excluded_lines": 0,
273 "missing_lines": 0,
274 "num_statements": 7,
275 "percent_covered": 100.0,
276 "percent_covered_display": "100",
277 "percent_statements_covered": 100.0,
278 "percent_statements_covered_display": "100",
279 },
280 },
281 "c": {
282 "executed_lines": [],
283 "excluded_lines": [],
284 "missing_lines": [4],
285 "summary": {
286 "covered_lines": 0,
287 "excluded_lines": 0,
288 "missing_lines": 1,
289 "num_statements": 1,
290 "percent_covered": 0.0,
291 "percent_covered_display": "0",
292 "percent_statements_covered": 0.0,
293 "percent_statements_covered_display": "0",
294 },
295 },
296 "D.e": {
297 "executed_lines": [],
298 "excluded_lines": [],
299 "missing_lines": [11, 12, 13],
300 "summary": {
301 "covered_lines": 0,
302 "excluded_lines": 0,
303 "missing_lines": 3,
304 "num_statements": 3,
305 "percent_covered": 0.0,
306 "percent_covered_display": "0",
307 "percent_statements_covered": 0.0,
308 "percent_statements_covered_display": "0",
309 },
310 },
311 "D.f": {
312 "executed_lines": [],
313 "excluded_lines": [],
314 "missing_lines": [15],
315 "summary": {
316 "covered_lines": 0,
317 "excluded_lines": 0,
318 "missing_lines": 1,
319 "num_statements": 1,
320 "percent_covered": 0.0,
321 "percent_covered_display": "0",
322 "percent_statements_covered": 0.0,
323 "percent_statements_covered_display": "0",
324 },
325 },
326 },
327 "missing_lines": [4, 11, 12, 13, 15],
328 "summary": {
329 "covered_lines": 7,
330 "excluded_lines": 0,
331 "missing_lines": 5,
332 "num_statements": 12,
333 "percent_covered": 58.333333333333336,
334 "percent_covered_display": "58",
335 "percent_statements_covered": 58.333333333333336,
336 "percent_statements_covered_display": "58",
337 },
338 },
339 },
340 "meta": {
341 "branch_coverage": False,
342 "format": 3,
343 "show_contexts": False,
344 },
345 "totals": {
346 "covered_lines": 7,
347 "excluded_lines": 0,
348 "missing_lines": 5,
349 "num_statements": 12,
350 "percent_covered": 58.333333333333336,
351 "percent_covered_display": "58",
352 "percent_statements_covered": 58.333333333333336,
353 "percent_statements_covered_display": "58",
354 },
355 }
356 self._assert_expected_json_report_with_regions(cov, expected_result) 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
358 def test_branch_regions_coverage(self) -> None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
359 cov = coverage.Coverage(branch=True) 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
360 expected_result = { 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
361 "files": {
362 "b.py": {
363 "classes": {
364 "": {
365 "excluded_lines": [],
366 "executed_branches": [],
367 "executed_lines": [1, 3, 6, 7, 9, 10, 14],
368 "missing_branches": [],
369 "missing_lines": [4],
370 "summary": {
371 "covered_branches": 0,
372 "covered_lines": 7,
373 "excluded_lines": 0,
374 "missing_branches": 0,
375 "missing_lines": 1,
376 "num_branches": 0,
377 "num_partial_branches": 0,
378 "num_statements": 8,
379 "percent_covered": 87.5,
380 "percent_covered_display": "88",
381 "percent_statements_covered": 87.5,
382 "percent_statements_covered_display": "88",
383 "percent_branches_covered": 100.0,
384 "percent_branches_covered_display": "100",
385 },
386 },
387 "C": {
388 "excluded_lines": [],
389 "executed_branches": [],
390 "executed_lines": [],
391 "missing_branches": [],
392 "missing_lines": [],
393 "summary": {
394 "covered_branches": 0,
395 "covered_lines": 0,
396 "excluded_lines": 0,
397 "missing_branches": 0,
398 "missing_lines": 0,
399 "num_branches": 0,
400 "num_partial_branches": 0,
401 "num_statements": 0,
402 "percent_covered": 100.0,
403 "percent_covered_display": "100",
404 "percent_statements_covered": 100.0,
405 "percent_statements_covered_display": "100",
406 "percent_branches_covered": 100.0,
407 "percent_branches_covered_display": "100",
408 },
409 },
410 "D": {
411 "excluded_lines": [],
412 "executed_branches": [],
413 "executed_lines": [],
414 "missing_branches": [[11, 12], [11, 13]],
415 "missing_lines": [11, 12, 13, 15],
416 "summary": {
417 "covered_branches": 0,
418 "covered_lines": 0,
419 "excluded_lines": 0,
420 "missing_branches": 2,
421 "missing_lines": 4,
422 "num_branches": 2,
423 "num_partial_branches": 0,
424 "num_statements": 4,
425 "percent_covered": 0.0,
426 "percent_covered_display": "0",
427 "percent_statements_covered": 0.0,
428 "percent_statements_covered_display": "0",
429 "percent_branches_covered": 0.0,
430 "percent_branches_covered_display": "0",
431 },
432 },
433 },
434 "excluded_lines": [],
435 "executed_branches": [],
436 "executed_lines": [1, 3, 6, 7, 9, 10, 14],
437 "functions": {
438 "": {
439 "excluded_lines": [],
440 "executed_branches": [],
441 "executed_lines": [1, 3, 6, 7, 9, 10, 14],
442 "missing_branches": [],
443 "missing_lines": [],
444 "summary": {
445 "covered_branches": 0,
446 "covered_lines": 7,
447 "excluded_lines": 0,
448 "missing_branches": 0,
449 "missing_lines": 0,
450 "num_branches": 0,
451 "num_partial_branches": 0,
452 "num_statements": 7,
453 "percent_covered": 100.0,
454 "percent_covered_display": "100",
455 "percent_statements_covered": 100.0,
456 "percent_statements_covered_display": "100",
457 "percent_branches_covered": 100.0,
458 "percent_branches_covered_display": "100",
459 },
460 },
461 "D.e": {
462 "excluded_lines": [],
463 "executed_branches": [],
464 "executed_lines": [],
465 "missing_branches": [[11, 12], [11, 13]],
466 "missing_lines": [11, 12, 13],
467 "summary": {
468 "covered_branches": 0,
469 "covered_lines": 0,
470 "excluded_lines": 0,
471 "missing_branches": 2,
472 "missing_lines": 3,
473 "num_branches": 2,
474 "num_partial_branches": 0,
475 "num_statements": 3,
476 "percent_covered": 0.0,
477 "percent_covered_display": "0",
478 "percent_statements_covered": 0.0,
479 "percent_statements_covered_display": "0",
480 "percent_branches_covered": 0.0,
481 "percent_branches_covered_display": "0",
482 },
483 },
484 "D.f": {
485 "excluded_lines": [],
486 "executed_branches": [],
487 "executed_lines": [],
488 "missing_branches": [],
489 "missing_lines": [15],
490 "summary": {
491 "covered_branches": 0,
492 "covered_lines": 0,
493 "excluded_lines": 0,
494 "missing_branches": 0,
495 "missing_lines": 1,
496 "num_branches": 0,
497 "num_partial_branches": 0,
498 "num_statements": 1,
499 "percent_covered": 0.0,
500 "percent_covered_display": "0",
501 "percent_statements_covered": 0.0,
502 "percent_statements_covered_display": "0",
503 "percent_branches_covered": 100.0,
504 "percent_branches_covered_display": "100",
505 },
506 },
507 "c": {
508 "excluded_lines": [],
509 "executed_branches": [],
510 "executed_lines": [],
511 "missing_branches": [],
512 "missing_lines": [4],
513 "summary": {
514 "covered_branches": 0,
515 "covered_lines": 0,
516 "excluded_lines": 0,
517 "missing_branches": 0,
518 "missing_lines": 1,
519 "num_branches": 0,
520 "num_partial_branches": 0,
521 "num_statements": 1,
522 "percent_covered": 0.0,
523 "percent_covered_display": "0",
524 "percent_statements_covered": 0.0,
525 "percent_statements_covered_display": "0",
526 "percent_branches_covered": 100.0,
527 "percent_branches_covered_display": "100",
528 },
529 },
530 },
531 "missing_branches": [[11, 12], [11, 13]],
532 "missing_lines": [4, 11, 12, 13, 15],
533 "summary": {
534 "covered_branches": 0,
535 "covered_lines": 7,
536 "excluded_lines": 0,
537 "missing_branches": 2,
538 "missing_lines": 5,
539 "num_branches": 2,
540 "num_partial_branches": 0,
541 "num_statements": 12,
542 "percent_covered": 50.0,
543 "percent_covered_display": "50",
544 "percent_statements_covered": 58.333333333333336,
545 "percent_statements_covered_display": "58",
546 "percent_branches_covered": 0.0,
547 "percent_branches_covered_display": "0",
548 },
549 },
550 },
551 "meta": {
552 "branch_coverage": True,
553 "format": 3,
554 "show_contexts": False,
555 },
556 "totals": {
557 "covered_branches": 0,
558 "covered_lines": 7,
559 "excluded_lines": 0,
560 "missing_branches": 2,
561 "missing_lines": 5,
562 "num_branches": 2,
563 "num_partial_branches": 0,
564 "num_statements": 12,
565 "percent_covered": 50.0,
566 "percent_covered_display": "50",
567 "percent_statements_covered": 58.333333333333336,
568 "percent_statements_covered_display": "58",
569 "percent_branches_covered": 0.0,
570 "percent_branches_covered_display": "0",
571 },
572 }
573 self._assert_expected_json_report_with_regions(cov, expected_result) 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
575 def run_context_test(self, relative_files: bool) -> None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
576 """A helper for two tests below."""
577 self.make_file( 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
578 "config",
579 f"""\
580 [run]
581 relative_files = {relative_files}
583 [report]
584 precision = 2
586 [json]
587 show_contexts = True
588 """,
589 )
590 cov = coverage.Coverage(context="cool_test", config_file="config") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
591 a_py_result = { 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
592 "executed_lines": [1, 2, 4, 5, 8],
593 "missing_lines": [3, 7, 9],
594 "excluded_lines": [],
595 "contexts": {
596 "1": ["cool_test"],
597 "2": ["cool_test"],
598 "4": ["cool_test"],
599 "5": ["cool_test"],
600 "8": ["cool_test"],
601 },
602 "summary": {
603 "excluded_lines": 0,
604 "missing_lines": 3,
605 "covered_lines": 5,
606 "num_statements": 8,
607 "percent_covered": 62.5,
608 "percent_covered_display": "62.50",
609 "percent_statements_covered": 62.5,
610 "percent_statements_covered_display": "62.50",
611 },
612 }
613 expected_result = { 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
614 "meta": {
615 "branch_coverage": False,
616 "format": 3,
617 "show_contexts": True,
618 },
619 "files": {
620 "a.py": copy.deepcopy(a_py_result),
621 },
622 "totals": {
623 "excluded_lines": 0,
624 "missing_lines": 3,
625 "covered_lines": 5,
626 "num_statements": 8,
627 "percent_covered": 62.5,
628 "percent_covered_display": "62.50",
629 "percent_statements_covered": 62.5,
630 "percent_statements_covered_display": "62.50",
631 },
632 }
633 # With regions, a lot of data is duplicated.
634 expected_result["files"]["a.py"]["classes"] = {"": a_py_result} # type: ignore[index] 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
635 expected_result["files"]["a.py"]["functions"] = {"": a_py_result} # type: ignore[index] 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
636 self._assert_expected_json_report(cov, expected_result) 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
638 def test_context_non_relative(self) -> None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
639 self.run_context_test(relative_files=False) 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
641 def test_context_relative(self) -> None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
642 self.run_context_test(relative_files=True) 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
644 def test_l1_equals_l2(self) -> None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
645 # In results.py, we had a line checking `if l1 == l2` that was never
646 # true. This test makes it true. The annotations are essential, I
647 # don't know why.
648 self.make_file( 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
649 "wtf.py",
650 """\
651 def function(
652 x: int,
653 y: int,
654 ) -> None:
655 return x + y
657 assert function(3, 5) == 8
658 """,
659 )
660 cov = coverage.Coverage(branch=True) 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
661 mod = self.start_import_stop(cov, "wtf") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234
662 cov.json_report(mod) 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234