Skip to content

Commit 30d4595

Browse files
committed
Flesh out suggest commands tests
* Added tons of cases for the suggest cmds files including various different locales and non-ASCII strings * Found whitespace bug in suggest cmds that was fixed * Fixed case where there may be no reviewers to suggest
1 parent 48151e0 commit 30d4595

File tree

2 files changed

+194
-15
lines changed

2 files changed

+194
-15
lines changed

git_py_stats/suggest_cmds.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,14 @@ def suggest_reviewers(config: Dict[str, Union[str, int]]) -> None:
6161
return
6262

6363
# Split the output into lines (each line is a commit author)
64-
lines = output.splitlines()
64+
# and sanitize the string
65+
lines = [line.strip() for line in output.splitlines()]
66+
lines = [line for line in lines if line]
67+
68+
# Return early if nothing found
69+
if not lines:
70+
print("No potential reviewers found.")
71+
return
6572

6673
# Mimic "head -n 100"
6774
head_lines = lines[:100]
Lines changed: 186 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import unittest
22
from unittest.mock import patch, MagicMock
3+
34
from git_py_stats import suggest_cmds
45

56

67
class TestSuggestCmds(unittest.TestCase):
78
"""
8-
Unit test class for testing suggest_cmds
9+
Unit test class for testing suggest_cmds.
910
"""
1011

1112
def setUp(self):
@@ -18,29 +19,200 @@ def setUp(self):
1819
"pathspec": "--",
1920
}
2021

21-
# Don't print to stdout and mock git command output
22+
@patch("git_py_stats.suggest_cmds.print")
2223
@patch("git_py_stats.suggest_cmds.run_git_command")
24+
def test_suggest_reviewers_normal_case(self, mock_run_git_command, mock_print):
25+
"""
26+
Test suggest_reviewers with typical git output.
27+
"""
28+
# Mock git command output with multiple authors
29+
mock_run_git_command.return_value = "Alice\nBob\nAlice\nCharlie\nBob\nBob\n"
30+
31+
# Expected output after processing
32+
expected_output = [
33+
"Suggested code reviewers based on git history:",
34+
" 3 Bob",
35+
" 2 Alice",
36+
" 1 Charlie",
37+
]
38+
39+
suggest_cmds.suggest_reviewers(self.mock_config)
40+
41+
# Verify that print was called with the expected output
42+
mock_print.assert_any_call("Suggested code reviewers based on git history:")
43+
mock_print.assert_any_call(" 3 Bob")
44+
mock_print.assert_any_call(" 2 Alice")
45+
mock_print.assert_any_call(" 1 Charlie")
46+
2347
@patch("git_py_stats.suggest_cmds.print")
24-
def test_suggest_reviewers(self, mock_print, mock_run_git_command) -> None:
48+
@patch("git_py_stats.suggest_cmds.run_git_command")
49+
def test_suggest_reviewers_no_output(self, mock_run_git_command, mock_print):
2550
"""
26-
Test case for suggest_reviewers in suggest_cmds.
51+
Test suggest_reviewers when git command returns no output.
52+
"""
53+
mock_run_git_command.return_value = ""
54+
55+
suggest_cmds.suggest_reviewers(self.mock_config)
2756

28-
Checks if `suggest_reviewers` executes without errors, and it uses
29-
`unittest.mock.patch` to mock the print function to prevent actual
30-
output during testing.
57+
# Verify that print was called with "No data available."
58+
mock_print.assert_called_once_with("No data available.")
3159

32-
Verifies that the function returns `None` and calls the print function
33-
at least once, indicating that some output was generated.
60+
@patch("git_py_stats.suggest_cmds.print")
61+
@patch("git_py_stats.suggest_cmds.run_git_command")
62+
def test_suggest_reviewers_no_authors_found(self, mock_run_git_command, mock_print):
3463
"""
35-
# Mock git command output to provide a list of authors
36-
mock_run_git_command.return_value = "Alice\nBob\nAlice\nCharlie\nBob\nBob\n"
64+
Test suggest_reviewers when no authors are found after processing.
65+
"""
66+
mock_run_git_command.return_value = "\n" # Only newline characters
3767

38-
# Call function with mock configuration
3968
suggest_cmds.suggest_reviewers(self.mock_config)
4069

