Coverage for tests/test_build.py: 100.00%

116 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-04-04 17:35 +0200

1"""Tests for the `build` module.""" 

2 

3from __future__ import annotations 

4 

5from time import sleep 

6from typing import TYPE_CHECKING, Literal 

7 

8import pytest 

9 

10from git_changelog import Changelog 

11from git_changelog.commit import AngularConvention 

12 

13if TYPE_CHECKING: 

14 from git_changelog.build import Version 

15 from tests.helpers import GitRepo 

16 

17 

18@pytest.mark.parametrize( 

19 ("versioning", "bump", "expected"), 

20 [ 

21 ("semver", "auto", "0.0.1"), # chore commit 

22 ("semver", "major", "1.0.0"), 

23 ("semver", "minor", "0.1.0"), 

24 ("semver", "patch", "0.0.1"), 

25 ("semver", "1.1.1", "1.1.1"), 

26 ("pep440", "auto", "0.0.1"), # chore commit 

27 ("pep440", "major", "1.0.0"), 

28 ("pep440", "minor+dev", "0.1.0.dev0"), 

29 ("pep440", "micro+alpha+dev", "0.0.1a0.dev0"), 

30 ("pep440", "1.1.1", "1.1.1"), 

31 ], 

32) 

33def test_bump_with_semver_on_new_repo( 

34 repo: GitRepo, 

35 versioning: Literal["pep440", "semver"], 

36 bump: str, 

37 expected: str, 

38) -> None: 

39 """Bump to user specified version on new Git repo. 

40 

41 Parameters: 

42 repo: GitRepo to a temporary repository. 

43 bump: The bump parameter value. 

44 expected: Expected version for the new changelog entry. 

45 """ 

46 changelog = Changelog(repo.path, convention=AngularConvention, bump=bump, versioning=versioning, zerover=False) 

47 assert len(changelog.versions_list) == 1 

48 assert changelog.versions_list[0].planned_tag == expected 

49 

50 

51@pytest.mark.parametrize("bump", ["auto", "major", "minor", "2.0.0"]) 

52def test_no_bump_on_first_tag(repo: GitRepo, bump: str) -> None: 

53 """Ignore bump on new git repo without unreleased commits. 

54 

55 Parameters: 

56 repo: GitRepo to a temporary repository. 

57 bump: The bump parameter value. 

58 """ 

59 repo.tag("1.1.1") 

60 

61 changelog = Changelog(repo.path, convention=AngularConvention, bump=bump) 

62 assert len(changelog.versions_list) == 1 

63 assert changelog.versions_list[0].tag == "1.1.1" 

64 

65 

66def test_one_release_branch_with_feat_branch(repo: GitRepo) -> None: 

67 r"""Test parsing and grouping commits to versions. 

68 

69 Commit graph: 

70 1.0.0 

71 | 

72 main A-B---D 

73 \ / 

74 feat --C 

75 

76 Expected: 

77 - 1.0.0: D B C A 

78 

79 Parameters: 

80 repo: GitRepo to a temporary repository. 

81 """ 

82 commit_a = repo.first_hash 

83 repo.branch("develop") 

84 commit_b = repo.commit("fix: B") 

85 repo.checkout("develop") 

86 commit_c = repo.commit("feat: C") 

87 repo.checkout("main") 

88 commit_d = repo.merge("develop") 

89 repo.tag("1.0.0") 

90 

91 changelog = Changelog(repo.path, convention=AngularConvention) 

92 

93 assert len(changelog.versions_list) == 1 

94 _assert_version( 

95 changelog.versions_list[0], 

96 expected_tag="1.0.0", 

97 expected_prev_tag=None, 

98 expected_commits=[commit_d, commit_b, commit_c, commit_a], 

99 ) 

100 

101 

102def test_one_release_branch_with_two_versions(repo: GitRepo) -> None: 

103 r"""Test parsing and grouping commits to versions. 

104 

105 Commit graph: 

106 1.1.0 

107 1.0.0 | 

108 | | 

109 main A-B---D 

110 \ / 

111 feat --C 

112 

113 Expected: 

114 - 1.1.0: D C 

115 - 1.0.0: B A 

116 

117 Parameters: 

118 repo: GitRepo to a temporary repository. 

119 """ 

120 commit_a = repo.first_hash 

121 repo.branch("develop") 

122 commit_b = repo.commit("fix: B") 

123 repo.tag("1.0.0") 

124 repo.checkout("develop") 

125 commit_c = repo.commit("feat: C") 

126 repo.checkout("main") 

127 commit_d = repo.merge("develop") 

128 repo.tag("1.1.0") 

129 

130 changelog = Changelog(repo.path, convention=AngularConvention) 

131 

132 assert len(changelog.versions_list) == 2 

133 _assert_version( 

134 changelog.versions_list[0], 

135 expected_tag="1.1.0", 

136 expected_prev_tag="1.0.0", 

137 expected_commits=[commit_d, commit_c], 

138 ) 

139 _assert_version( 

140 changelog.versions_list[1], 

141 expected_tag="1.0.0", 

142 expected_prev_tag=None, 

143 expected_commits=[commit_b, commit_a], 

144 ) 

145 

146 

147def test_two_release_branches(repo: GitRepo) -> None: 

148 r"""Test parsing and grouping commits to versions. 

149 

150 Commit graph: 

151 1.1.0 

152 1.0.0 | 

153 | | 

154 main A-B---D-----G 

155 \ \ / 

156 develop --C---E-F 

157 | 

158 2.0.0 

159 Expected: 

160 - Unreleased: G F 

161 - 2.0.0: E C 

162 - 1.1.0: D 

163 - 1.0.0: B A 

164 

165 Parameters: 

166 repo: GitRepo to a temporary repository. 

167 """ 

