-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Python: [Bug]: pytest.raises wrong usage (dead code and unexpected behaviour) #5115
Description
Description
Problem Summary
Multiple with pytest.raises(...) blocks contain more than one statement. Because pytest.raises exits immediately after the first exception, all subsequent statements are dead code that never execute. This creates a false sense of test coverage — assertions appear to pass but are never actually tested.
# BAD: second call is dead code
with pytest.raises(ValueError):
function_that_raises() # raises here, block exits
another_function_that_raises() # NEVER RUNSAffected Locations
1. test_types.py — "Invalid base64" block (line 194)
Original code:
with pytest.raises(ValueError, match="Invalid base64 data provided."):
detect_media_type_from_base64(data_str="invalid_base64!") # raises → block exits
detect_media_type_from_base64(data_str="") # DEAD CODEWhat actually happens with data_str="":
>>> detect_media_type_from_base64(data_str="")
None # Does NOT raise — base64.b64decode("") succeeds, returns b"", no magic bytes matchbase64.b64decode("") is valid and returns b"". The function then checks magic bytes, finds no match, and returns None.
⚠️ Maintainer decision needed:The original test implied
data_str=""should raiseValueError. Two interpretations:Option A: Empty string is valid input —
base64.b64decode("")succeeds, the function returnsNone. The test was simply wrong.Option B: Empty string should be rejected as invalid input. This requires a code change in
detect_media_type_from_base64()to add an explicit check:if data_str is not None: if not data_str: raise ValueError("Invalid base64 data provided.")If Option B is chosen, the test should remain as two separate
pytest.raisesblocks.
2. test_types.py — "Provide exactly one" block (line 198)
Original code:
with pytest.raises(ValueError, match="Provide exactly one of data_bytes, data_str, or data_uri."):
detect_media_type_from_base64() # raises → block exits
detect_media_type_from_base64(data_bytes=b"data", data_str="data", data_uri="data:...;base64,AAA") # DEAD
detect_media_type_from_base64(data_bytes=b"data", data_str="data") # DEAD
detect_media_type_from_base64(data_bytes=b"data", data_uri="data:...;base64,AAA") # DEAD
detect_media_type_from_base64(data_str="data", data_uri="data:...;base64,AAA") # DEADSuggested Patch: Split into 5 individual with pytest.raises blocks.
Hidden issue here (I've tried to split and noticed inconsistency):
The last case (data_str + data_uri) raises "Invalid base64 data provided." instead of "Provide exactly one...".
This happens because:
data_uriis processed first → extracts base64 payload → overwritesdata_strdatais stillNone(nodata_byteswas set)- The
data_str is not Nonecheck passes, but the mutual-exclusion guard (if data is not None) doesn't trigger base64.b64decode()fails on the extracted payload → raises "Invalid base64"
So the original data_str parameter is silently discarded. The function still raises ValueError, just with a different message.
⚠️ Maintainer decision needed:Option A: Accept that
data_str+data_uriraises a different error message. The function still rejects the input, just via a different code path.Option B: Fix
detect_media_type_from_base64()to check mutual exclusion upfront before any processing:provided = sum(x is not None for x in (data_bytes, data_str, data_uri)) if provided != 1: raise ValueError("Provide exactly one of data_bytes, data_str, or data_uri.")This would make all combinations produce the same clear error message. The test could then use the strict
match=pattern for all 5 cases.
I haven't introduce the PR yet, because first we have to define the desired behaviour. But once decision is made I would like to handle this bug in order to help the community and project :)
Code Sample
# BAD: second call is dead code
with pytest.raises(ValueError):
function_that_raises() # raises here, block exits
another_function_that_raises() # NEVER RUNSError Messages / Stack Traces
Package Versions
agent-framework-core v1.0.0
Python Version
Python3.14, Python3.13
Additional Context
No response
Metadata
Metadata
Assignees
Labels
Type
Projects
Status