Coverage for tests / test_lcov.py: 100.000%

174 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 LCOV-based summary reporting for coverage.py.""" 

5 

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

7 

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

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

10 

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

12 

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

14 

15 

16class LcovTest(CoverageTest): 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

17 """Tests of the LCOV reports from coverage.py.""" 

18 

19 def create_initial_files(self) -> None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

20 """ 

21 Helper for tests that handles the common ceremony so the tests can 

22 show the consequences of changes in the setup. 

23 """ 

24 self.make_file( 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

25 "main_file.py", 

26 """\ 

27 def cuboid_volume(l): 

28 return (l*l*l) 

29 

30 def IsItTrue(): 

31 return True 

32 """, 

33 ) 

34 

35 self.make_file( 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

36 "test_file.py", 

37 """\ 

38 from main_file import cuboid_volume 

39 import unittest 

40 

41 class TestCuboid(unittest.TestCase): 

42 def test_volume(self): 

43 self.assertAlmostEqual(cuboid_volume(2),8) 

44 self.assertAlmostEqual(cuboid_volume(1),1) 

45 self.assertAlmostEqual(cuboid_volume(0),0) 

46 self.assertAlmostEqual(cuboid_volume(5.5),166.375) 

47 """, 

48 ) 

49 

50 def get_lcov_report_content(self, filename: str = "coverage.lcov") -> str: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

51 """Return the content of an LCOV report.""" 

52 with open(filename, encoding="utf-8") as file: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

53 return file.read() 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

54 

55 def test_lone_file(self) -> None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

56 # For a single file with a couple of functions, the lcov should cover 

57 # the function definitions themselves, but not the returns. 

58 self.make_file( 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

59 "main_file.py", 

60 """\ 

61 def cuboid_volume(l): 

62 return (l*l*l) 

63 

64 def IsItTrue(): 

65 return True 

66 """, 

67 ) 

68 expected_result = textwrap.dedent("""\ 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

69 SF:main_file.py 

70 DA:1,1 

71 DA:2,0 

72 DA:4,1 

73 DA:5,0 

74 LF:4 

75 LH:2 

76 FN:1,2,cuboid_volume 

77 FNDA:0,cuboid_volume 

78 FN:4,5,IsItTrue 

79 FNDA:0,IsItTrue 

80 FNF:2 

81 FNH:0 

82 end_of_record 

83 """) 

84 self.assert_doesnt_exist(".coverage") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

85 cov = coverage.Coverage(source=["."]) 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

86 self.start_import_stop(cov, "main_file") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

87 pct = cov.lcov_report() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

88 assert pct == 50.0 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

89 actual_result = self.get_lcov_report_content() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

90 assert expected_result == actual_result 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

91 

92 def test_line_checksums(self) -> None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

93 self.make_file( 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

94 "main_file.py", 

95 """\ 

96 def cuboid_volume(l): 

97 return (l*l*l) 

98 

99 def IsItTrue(): 

100 return True 

101 """, 

102 ) 

103 self.make_file(".coveragerc", "[lcov]\nline_checksums = true\n") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

104 self.assert_doesnt_exist(".coverage") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

105 cov = coverage.Coverage(source=["."]) 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

106 self.start_import_stop(cov, "main_file") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

107 pct = cov.lcov_report() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

108 assert pct == 50.0 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

109 expected_result = textwrap.dedent("""\ 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

110 SF:main_file.py 

111 DA:1,1,7URou3io0zReBkk69lEb/Q 

112 DA:2,0,Xqj6H1iz/nsARMCAbE90ng 

113 DA:4,1,ilhb4KUfytxtEuClijZPlQ 

114 DA:5,0,LWILTcvARcydjFFyo9qM0A 

115 LF:4 

116 LH:2 

117 FN:1,2,cuboid_volume 

118 FNDA:0,cuboid_volume 

119 FN:4,5,IsItTrue 

120 FNDA:0,IsItTrue 

121 FNF:2 

122 FNH:0 

123 end_of_record 

