Skip to content

Commit d517cd3

Browse files
authored
Use a custom fixture to capture and filter logs (#603)
1 parent c0efe05 commit d517cd3

File tree

3 files changed

+91
-78
lines changed

3 files changed

+91
-78
lines changed

tests/conftest.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,37 @@
2323
from tests.fixtures import factories
2424

2525

26+
class FilteredLogCaptureFixture(pytest.LogCaptureFixture):
27+
"""A custom implementation to simplify capture
28+
of logs for a particular logger."""
29+
30+
def __init__(self, *args, **kwargs):
31+
super().__init__(*args, **kwargs)
32+
self.logger_name = "" # root (all)
33+
34+
@property
35+
def records(self):
36+
"""Return filtered list of messages"""
37+
return [
38+
r
39+
for r in super().records
40+
if not self.logger_name or r.name == self.logger_name
41+
]
42+
43+
def for_logger(self, logger_name):
44+
"""Specify logger to filter captured messages"""
45+
self.logger_name = logger_name
46+
return self
47+
48+
49+
@pytest.fixture()
50+
def capturelogs(request):
51+
"""A custom log capture that can filter on logger name."""
52+
result = FilteredLogCaptureFixture(request.node)
53+
yield result
54+
result._finalize()
55+
56+
2657
@pytest.fixture(autouse=True)
2758
def mocked_statsd():
2859
with mock.patch("jbi.services.common.statsd") as _mocked_statsd:

tests/unit/test_runner.py

Lines changed: 23 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -85,33 +85,28 @@ def test_request_is_ignored_because_no_action(
8585

8686

8787
def test_execution_logging_for_successful_requests(
88-
caplog,
88+
capturelogs,
8989
webhook_create_example: BugzillaWebhookRequest,
9090
actions_example: Actions,
9191
mocked_bugzilla,
9292
):
9393
mocked_bugzilla.get_bug.return_value = webhook_create_example.bug
9494

95-
with caplog.at_level(logging.DEBUG):
95+
with capturelogs.for_logger("jbi.runner").at_level(logging.DEBUG):
9696
execute_action(
9797
request=webhook_create_example,
9898
actions=actions_example,
9999
)
100100

101-
captured_log_msgs = (
102-
r.msg % r.args for r in caplog.records if r.name == "jbi.runner"
103-
)
104-
105-
for message in [
101+
assert {
106102
"Handling incoming request",
107103
"Execute action 'devtest' for Bug 654321",
108104
"Action 'devtest' executed successfully for Bug 654321",
109-
]:
110-
assert message in captured_log_msgs
105+
}.issubset(set(capturelogs.messages))
111106

112107

113108
def test_execution_logging_for_ignored_requests(
114-
caplog,
109+
capturelogs,
115110
webhook_create_example: BugzillaWebhookRequest,
116111
actions_example: Actions,
117112
mocked_bugzilla,
@@ -120,41 +115,35 @@ def test_execution_logging_for_ignored_requests(
120115
webhook_create_example.bug.whiteboard = "foo"
121116
mocked_bugzilla.get_bug.return_value = webhook_create_example.bug
122117

123-
with caplog.at_level(logging.DEBUG):
118+
with capturelogs.for_logger("jbi.runner").at_level(logging.DEBUG):
124119
with pytest.raises(IgnoreInvalidRequestError):
125120
execute_action(
126121
request=webhook_create_example,
127122
actions=actions_example,
128123
)
129124

130-
captured_log_msgs = [
131-
r.msg % r.args for r in caplog.records if r.name == "jbi.runner"
132-
]
133-
134-
assert captured_log_msgs == [
125+
assert capturelogs.messages == [
135126
"Handling incoming request",
136127
"Ignore incoming request: no bug whiteboard matching action tags: devtest",
137128
]
138129

139130

140131
def test_action_is_logged_as_success_if_returns_true(
141-
caplog,
132+
capturelogs,
142133
webhook_create_example: BugzillaWebhookRequest,
143134
actions_example: Actions,
144135
mocked_bugzilla,
145136
):
146137
mocked_bugzilla.get_bug.return_value = webhook_create_example.bug
147138

148139
with mock.patch("jbi.runner.Executor.__call__", return_value=(True, {})):
149-
with caplog.at_level(logging.DEBUG):
140+
with capturelogs.for_logger("jbi.runner").at_level(logging.DEBUG):
150141
execute_action(
151142
request=webhook_create_example,
152143
actions=actions_example,
153144
)
154145

155-
captured_log_msgs = [
156-
(r.msg % r.args, r.operation) for r in caplog.records if r.name == "jbi.runner"
157-
]
146+
captured_log_msgs = [(r.getMessage(), r.operation) for r in capturelogs.records]
158147

159148
assert captured_log_msgs == [
160149
("Handling incoming request", Operation.HANDLE),
@@ -164,28 +153,26 @@ def test_action_is_logged_as_success_if_returns_true(
164153
),
165154
("Action 'devtest' executed successfully for Bug 654321", Operation.SUCCESS),
166155
]
167-
assert caplog.records[-1].bug["id"] == 654321
168-
assert caplog.records[-1].action["whiteboard_tag"] == "devtest"
156+
assert capturelogs.records[-1].bug["id"] == 654321
157+
assert capturelogs.records[-1].action["whiteboard_tag"] == "devtest"
169158

170159

171160
def test_action_is_logged_as_ignore_if_returns_false(
172-
caplog,
161+
capturelogs,
173162
webhook_create_example: BugzillaWebhookRequest,
174163
actions_example: Actions,
175164
mocked_bugzilla,
176165
):
177166
mocked_bugzilla.get_bug.return_value = webhook_create_example.bug
178167

179168
with mock.patch("jbi.runner.Executor.__call__", return_value=(False, {})):
180-
with caplog.at_level(logging.DEBUG):
169+
with capturelogs.for_logger("jbi.runner").at_level(logging.DEBUG):
181170
execute_action(
182171
request=webhook_create_example,
183172
actions=actions_example,
184173
)
185174

186-
captured_log_msgs = [
187-
(r.msg % r.args, r.operation) for r in caplog.records if r.name == "jbi.runner"
188-
]
175+
captured_log_msgs = [(r.getMessage(), r.operation) for r in capturelogs.records]
189176

190177
assert captured_log_msgs == [
191178
("Handling incoming request", Operation.HANDLE),
@@ -235,23 +222,20 @@ def test_runner_ignores_if_jira_issue_is_not_readable(
235222
actions_example: Actions,
236223
mocked_bugzilla,
237224
mocked_jira,
238-
caplog,
225+
capturelogs,
239226
):
240227
mocked_jira.get_issue.return_value = None
241228
mocked_bugzilla.get_bug.return_value = webhook_comment_example.bug
242229

243-
with caplog.at_level(logging.DEBUG):
230+
with capturelogs.for_logger("jbi.runner").at_level(logging.DEBUG):
244231
with pytest.raises(IgnoreInvalidRequestError) as exc_info:
245232
execute_action(
246233
request=webhook_comment_example,
247234
actions=actions_example,
248235
)
249236

250237
assert str(exc_info.value) == "ignore unreadable issue JBI-234"
251-
captured_log_msgs = [
252-
r.msg % r.args for r in caplog.records if r.name == "jbi.runner"
253-
]
254-
assert captured_log_msgs == [
238+
assert capturelogs.messages == [
255239
"Handling incoming request",
256240
"Ignore incoming request: ignore unreadable issue JBI-234",
257241
]
@@ -306,7 +290,7 @@ def test_default_returns_callable_without_data(action_params_factory):
306290
@pytest.mark.no_mocked_jira
307291
def test_default_logs_all_received_responses(
308292
mocked_responses,
309-
caplog,
293+
capturelogs,
310294
context_comment_example: ActionContext,
311295
action_params_factory,
312296
):
@@ -330,11 +314,13 @@ def test_default_logs_all_received_responses(
330314
)
331315
)
332316

333-
with caplog.at_level(logging.DEBUG):
317+
with capturelogs.for_logger("jbi.runner").at_level(logging.DEBUG):
334318
action(context=context_comment_example)
335319

336320
captured_log_msgs = (
337-
(r.msg % r.args, r.response) for r in caplog.records if r.name == "jbi.runner"
321+
(r.msg % r.args, r.response)
322+
for r in capturelogs.records
323+
if r.name == "jbi.runner"
338324
)
339325

340326
assert (

0 commit comments

Comments
 (0)