168 commit_a = repo.first_hash 

169 repo.branch("develop") 

170 commit_b = repo.commit("fix: B") 

171 repo.tag("1.0.0") 

172 repo.checkout("develop") 

173 commit_c = repo.commit("feat: C") 

174 repo.checkout("main") 

175 commit_d = repo.commit("fix: C") 

176 repo.tag("1.1.0") 

177 repo.checkout("develop") 

178 # Git timestamp only has second precision, 

179 # so we delay to ensure git-log lists it before commit C. 

180 sleep(1) 

181 commit_e = repo.merge("main") 

182 repo.tag("2.0.0") 

183 commit_f = repo.commit("feat: F") 

184 repo.checkout("main") 

185 commit_g = repo.merge("develop") 

186 

187 changelog = Changelog(repo.path, convention=AngularConvention) 

188 

189 assert len(changelog.versions_list) == 4 

190 versions = iter(changelog.versions_list) 

191 _assert_version(next(versions), expected_tag="", expected_prev_tag="2.0.0", expected_commits=[commit_g, commit_f]) 

192 _assert_version( 

193 next(versions), 

194 expected_tag="2.0.0", 

195 expected_prev_tag="1.1.0", 

196 expected_commits=[commit_e, commit_c], 

197 ) 

198 _assert_version(next(versions), expected_tag="1.1.0", expected_prev_tag="1.0.0", expected_commits=[commit_d]) 

199 _assert_version(next(versions), expected_tag="1.0.0", expected_prev_tag=None, expected_commits=[commit_b, commit_a]) 

200 

201 

202def _assert_version( 

203 version: Version, 

204 expected_tag: str, 

205 expected_prev_tag: str | None, 

206 expected_commits: list[str], 

207) -> None: 

208 assert expected_tag in (version.tag, version.planned_tag) 

209 if expected_prev_tag: 

210 assert version.previous_version is not None, f"Expected previous version '{expected_prev_tag}', but was None" 

211 assert version.previous_version.tag == expected_prev_tag 

212 else: 

213 assert version.previous_version is None 

214 hashes = [commit.hash for commit in version.commits] 

215 assert hashes == expected_commits 

216 

217 

218def test_no_remote_url(repo: GitRepo) -> None: 

219 """Test parsing and grouping commits to versions without a git remote. 

220 

221 Parameters: 

222 repo: GitRepo to a temporary repository. 

223 """ 

224 repo.git("remote", "remove", "origin") 

225 commit_a = repo.first_hash 

226 repo.tag("1.0.0") 

227 

228 changelog = Changelog(repo.path, convention=AngularConvention) 

229 

230 assert len(changelog.versions_list) == 1 

231 _assert_version( 

232 changelog.versions_list[0], 

233 expected_tag="1.0.0", 

234 expected_prev_tag=None, 

235 expected_commits=[commit_a], 

236 ) 

237 

238 

239def test_merge_into_unreleased(repo: GitRepo) -> None: 

240 r"""Test parsing and grouping commits to versions. 

241 

242 Commit graph: 

243 main A---C---E 

244 \ / \ / 

245 feat B D 

246 

247 Expected: 

248 - Unreleased: E D C B A 

249 

250 Parameters: 

251 repo: GitRepo to a temporary repository. 

252 """ 

253 commit_a = repo.first_hash 

254 repo.branch("feat/1") 

255 repo.checkout("feat/1") 

256 commit_b = repo.commit("feat: B") 

257 repo.checkout("main") 

258 commit_c = repo.merge("feat/1") 

259 repo.branch("feat/2") 

260 repo.checkout("feat/2") 

261 commit_d = repo.commit("feat: D") 

262 repo.checkout("main") 

263 commit_e = repo.merge("feat/2") 

264 

265 changelog = Changelog(repo.path, convention=AngularConvention) 

266 

267 assert len(changelog.versions_list) == 1 

268 version = changelog.versions_list[0] 

269 _assert_version( 

270 version, 

271 expected_tag="", 

272 expected_prev_tag=None, 

273 expected_commits=[commit_e, commit_c, commit_d, commit_a, commit_b], 

274 ) 

275 

276 

277def test_build_changelog_with_pep440_versions(repo: GitRepo) -> None: 

278 """Test parsing and grouping commits to PEP440 versions. 

279 

280 Parameters: 

281 repo: GitRepo to a temporary repository. 

282 """ 

283 repo.commit("feat: Feature") 

284 repo.tag("1.0.0") 

285 repo.commit("fix: Fix") 

286 repo.tag("1.0.0.post0") 

287 repo.commit("feat: Feat") 

288 changelog = Changelog(repo.path, convention=AngularConvention, versioning="pep440") 

289 assert len(changelog.versions_list) == 3 

290 assert changelog.versions_list[1].tag == "1.0.0.post0" 

291 

292 

293def test_ignore_nonsemver_tag(repo: GitRepo) -> None: 

294 """Test parsing and grouping commits to versions. 

295 

296 Commit graph: 

297 1.0.0 

298 | 

299 main A-B-C 

300 | 

301 dummy 

302 

303 Expected: 

304 - 1.0.0: C B A 

305 

306 Parameters: 

307 repo: GitRepo to a temporary repository. 

308 """ 

309 commit_a = repo.first_hash 

310 commit_b = repo.commit("fix: B") 

311 repo.tag("dummy") 

312 commit_c = repo.commit("feat: C") 

313 repo.tag("1.0.0") 

314 

315 changelog = Changelog(repo.path, convention=AngularConvention) 

316 

317 assert len(changelog.versions_list) == 1 

318 _assert_version( 

319 changelog.versions_list[0], 

320 expected_tag="1.0.0", 

321 expected_prev_tag=None, 

322 expected_commits=[commit_c, commit_b, commit_a], 

323 )