Skip to content

Commit 163cd0d

Browse files
anxkhnjazhang00
authored andcommitted
test(plugins): assert error propagation in plugin error fallback tests
Merge #6309 Three plugin "fallback to runner" tests are meant to verify that when the `on_*_error` callback is disabled, the underlying error is not swallowed and propagates out through the runner. As written, they do not actually enforce that: - `test_async_on_tool_error_fallback_to_runner` and `test_live_on_tool_error_fallback_to_runner` (`tests/unittests/flows/llm_flows/test_plugin_tool_callbacks.py`) are shaped as: ```python try: await invoke_tool_with_plugin(mock_error_tool, mock_plugin) except Exception as e: assert e == mock_error ``` The only assertion lives inside the `except`. If the production code ever stops raising (exactly the regression these tests exist to catch), the `try` body completes normally, the `except` never runs, the assertion is skipped, and the test still passes green. - `test_on_model_error_callback_fallback_to_runner` (`tests/unittests/flows/llm_flows/test_plugin_model_callbacks.py`) is worse: its `try` only constructs `InMemoryRunner(agent, plugins=[...])`, which never runs the agent, so no error path is exercised at all and the test can never fail. All three pass today over correct code, so this is latent false safety, not a live bug: they would not catch the swallow-the-error regression they are named for. **Solution:** Rewrite the three test bodies so a no-raise regression fails them, following conventions already used in this repo. No production code changes. - Tool tests: wrap the call in `pytest.raises(ClientError)` and assert the captured error, so the test fails if nothing is raised: ```python with pytest.raises(ClientError) as exc_info: await invoke_tool_with_plugin(mock_error_tool, mock_plugin) assert exc_info.value == mock_error ``` - Model test: actually run the agent, then assert the unhandled model error surfaces as a terminal error event. On the synchronous runner an unhandled model error is converted into an error event rather than raised to the caller, so `pytest.raises` is not the right shape here; this mirrors the existing error-event assertions in `tests/unittests/flows/llm_flows/test_base_llm_flow.py`: ```python runner = testing_utils.InMemoryRunner(agent, plugins=[mock_plugin]) events = runner.run('test') error_events = [e for e in events if e.error_code] assert len(error_events) == 1 assert error_events[0].error_code == 'ClientError' ``` Closes #6309 Co-authored-by: Jason Zhang <jasoncz@google.com> PiperOrigin-RevId: 947861608
1 parent 7c11f58 commit 163cd0d

2 files changed

Lines changed: 11 additions & 11 deletions

File tree

tests/unittests/flows/llm_flows/test_plugin_model_callbacks.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -171,18 +171,20 @@ def test_on_model_error_callback_with_plugin(mock_plugin):
171171

172172

173173
def test_on_model_error_callback_fallback_to_runner(mock_plugin):
174-
"""Tests that the model error is not handled and falls back to raise from runner."""
174+
"""Tests that the model error is not handled and surfaces from the runner."""
175175
mock_model = testing_utils.MockModel.create(error=mock_error, responses=[])
176176
mock_plugin.enable_on_model_error_callback = False
177177
agent = Agent(
178178
name='root_agent',
179179
model=mock_model,
180180
)
181181

182-
try:
183-
testing_utils.InMemoryRunner(agent, plugins=[mock_plugin])
184-
except Exception as e:
185-
assert e == mock_error
182+
runner = testing_utils.InMemoryRunner(agent, plugins=[mock_plugin])
183+
184+
events = runner.run('test')
185+
error_events = [e for e in events if e.error_code]
186+
assert len(error_events) == 1
187+
assert error_events[0].error_code == 'ClientError'
186188

187189

188190
if __name__ == '__main__':

tests/unittests/flows/llm_flows/test_plugin_tool_callbacks.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,9 @@ async def test_async_on_tool_error_fallback_to_runner(
180180
):
181181
mock_plugin.enable_on_tool_error_callback = False
182182

183-
try:
183+
with pytest.raises(ClientError) as exc_info:
184184
await invoke_tool_with_plugin(mock_error_tool, mock_plugin)
185-
except Exception as e:
186-
assert e == mock_error
185+
assert exc_info.value == mock_error
187186

188187

189188
async def invoke_tool_with_plugin_live(
@@ -258,10 +257,9 @@ async def test_live_on_tool_error_fallback_to_runner(
258257
):
259258
mock_plugin.enable_on_tool_error_callback = False
260259

261-
try:
260+
with pytest.raises(ClientError) as exc_info:
262261
await invoke_tool_with_plugin_live(mock_error_tool, mock_plugin)
263-
except Exception as e:
264-
assert e == mock_error
262+
assert exc_info.value == mock_error
265263

266264

267265
@pytest.mark.asyncio

0 commit comments

Comments
 (0)