Skip to content

Commit de3b9c1

Browse files
simonwclaude
andcommitted
Refactor HTTP handler tests to use pytest.mark.parametrize
Consolidates three separate tests (success, 404, 500) into a single parametrized test for cleaner, more maintainable test code. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent b712b9e commit de3b9c1

1 file changed

Lines changed: 51 additions & 90 deletions

File tree

tests/test_localserver.py

Lines changed: 51 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -257,104 +257,64 @@ def test_credential_cache_policy_generation(mocker):
257257
assert "s3:GetObject" in actions
258258

259259

260-
def test_make_credential_handler_returns_credentials(mocker):
261-
from s3_credentials.localserver import make_credential_handler
262-
import io
263-
264-
mock_cache = Mock()
265-
mock_cache.get_credentials.return_value = {
266-
"AccessKeyId": "AKIAIOSFODNN7EXAMPLE",
267-
"SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
268-
"SessionToken": "session-token",
269-
"Expiration": datetime.datetime(2025, 12, 16, 12, 0, 0),
270-
}
271-
272-
handler_class = make_credential_handler(mock_cache)
273-
274-
# Create handler instance with mocked internals
275-
handler = handler_class.__new__(handler_class)
276-
handler.path = "/"
277-
handler.wfile = io.BytesIO()
278-
handler.request_version = "HTTP/1.1"
279-
handler.requestline = "GET / HTTP/1.1"
280-
281-
# Mock response methods
282-
response_code = None
283-
headers = {}
284-
285-
def mock_send_response(code):
286-
nonlocal response_code
287-
response_code = code
288-
289-
def mock_send_header(name, value):
290-
headers[name] = value
291-
292-
def mock_end_headers():
293-
pass
294-
295-
handler.send_response = mock_send_response
296-
handler.send_header = mock_send_header
297-
handler.end_headers = mock_end_headers
298-
299-
# Call do_GET
300-
handler.do_GET()
301-
302-
# Verify response
303-
assert response_code == 200
304-
assert headers["Content-Type"] == "application/json"
305-
306-
# Parse the response body
307-
response_body = handler.wfile.getvalue().decode()
308-
response_json = json.loads(response_body)
309-
assert response_json["Version"] == 1
310-
assert response_json["AccessKeyId"] == "AKIAIOSFODNN7EXAMPLE"
311-
assert (
312-
response_json["SecretAccessKey"] == "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
313-
)
314-
assert response_json["SessionToken"] == "session-token"
260+
VALID_CREDENTIALS = {
261+
"AccessKeyId": "AKIAIOSFODNN7EXAMPLE",
262+
"SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
263+
"SessionToken": "session-token",
264+
"Expiration": datetime.datetime(2025, 12, 16, 12, 0, 0),
265+
}
315266

316267

317-
def test_make_credential_handler_404_on_wrong_path(mocker):
318-
from s3_credentials.localserver import make_credential_handler
319-
import io
320-
321-
mock_cache = Mock()
322-
handler_class = make_credential_handler(mock_cache)
323-
324-
handler = handler_class.__new__(handler_class)
325-
handler.path = "/wrong-path"
326-
handler.wfile = io.BytesIO()
327-
handler.request_version = "HTTP/1.1"
328-
329-
response_code = None
330-
headers = {}
331-
332-
def mock_send_response(code):
333-
nonlocal response_code
334-
response_code = code
335-
336-
handler.send_response = mock_send_response
337-
handler.send_header = lambda name, value: headers.update({name: value})
338-
handler.end_headers = lambda: None
339-
340-
handler.do_GET()
341-
342-
assert response_code == 404
343-
response_body = handler.wfile.getvalue().decode()
344-
assert "Not found" in response_body
345-
346-
347-
def test_make_credential_handler_500_on_error(mocker):
268+
@pytest.mark.parametrize(
269+
"path,credentials_return,credentials_error,expected_status,expected_body_contains",
270+
[
271+
# Success case: valid path, credentials returned
272+
(
273+
"/",
274+
VALID_CREDENTIALS,
275+
None,
276+
200,
277+
['"Version": 1', '"AccessKeyId"', '"SessionToken"'],
278+
),
279+
# 404 case: wrong path
280+
(
281+
"/wrong-path",
282+
None,
283+
None,
284+
404,
285+
["Not found"],
286+
),
287+
# 500 case: credential generation fails
288+
(
289+
"/",
290+
None,
291+
Exception("AWS Error"),
292+
500,
293+
["AWS Error"],
294+
),
295+
],
296+
ids=["success", "wrong-path-404", "error-500"],
297+
)
298+
def test_credential_handler_responses(
299+
path,
300+
credentials_return,
301+
credentials_error,
302+
expected_status,
303+
expected_body_contains,
304+
):
348305
from s3_credentials.localserver import make_credential_handler
349306
import io
350307

351308
mock_cache = Mock()
352-
mock_cache.get_credentials.side_effect = Exception("AWS Error")
309+
if credentials_error:
310+
mock_cache.get_credentials.side_effect = credentials_error
311+
elif credentials_return:
312+
mock_cache.get_credentials.return_value = credentials_return
353313

354314
handler_class = make_credential_handler(mock_cache)
355315

356316
handler = handler_class.__new__(handler_class)
357-
handler.path = "/"
317+
handler.path = path
358318
handler.wfile = io.BytesIO()
359319
handler.request_version = "HTTP/1.1"
360320

@@ -370,6 +330,7 @@ def mock_send_response(code):
370330

371331
handler.do_GET()
372332

373-
assert response_code == 500
333+
assert response_code == expected_status
374334
response_body = handler.wfile.getvalue().decode()
375-
assert "AWS Error" in response_body
335+
for expected in expected_body_contains:
336+
assert expected in response_body

0 commit comments

Comments
 (0)