124 """) 

125 actual_result = self.get_lcov_report_content() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

126 assert expected_result == actual_result 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

127 

128 def test_simple_line_coverage_two_files(self) -> None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

129 # Test that line coverage is created when coverage is run, 

130 # and matches the output of the file below. 

131 self.create_initial_files() 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

132 self.assert_doesnt_exist(".coverage") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

133 self.make_file(".coveragerc", "[lcov]\noutput = data.lcov\n") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

134 cov = coverage.Coverage(source=".") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

135 self.start_import_stop(cov, "test_file") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

136 pct = cov.lcov_report() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

137 assert pct == 50.0 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

138 self.assert_exists("data.lcov") 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

139 expected_result = textwrap.dedent("""\ 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

140 SF:main_file.py 

141 DA:1,1 

142 DA:2,0 

143 DA:4,1 

144 DA:5,0 

145 LF:4 

146 LH:2 

147 FN:1,2,cuboid_volume 

148 FNDA:0,cuboid_volume 

149 FN:4,5,IsItTrue 

150 FNDA:0,IsItTrue 

151 FNF:2 

152 FNH:0 

153 end_of_record 

154 SF:test_file.py 

155 DA:1,1 

156 DA:2,1 

157 DA:4,1 

158 DA:5,1 

159 DA:6,0 

160 DA:7,0 

161 DA:8,0 

162 DA:9,0 

163 LF:8 

164 LH:4 

165 FN:5,9,TestCuboid.test_volume 

166 FNDA:0,TestCuboid.test_volume 

167 FNF:1 

168 FNH:0 

169 end_of_record 

170 """) 

171 actual_result = self.get_lcov_report_content(filename="data.lcov") 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

172 assert expected_result == actual_result 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

173 

174 def test_branch_coverage_one_file(self) -> None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

175 # Test that the reporter produces valid branch coverage. 

176 self.make_file( 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

177 "main_file.py", 

178 """\ 

179 def is_it_x(x): 

180 if x == 3: 

181 return x 

182 else: 

183 return False 

184 """, 

185 ) 

186 self.assert_doesnt_exist(".coverage") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

187 cov = coverage.Coverage(branch=True, source=".") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

188 self.start_import_stop(cov, "main_file") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

189 pct = cov.lcov_report() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

190 assert math.isclose(pct, 16.666666666666668) 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

191 self.assert_exists("coverage.lcov") 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

192 expected_result = textwrap.dedent("""\ 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

193 SF:main_file.py 

194 DA:1,1 

195 DA:2,0 

196 DA:3,0 

197 DA:5,0 

198 LF:4 

199 LH:1 

200 FN:1,5,is_it_x 

201 FNDA:0,is_it_x 

202 FNF:1 

203 FNH:0 

204 BRDA:2,0,jump to line 3,- 

205 BRDA:2,0,jump to line 5,- 

206 BRF:2 

207 BRH:0 

208 end_of_record 

209 """) 

210 actual_result = self.get_lcov_report_content() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

211 assert expected_result == actual_result 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

212 

213 def test_branch_coverage_two_files(self) -> None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

214 # Test that valid branch coverage is generated 

215 # in the case of two files. 

216 self.make_file( 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

217 "main_file.py", 

218 """\ 

219 def is_it_x(x): 

220 if x == 3: 

221 return x 

222 else: 

223 return False 

224 """, 

225 ) 

226 

227 self.make_file( 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

228 "test_file.py", 

229 """\ 

230 from main_file import * 

231 import unittest 

232 

233 class TestIsItX(unittest.TestCase): 

234 def test_is_it_x(self): 

235 self.assertEqual(is_it_x(3), 3) 

236 self.assertEqual(is_it_x(4), False) 

237 """, 

238 ) 

239 self.assert_doesnt_exist(".coverage") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

240 cov = coverage.Coverage(branch=True, source=".") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

241 self.start_import_stop(cov, "test_file") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

242 pct = cov.lcov_report() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

243 assert math.isclose(pct, 41.666666666666664) 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

244 self.assert_exists("coverage.lcov") 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

245 expected_result = textwrap.dedent("""\ 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

246 SF:main_file.py 

247 DA:1,1 

248 DA:2,0 

249 DA:3,0 

250 DA:5,0 

251 LF:4 

252 LH:1 

253 FN:1,5,is_it_x 

254 FNDA:0,is_it_x 

255 FNF:1 

256 FNH:0 

