Skip to content

Commit 4ae74ab

Browse files
committed
test: cover remaining contributor paths
Signed-off-by: Venu Vardhan Reddy Tekula <venuvrtekula@gmail.com>
1 parent e2771ed commit 4ae74ab

3 files changed

Lines changed: 170 additions & 1 deletion

File tree

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
[![Python package](https://github.com/github/contributors/actions/workflows/python-ci.yml/badge.svg)](https://github.com/github/contributors/actions/workflows/python-ci.yml)
44
[![Docker Image CI](https://github.com/github/contributors/actions/workflows/docker-ci.yml/badge.svg)](https://github.com/github/contributors/actions/workflows/docker-ci.yml)
5-
[![CodeQL](https://github.com/github/contributors/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/github/contributors/actions/workflows/github-code-scanning/codeql)[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/github/contributors/badge)](https://scorecard.dev/viewer/?uri=github.com/github/contributors)
5+
[![CodeQL](https://github.com/github/contributors/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/github/contributors/actions/workflows/github-code-scanning/codeql)
6+
[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/github/contributors/badge)](https://scorecard.dev/viewer/?uri=github.com/github/contributors)
67

78
This is a GitHub Action that given an organization or specified repositories, produces information about the [contributors](https://chaoss.community/kb/metric-contributors/) over the specified time period.
89

test_contributor_stats.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,17 @@ def test_init(self):
4545
"commit_url5",
4646
)
4747

48+
def test_repr(self):
49+
"""Test the __repr__ method includes key fields."""
50+
representation = repr(self.contributor)
51+
self.assertIn("contributor_stats(username=zkoppert", representation)
52+
self.assertIn("new_contributor=False", representation)
53+
self.assertIn(
54+
"avatar_url=https://avatars.githubusercontent.com/u/29484535?v=4",
55+
representation,
56+
)
57+
self.assertIn("contribution_count=1261", representation)
58+
4859
def test_merge_contributors(self):
4960
"""
5061
Test the merge_contributors function.
@@ -214,6 +225,28 @@ def test_fetch_sponsor_info(self, mock_post):
214225
timeout=60,
215226
)
216227

228+
@patch("requests.post")
229+
def test_fetch_sponsor_info_raises_on_error(self, mock_post):
230+
"""Test get_sponsor_information raises when the API response is invalid."""
231+
mock_response = MagicMock()
232+
mock_response.status_code = 500
233+
mock_response.json.return_value = {"errors": [{"message": "fail"}]}
234+
mock_post.return_value = mock_response
235+
236+
contributors = [
237+
ContributorStats(
238+
username="user1",
239+
new_contributor=False,
240+
avatar_url="https://avatars.githubusercontent.com/u/",
241+
contribution_count="100",
242+
commit_url="url1",
243+
sponsor_info="",
244+
),
245+
]
246+
247+
with self.assertRaises(ValueError):
248+
get_sponsor_information(contributors, token="token", ghe="")
249+
217250

218251
if __name__ == "__main__":
219252
unittest.main()

test_contributors.py

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
"""This module contains the tests for the contributors.py module"""
22

3+
import runpy
34
import unittest
45
from unittest.mock import MagicMock, patch
56

7+
import contributors as contributors_module
68
from contributor_stats import ContributorStats
79
from contributors import get_all_contributors, get_contributors
810

@@ -199,6 +201,139 @@ def test_get_contributors_no_commit_end_date(self, mock_contributor_stats):
199201
"",
200202
)
201203

204+
def test_get_contributors_skips_when_no_commits_in_range(self):
205+
"""Test get_contributors skips users with no commits in the date range."""
206+
mock_repo = MagicMock()
207+
mock_user = MagicMock()
208+
mock_user.login = "user"
209+
mock_user.avatar_url = "https://avatars.githubusercontent.com/u/12345678?v=4"
210+
mock_user.contributions_count = 100
211+
mock_repo.contributors.return_value = [mock_user]
212+
mock_repo.full_name = "owner/repo"
213+
mock_repo.commits.return_value = iter([])
214+
215+
result = get_contributors(mock_repo, "2022-01-01", "2022-12-31", "")
216+
217+
self.assertEqual(result, [])
218+
219+
def test_get_contributors_handles_exception(self):
220+
"""Test get_contributors returns None when an exception is raised."""
221+
222+
class BoomIterable: # pylint: disable=too-few-public-methods
223+
"""Iterable that raises an exception when iterated over."""
224+
225+
def __iter__(self):
226+
raise RuntimeError("boom")
227+
228+
mock_repo = MagicMock()
229+
mock_repo.full_name = "owner/repo"
230+
mock_repo.contributors.return_value = BoomIterable()
231+
232+
with patch("builtins.print") as mock_print:
233+
result = get_contributors(mock_repo, "2022-01-01", "2022-12-31", "")
234+
235+
self.assertIsNone(result)
236+
mock_print.assert_any_call(
237+
"Error getting contributors for repository: owner/repo"
238+
)
239+
240+
def test_main_runs_under_main_guard(self):
241+
"""Test running contributors as a script executes main."""
242+
mock_env = MagicMock()
243+
mock_env.get_env_vars.return_value = (
244+
"org",
245+
[],
246+
123,
247+
456,
248+
b"key",
249+
False,
250+
"",
251+
"",
252+
"2022-01-01",
253+
"2022-12-31",
254+
"true",
255+
False,
256+
)
257+
258+
mock_auth = MagicMock()
259+
mock_github = MagicMock()
260+
mock_org = MagicMock()
261+
mock_org.repositories.return_value = []
262+
mock_github.organization.return_value = mock_org
263+
mock_auth.auth_to_github.return_value = mock_github
264+
mock_auth.get_github_app_installation_token.return_value = "token"
265+
266+
mock_markdown = MagicMock()
267+
mock_json_writer = MagicMock()
268+
269+
with patch.dict(
270+
"sys.modules",
271+
{
272+
"env": mock_env,
273+
"auth": mock_auth,
274+
"markdown": mock_markdown,
275+
"json_writer": mock_json_writer,
276+
},
277+
clear=False,
278+
):
279+
runpy.run_module("contributors", run_name="__main__")
280+
281+
mock_env.get_env_vars.assert_called_once()
282+
mock_auth.auth_to_github.assert_called_once()
283+
mock_auth.get_github_app_installation_token.assert_called_once_with(
284+
"", 123, b"key", 456
285+
)
286+
mock_markdown.write_to_markdown.assert_called_once()
287+
mock_json_writer.write_to_json.assert_called_once()
288+
289+
def test_main_sets_new_contributor_flag(self):
290+
"""Test main sets new_contributor when start/end dates are provided."""
291+
contributor = ContributorStats(
292+
"user1",
293+
False,
294+
"https://avatars.githubusercontent.com/u/1",
295+
10,
296+
"commit_url",
297+
"",
298+
)
299+
300+
with patch.object(
301+
contributors_module.env, "get_env_vars"
302+
) as mock_get_env_vars, patch.object(
303+
contributors_module.auth, "auth_to_github"
304+
) as mock_auth_to_github, patch.object(
305+
contributors_module, "get_all_contributors"
306+
) as mock_get_all_contributors, patch.object(
307+
contributors_module.contributor_stats,
308+
"is_new_contributor",
309+
return_value=True,
310+
) as mock_is_new, patch.object(
311+
contributors_module.markdown, "write_to_markdown"
312+
), patch.object(
313+
contributors_module.json_writer, "write_to_json"
314+
):
315+
mock_get_env_vars.return_value = (
316+
"org",
317+
[],
318+
None,
319+
None,
320+
b"",
321+
False,
322+
"token",
323+
"",
324+
"2022-01-01",
325+
"2022-12-31",
326+
False,
327+
False,
328+
)
329+
mock_auth_to_github.return_value = MagicMock()
330+
mock_get_all_contributors.side_effect = [[contributor], []]
331+
332+
contributors_module.main()
333+
334+
mock_is_new.assert_called_once_with("user1", [])
335+
self.assertTrue(contributor.new_contributor)
336+
202337

203338
if __name__ == "__main__":
204339
unittest.main()

0 commit comments

Comments
 (0)