Repository navigation
Expand file tree
/
Copy pathtest_time_to_first_review.py
More file actions
150 lines (109 loc) · 5.85 KB
/
Copy pathtest_time_to_first_review.py
File metadata and controls
150 lines (109 loc) · 5.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
"""Unit tests for the time_to_first_review module."""
import unittest
from datetime import datetime, timedelta
from unittest.mock import MagicMock
from time_to_first_review import (
get_stats_time_to_first_review,
measure_time_to_first_review,
)
class TestMeasureTimeToFirstReview(unittest.TestCase):
"""Test the measure_time_to_first_review function."""
def test_measure_time_to_first_review_basic(self):
"""Test that the function calculates correct review time."""
mock_issue = MagicMock()
mock_issue.created_at = datetime.fromisoformat("2023-01-01T00:00:00Z")
mock_review = MagicMock()
mock_review.submitted_at = datetime.fromisoformat("2023-01-02T00:00:00Z")
mock_pull_request = MagicMock()
mock_pull_request.get_reviews.return_value = [mock_review]
result = measure_time_to_first_review(mock_issue, mock_pull_request, None, [])
expected = timedelta(days=1)
self.assertEqual(result, expected)
def test_measure_time_to_first_review_no_reviews(self):
"""Test that function returns None if there are no reviews."""
mock_issue = MagicMock()
mock_issue.created_at = datetime.fromisoformat("2023-01-01T00:00:00Z")
mock_pull_request = MagicMock()
mock_pull_request.get_reviews.return_value = []
result = measure_time_to_first_review(mock_issue, mock_pull_request, None, [])
self.assertEqual(result, None)
def test_measure_time_to_first_review_ignore_pending(self):
"""Test that pending reviews are ignored."""
mock_issue = MagicMock()
mock_issue.created_at = datetime.fromisoformat("2023-01-01T00:00:00Z")
pending_review = MagicMock()
pending_review.submitted_at = None
valid_review = MagicMock()
valid_review.submitted_at = datetime.fromisoformat("2023-01-03T00:00:00Z")
mock_pull_request = MagicMock()
mock_pull_request.get_reviews.return_value = [pending_review, valid_review]
result = measure_time_to_first_review(mock_issue, mock_pull_request, None, [])
expected = timedelta(days=2)
self.assertEqual(result, expected)
def test_get_stats_time_to_first_review_normal(self):
"""Test a normal list of issues with review times."""
issue1 = MagicMock()
issue1.time_to_first_review = timedelta(days=1)
issue2 = MagicMock()
issue2.time_to_first_review = timedelta(days=3)
stats = get_stats_time_to_first_review([issue1, issue2])
self.assertIsNotNone(stats)
self.assertEqual(stats["avg"], timedelta(days=2))
def test_get_stats_time_to_first_review_all_none(self):
"""Test a list where all review times are None."""
issue = MagicMock()
issue.time_to_first_review = None
self.assertIsNone(get_stats_time_to_first_review([issue]))
def test_get_stats_time_to_first_review_empty(self):
"""Test an empty list."""
self.assertIsNone(get_stats_time_to_first_review([]))
def test_measure_time_to_first_review_ready_for_review_path(self):
"""Test the ready_for_review_at path (Start time logic)."""
mock_issue = MagicMock()
mock_issue.created_at = datetime.fromisoformat("2023-01-01T00:00:00Z")
ready_at = datetime.fromisoformat("2023-01-01T12:00:00Z")
mock_review = MagicMock()
mock_review.submitted_at = datetime.fromisoformat("2023-01-01T13:00:00Z")
mock_pr = MagicMock()
mock_pr.get_reviews.return_value = [mock_review]
result = measure_time_to_first_review(mock_issue, mock_pr, ready_at, [])
self.assertEqual(result, timedelta(hours=1))
def test_measure_time_to_first_review_ignore_users(self):
"""Test filtering out a matching reviewer from ignore_users."""
mock_issue = MagicMock()
mock_issue.created_at = datetime.fromisoformat("2023-01-01T10:00:00Z")
bad_review = MagicMock()
bad_review.user.login = "bot-user"
bad_review.submitted_at = datetime.fromisoformat("2023-01-01T11:00:00Z")
good_review = MagicMock()
good_review.user.login = "human-user"
good_review.submitted_at = datetime.fromisoformat("2023-01-01T12:00:00Z")
mock_pr = MagicMock()
mock_pr.get_reviews.return_value = [bad_review, good_review]
result = measure_time_to_first_review(mock_issue, mock_pr, None, ["bot-user"])
self.assertEqual(result, timedelta(hours=2))
def test_measure_time_to_first_review_type_error_path(self):
"""Test the except TypeError error handling path."""
mock_issue = MagicMock()
mock_issue.created_at = datetime.fromisoformat("2023-01-01T00:00:00Z")
mock_pr = MagicMock()
mock_pr.get_reviews.side_effect = TypeError("ghost user")
result = measure_time_to_first_review(mock_issue, mock_pr, None, [])
self.assertIsNone(result)
class TestTimeToFirstReviewEdgeCases(unittest.TestCase):
"""Covers measure_time_to_first_review edge-case branches."""
def test_returns_none_when_issue_or_pr_missing(self):
"""Function returns None when either input is None."""
self.assertIsNone(measure_time_to_first_review(None, MagicMock()))
self.assertIsNone(measure_time_to_first_review(MagicMock(), None))
def test_ignore_users_defaults_to_empty_list(self):
"""ignore_users defaults to an empty list when omitted."""
mock_issue = MagicMock()
mock_issue.created_at = datetime.fromisoformat("2023-01-01T00:00:00Z")
mock_review = MagicMock()
mock_review.submitted_at = datetime.fromisoformat("2023-01-02T00:00:00Z")
mock_pr = MagicMock()
mock_pr.get_reviews.return_value = [mock_review]
# Omit ignore_users to exercise the default-None branch.
result = measure_time_to_first_review(mock_issue, mock_pr)
self.assertEqual(result, timedelta(days=1))