257 BRDA:2,0,jump to line 3,- 

258 BRDA:2,0,jump to line 5,- 

259 BRF:2 

260 BRH:0 

261 end_of_record 

262 SF:test_file.py 

263 DA:1,1 

264 DA:2,1 

265 DA:4,1 

266 DA:5,1 

267 DA:6,0 

268 DA:7,0 

269 LF:6 

270 LH:4 

271 FN:5,7,TestIsItX.test_is_it_x 

272 FNDA:0,TestIsItX.test_is_it_x 

273 FNF:1 

274 FNH:0 

275 end_of_record 

276 """) 

277 actual_result = self.get_lcov_report_content() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

278 assert expected_result == actual_result 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

279 

280 def test_half_covered_branch(self) -> None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

281 # Test that for a given branch that is only half covered, 

282 # the block numbers remain the same, and produces valid lcov. 

283 self.make_file( 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

284 "main_file.py", 

285 """\ 

286 something = True 

287 

288 if something: 

289 print("Yes, something") 

290 else: 

291 print("No, nothing") 

292 """, 

293 ) 

294 self.assert_doesnt_exist(".coverage") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

295 cov = coverage.Coverage(branch=True, source=".") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

296 self.start_import_stop(cov, "main_file") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

297 pct = cov.lcov_report() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

298 assert math.isclose(pct, 66.66666666666667) 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

299 self.assert_exists("coverage.lcov") 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

300 expected_result = textwrap.dedent("""\ 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

301 SF:main_file.py 

302 DA:1,1 

303 DA:3,1 

304 DA:4,1 

305 DA:6,0 

306 LF:4 

307 LH:3 

308 BRDA:3,0,jump to line 4,1 

309 BRDA:3,0,jump to line 6,0 

310 BRF:2 

311 BRH:1 

312 end_of_record 

313 """) 

314 actual_result = self.get_lcov_report_content() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

315 assert expected_result == actual_result 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

316 

317 def test_empty_init_files(self) -> None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

318 # Test that an empty __init__.py still generates a (vacuous) 

319 # coverage record. 

320 self.make_file("__init__.py", "") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

321 self.assert_doesnt_exist(".coverage") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

322 cov = coverage.Coverage(branch=True, source=".") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

323 self.start_import_stop(cov, "__init__") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

324 pct = cov.lcov_report() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

325 assert pct == 0.0 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

326 self.assert_exists("coverage.lcov") 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

327 expected_result = textwrap.dedent("""\ 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

328 SF:__init__.py 

329 end_of_record 

330 """) 

331 actual_result = self.get_lcov_report_content() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

332 assert expected_result == actual_result 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

333 

334 def test_empty_init_file_skipped(self) -> None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

335 # Test that the lcov reporter honors skip_empty. Because skip_empty 

336 # keys off the overall number of lines of code, the result in this 

337 # case will be the same regardless of the age of the Python interpreter. 

338 self.make_file("__init__.py", "") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

339 self.make_file(".coveragerc", "[report]\nskip_empty = True\n") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

340 self.assert_doesnt_exist(".coverage") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

341 cov = coverage.Coverage(branch=True, source=".") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

342 self.start_import_stop(cov, "__init__") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

343 pct = cov.lcov_report() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

344 assert pct == 0.0 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

345 self.assert_exists("coverage.lcov") 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

346 expected_result = "" 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

347 actual_result = self.get_lcov_report_content() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

348 assert expected_result == actual_result 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

349 

350 def test_excluded_lines(self) -> None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

351 self.make_file( 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

352 ".coveragerc", 

353 """\ 

354 [report] 

355 exclude_lines = foo 

356 """, 

357 ) 

358 self.make_file( 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

359 "runme.py", 

360 """\ 

361 s = "Hello 1" 

362 t = "foo is ignored 2" 

363 if s.upper() == "BYE 3": 

364 i_am_missing_4() 

365 foo_is_missing_5() 

366 print("Done 6") 

367 # foo 7 

368 # line 8 

369 """, 

370 ) 

371 cov = coverage.Coverage(source=".", branch=True) 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

372 self.start_import_stop(cov, "runme") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

373 cov.lcov_report() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

374 expected_result = textwrap.dedent("""\ 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