41-
# Assert that print was called at least once
42-
mock_print.assert_called()
70+
# Verify that print was called with "No potential reviewers found."
71+
mock_print.assert_called_once_with("No potential reviewers found.")
72+
73+
@patch("git_py_stats.suggest_cmds.print")
74+
@patch("git_py_stats.suggest_cmds.run_git_command")
75+
def test_suggest_reviewers_single_author(self, mock_run_git_command, mock_print):
76+
"""
77+
Test suggest_reviewers with only one author in git output.
78+
"""
79+
mock_run_git_command.return_value = "Alice\nAlice\nAlice\n"
80+
81+
suggest_cmds.suggest_reviewers(self.mock_config)
82+
83+
# Verify the output
84+
mock_print.assert_any_call("Suggested code reviewers based on git history:")
85+
mock_print.assert_any_call(" 3 Alice")
86+
87+
@patch("git_py_stats.suggest_cmds.print")
88+
@patch("git_py_stats.suggest_cmds.run_git_command")
89+
def test_suggest_reviewers_handles_exceptions(self, mock_run_git_command, mock_print):
90+
"""
91+
Test suggest_reviewers when run_git_command returns None (simulating an exception).
92+
"""
93+
mock_run_git_command.return_value = None
94+
95+
suggest_cmds.suggest_reviewers(self.mock_config)
96+
97+
# Verify that "No data available." was printed
98+
mock_print.assert_called_once_with("No data available.")
99+
100+
@patch("git_py_stats.suggest_cmds.print")
101+
@patch("git_py_stats.suggest_cmds.run_git_command")
102+
def test_suggest_reviewers_large_number_of_authors(self, mock_run_git_command, mock_print):
103+
"""
104+
Test suggest_reviewers with more than 100 authors.
105+
"""
106+
# Create a list of 150 authors
107+
authors = [f"Author_{i%10}" for i in range(150)] # 10 unique authors repeated
108+
mock_run_git_command.return_value = "\n".join(authors)
109+
110+
suggest_cmds.suggest_reviewers(self.mock_config)
111+
112+
# Ensure that only the top 100 commits are considered
113+
# So counts will be based on the first 100 entries
114+
counts = {f"Author_{i}": 0 for i in range(10)}
115+
for i in range(100):
116+
counts[authors[i]] += 1
117+
118+
# Prepare expected outputs
119+
expected_output = ["Suggested code reviewers based on git history:"]
120+
sorted_counts = sorted(counts.items(), key=lambda x: (-x[1], x[0]))
121+
for author, count in sorted_counts:
122+
expected_output.append(f"{count:7} {author}")
123+
124+
# Verify that print was called with expected outputs
125+
mock_print.assert_any_call("Suggested code reviewers based on git history:")
126+
for line in expected_output[1:]:
127+
mock_print.assert_any_call(line)
128+
129+
@patch("git_py_stats.suggest_cmds.print")
130+
@patch("git_py_stats.suggest_cmds.run_git_command")
131+
def test_suggest_reviewers_authors_with_same_count(self, mock_run_git_command, mock_print):
132+
"""
133+
Test suggest_reviewers when authors have the same commit count.
134+
"""
135+
mock_run_git_command.return_value = "Bob\nAlice\nCharlie\nBob\nAlice\nCharlie\n"
136+
137+
suggest_cmds.suggest_reviewers(self.mock_config)
138+
139+
# Since all have 2 commits, they should be sorted by name
140+
expected_output = [
141+
"Suggested code reviewers based on git history:",
142+
" 2 Alice",
143+
" 2 Bob",
144+
" 2 Charlie",
145+
]
146+
147+
# Verify that print was called with expected outputs
148+
mock_print.assert_any_call("Suggested code reviewers based on git history:")
149+
for line in expected_output[1:]:
150+
mock_print.assert_any_call(line)
151+
152+
@patch("git_py_stats.suggest_cmds.print")
153+
@patch("git_py_stats.suggest_cmds.run_git_command")
154+
def test_suggest_reviewers_non_standard_characters(self, mock_run_git_command, mock_print):
155+
"""
156+
Test suggest_reviewers with author names containing non-standard characters.
157+
"""
158+
mock_run_git_command.return_value = "José\nMüller\n李四\nO'Connor\nJosé\n"
159+
160+
suggest_cmds.suggest_reviewers(self.mock_config)
161+
162+
expected_output = [
163+
"Suggested code reviewers based on git history:",
164+
" 2 José",
165+
" 1 Müller",
166+
" 1 O'Connor",
167+
" 1 李四",
168+
]
169+
170+
mock_print.assert_any_call("Suggested code reviewers based on git history:")
171+
for line in expected_output[1:]:
172+
mock_print.assert_any_call(line)
173+
174+
@patch("git_py_stats.suggest_cmds.print")
175+
@patch("git_py_stats.suggest_cmds.run_git_command")
176+
def test_suggest_reviewers_handles_empty_lines(self, mock_run_git_command, mock_print):
177+
"""
178+
Test suggest_reviewers when git output contains empty lines.
179+
"""
180+
mock_run_git_command.return_value = "Alice\n\nBob\n\nAlice\n"
181+
182+
suggest_cmds.suggest_reviewers(self.mock_config)
183+
184+
expected_output = [
185+
"Suggested code reviewers based on git history:",
186+
" 2 Alice",
187+
" 1 Bob",
188+
]
189+
190+
mock_print.assert_any_call("Suggested code reviewers based on git history:")
191+
for line in expected_output[1:]:
192+
mock_print.assert_any_call(line)
193+
194+
@patch("git_py_stats.suggest_cmds.print")
195+
@patch("git_py_stats.suggest_cmds.run_git_command")
196+
def test_suggest_reviewers_handles_whitespace(self, mock_run_git_command, mock_print):
197+
"""
198+
Test suggest_reviewers when author names have leading/trailing whitespace.
199+
"""
200+
mock_run_git_command.return_value = " Alice \nBob\nAlice\n"
201+
202+
suggest_cmds.suggest_reviewers(self.mock_config)
203+
204+
# Expect that the leading/trailing whitespace is preserved
205+
expected_output = [
206+
"Suggested code reviewers based on git history:",
207+
" 2 Alice",
208+
" 1 Bob",
209+
]
210+
211+
mock_print.assert_any_call("Suggested code reviewers based on git history:")
212+
for line in expected_output[1:]:
213+
mock_print.assert_any_call(line)
43214

44215

45216
if __name__ == "__main__":
46217
unittest.main()
218+

0 commit comments

Comments
 (0)