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

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 

3 

4"""Test json-based summary reporting for coverage.py""" 

5 

6from __future__ import annotations 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

7 

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

11 

12from datetime import datetime 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

13from typing import Any 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

14 

15import coverage 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

16from coverage import Coverage 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

17 

18from tests.coveragetest import UsingModulesMixin, CoverageTest 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

19 

20 

21class JsonReportTest(UsingModulesMixin, CoverageTest): 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

22 """Tests of the JSON reports from coverage.py.""" 

23 

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

47 

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} 

60 

61 def c(): 

62 return 4 

63 

64 class C: 

65 pass 

66 

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

77 

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

104 

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

168 

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

210 

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

357 

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

574 

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} 

582 

583 [report] 

584 precision = 2 

585 

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

637 

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

640 

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

643 

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 

656 

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