375 SF:runme.py 

376 DA:1,1 

377 DA:3,1 

378 DA:4,0 

379 DA:6,1 

380 LF:4 

381 LH:3 

382 BRDA:3,0,jump to line 4,0 

383 BRDA:3,0,jump to line 6,1 

384 BRF:2 

385 BRH:1 

386 end_of_record 

387 """) 

388 actual_result = self.get_lcov_report_content() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

389 assert expected_result == actual_result 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

390 

391 def test_exit_branches(self) -> None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

392 self.make_file( 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

393 "runme.py", 

394 """\ 

395 def foo(a): 

396 if a: 

397 print(f"{a!r} is truthy") 

398 foo(True) 

399 foo(False) 

400 foo([]) 

401 foo([0]) 

402 """, 

403 ) 

404 cov = coverage.Coverage(source=".", branch=True) 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

405 self.start_import_stop(cov, "runme") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

406 cov.lcov_report() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

407 expected_result = textwrap.dedent("""\ 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

408 SF:runme.py 

409 DA:1,1 

410 DA:2,1 

411 DA:3,1 

412 DA:4,1 

413 DA:5,1 

414 DA:6,1 

415 DA:7,1 

416 LF:7 

417 LH:7 

418 FN:1,3,foo 

419 FNDA:1,foo 

420 FNF:1 

421 FNH:1 

422 BRDA:2,0,jump to line 3,1 

423 BRDA:2,0,return from function 'foo',1 

424 BRF:2 

425 BRH:2 

426 end_of_record 

427 """) 

428 actual_result = self.get_lcov_report_content() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

429 assert expected_result == actual_result 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

430 

431 def test_genexpr_exit_arcs_pruned_full_coverage(self) -> None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

432 self.make_file( 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

433 "runme.py", 

434 """\ 

435 def foo(a): 

436 if any(x > 0 for x in a): 

437 print(f"{a!r} has positives") 

438 foo([]) 

439 foo([0]) 

440 foo([0,1]) 

441 foo([0,-1]) 

442 """, 

443 ) 

444 cov = coverage.Coverage(source=".", branch=True) 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

445 self.start_import_stop(cov, "runme") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

446 cov.lcov_report() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

447 expected_result = textwrap.dedent("""\ 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

448 SF:runme.py 

449 DA:1,1 

450 DA:2,1 

451 DA:3,1 

452 DA:4,1 

453 DA:5,1 

454 DA:6,1 

455 DA:7,1 

456 LF:7 

457 LH:7 

458 FN:1,3,foo 

459 FNDA:1,foo 

460 FNF:1 

461 FNH:1 

462 BRDA:2,0,jump to line 3,1 

463 BRDA:2,0,return from function 'foo',1 

464 BRF:2 

465 BRH:2 

466 end_of_record 

467 """) 

468 actual_result = self.get_lcov_report_content() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

469 assert expected_result == actual_result 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

470 

471 def test_genexpr_exit_arcs_pruned_never_true(self) -> None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

472 self.make_file( 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

473 "runme.py", 

474 """\ 

475 def foo(a): 

476 if any(x > 0 for x in a): 

477 print(f"{a!r} has positives") 

478 foo([]) 

479 foo([0]) 

480 """, 

481 ) 

482 cov = coverage.Coverage(source=".", branch=True) 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

483 self.start_import_stop(cov, "runme") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

484 cov.lcov_report() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

485 expected_result = textwrap.dedent("""\ 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

486 SF:runme.py 

487 DA:1,1 

488 DA:2,1 

489 DA:3,0 

490 DA:4,1 

491 DA:5,1 

492 LF:5 

493 LH:4 

494 FN:1,3,foo 

495 FNDA:1,foo 

496 FNF:1 

497 FNH:1 

498 BRDA:2,0,jump to line 3,0 

499 BRDA:2,0,return from function 'foo',1 

500 BRF:2 

501 BRH:1 

502 end_of_record 

503 """) 

504 actual_result = self.get_lcov_report_content() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

505 assert expected_result == actual_result 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

506 

507 def test_genexpr_exit_arcs_pruned_always_true(self) -> None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

508 self.make_file( 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

509 "runme.py", 

510 """\ 

