fugee / tests /unit /test_loop_errors.py
helmo's picture
[T017-T029] Phase 1 β€” agent loop + interview core
e16f16c
Raw
History Blame Contribute Delete
1.54 kB
"""tests/unit/test_loop_errors.py β€” loop error handling (SC-015).
If the LLM client fails, the loop must yield an ``ErrorEvent`` and finish
gracefully β€” never raise through the async generator (which in the UI would be a
silent hang). No real network is used: the client is replaced with a fake.
"""
import pytest
from agent.events import AgentStartEvent, ErrorEvent
from agent.loop import AgentLoop
class _RaisingClient:
async def chat(self, *args, **kwargs):
raise RuntimeError("connection refused")
class _RaisingMidStreamClient:
async def chat(self, *args, **kwargs):
async def _gen():
raise RuntimeError("stream died")
yield # pragma: no cover - makes this an async generator
return _gen()
@pytest.mark.asyncio
async def test_error_before_stream_becomes_error_event():
loop = AgentLoop()
loop._client = _RaisingClient() # bypass lazy real client
events = [ev async for ev in loop.run("hi", session=None, system_prompt="x")]
assert isinstance(events[0], AgentStartEvent)
assert isinstance(events[-1], ErrorEvent)
assert "connection refused" in events[-1].message
@pytest.mark.asyncio
async def test_error_mid_stream_becomes_error_event():
loop = AgentLoop()
loop._client = _RaisingMidStreamClient()
events = [ev async for ev in loop.run("hi", session=None, system_prompt="x")]
types = [e.type for e in events]
assert types[0] == "agent_start"
assert types[-1] == "error"
assert "stream died" in events[-1].message