511 def foo(a): 

512 if any(x > 0 for x in a): 

513 print(f"{a!r} has positives") 

514 foo([1]) 

515 foo([1,2]) 

516 """, 

517 ) 

518 cov = coverage.Coverage(source=".", branch=True) 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

519 self.start_import_stop(cov, "runme") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

520 cov.lcov_report() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

521 expected_result = textwrap.dedent("""\ 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

522 SF:runme.py 

523 DA:1,1 

524 DA:2,1 

525 DA:3,1 

526 DA:4,1 

527 DA:5,1 

528 LF:5 

529 LH:5 

530 FN:1,3,foo 

531 FNDA:1,foo 

532 FNF:1 

533 FNH:1 

534 BRDA:2,0,jump to line 3,1 

535 BRDA:2,0,return from function 'foo',0 

536 BRF:2 

537 BRH:1 

538 end_of_record 

539 """) 

540 actual_result = self.get_lcov_report_content() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

541 assert expected_result == actual_result 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

542 

543 def test_genexpr_exit_arcs_pruned_not_reached(self) -> None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

544 self.make_file( 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

545 "runme.py", 

546 """\ 

547 def foo(a): 

548 if any(x > 0 for x in a): 

549 print(f"{a!r} has positives") 

550 """, 

551 ) 

552 cov = coverage.Coverage(source=".", branch=True) 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

553 self.start_import_stop(cov, "runme") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

554 cov.lcov_report() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

555 expected_result = textwrap.dedent("""\ 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

556 SF:runme.py 

557 DA:1,1 

558 DA:2,0 

559 DA:3,0 

560 LF:3 

561 LH:1 

562 FN:1,3,foo 

563 FNDA:0,foo 

564 FNF:1 

565 FNH:0 

566 BRDA:2,0,jump to line 3,- 

567 BRDA:2,0,return from function 'foo',- 

568 BRF:2 

569 BRH:0 

570 end_of_record 

571 """) 

572 actual_result = self.get_lcov_report_content() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

573 assert expected_result == actual_result 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

574 

575 def test_always_raise(self) -> None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

576 self.make_file( 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

577 "always_raise.py", 

578 """\ 

579 try: 

580 if not_defined: 

581 print("Yes") 

582 else: 

583 print("No") 

584 except Exception: 

585 pass 

586 """, 

587 ) 

588 cov = coverage.Coverage(source=".", branch=True) 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

589 self.start_import_stop(cov, "always_raise") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

590 cov.lcov_report() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

591 expected_result = textwrap.dedent("""\ 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

592 SF:always_raise.py 

593 DA:1,1 

594 DA:2,1 

595 DA:3,0 

596 DA:5,0 

597 DA:6,1 

598 DA:7,1 

599 LF:6 

600 LH:4 

601 BRDA:2,0,jump to line 3,- 

602 BRDA:2,0,jump to line 5,- 

603 BRF:2 

604 BRH:0 

605 end_of_record 

606 """) 

607 actual_result = self.get_lcov_report_content() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

608 assert expected_result == actual_result 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

609 

610 def test_multiline_conditions(self) -> None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

611 self.make_file( 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

612 "multi.py", 

613 """\ 

614 def fun(x): 

615 if ( 

616 x 

617 ): 

618 print("got here") 

619 """, 

620 ) 

621 cov = coverage.Coverage(source=".", branch=True) 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

622 self.start_import_stop(cov, "multi") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

623 cov.lcov_report() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

624 lcov = self.get_lcov_report_content() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

625 assert "BRDA:2,0,return from function 'fun',-" in lcov 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

626 

627 def test_module_exit(self) -> None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

628 self.make_file( 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

629 "modexit.py", 

630 """\ 

631 #! /usr/bin/env python 

632 def foo(): 

633 return bar( 

634 ) 

635 if "x" == "y": # line 5 

636 foo() 

637 """, 

638 ) 

639 cov = coverage.Coverage(source=".", branch=True) 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

640 self.start_import_stop(cov, "modexit") 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

641 cov.lcov_report() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

642 lcov = self.get_lcov_report_content() 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

643 print(lcov) 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

644 assert "BRDA:5,0,exit the module,1" in lcov 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234