## What Cache the Timmy agent instance at app startup (in lifespan) instead of creating a new one per `/serve/chat` request. ## Changes - `src/timmy_serve/app.py`: Create agent in lifespan, store in `app.state.timmy` - `tests/timmy/test_timmy_serve_app.py`: Updated tests for lifespan-based caching, added `test_agent_cached_at_startup` 2085 unit tests pass. 2102 pre-push tests pass. 78.5% coverage. Closes #471 Co-authored-by: Timmy <timmy@timmytime.ai> Reviewed-on: http://localhost:3000/rockachopa/Timmy-time-dashboard/pulls/476 Co-authored-by: Timmy Time <timmy@Alexanderwhitestone.ai> Co-committed-by: Timmy Time <timmy@Alexanderwhitestone.ai>
77 lines
2.6 KiB
Python
77 lines
2.6 KiB
Python
"""Tests for timmy_serve/app.py — Serve FastAPI app and endpoints."""
|
|
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
import pytest
|
|
from fastapi.testclient import TestClient
|
|
|
|
|
|
@pytest.fixture
|
|
def serve_client():
|
|
"""Create a TestClient for the timmy-serve app with mocked Timmy agent."""
|
|
with patch("timmy_serve.app.create_timmy") as mock_create:
|
|
mock_create.return_value = MagicMock()
|
|
from timmy_serve.app import create_timmy_serve_app
|
|
|
|
app = create_timmy_serve_app()
|
|
with TestClient(app) as client:
|
|
yield client
|
|
|
|
|
|
class TestHealthEndpoint:
|
|
def test_health_returns_ok(self, serve_client):
|
|
resp = serve_client.get("/health")
|
|
assert resp.status_code == 200
|
|
data = resp.json()
|
|
assert data["status"] == "healthy"
|
|
assert data["service"] == "timmy-serve"
|
|
|
|
|
|
class TestServeStatus:
|
|
def test_status_returns_info(self, serve_client):
|
|
resp = serve_client.get("/serve/status")
|
|
assert resp.status_code == 200
|
|
data = resp.json()
|
|
assert data["status"] == "active"
|
|
|
|
|
|
class TestServeChatEndpoint:
|
|
@patch("timmy_serve.app.create_timmy")
|
|
def test_chat_returns_response(self, mock_create):
|
|
mock_agent = MagicMock()
|
|
mock_result = MagicMock()
|
|
mock_result.content = "I am Timmy."
|
|
mock_agent.run.return_value = mock_result
|
|
mock_create.return_value = mock_agent
|
|
|
|
from timmy_serve.app import create_timmy_serve_app
|
|
|
|
app = create_timmy_serve_app()
|
|
with TestClient(app) as client:
|
|
resp = client.post(
|
|
"/serve/chat",
|
|
json={"message": "Who are you?"},
|
|
)
|
|
assert resp.status_code == 200
|
|
data = resp.json()
|
|
assert data["response"] == "I am Timmy."
|
|
mock_agent.run.assert_called_once_with("Who are you?", stream=False)
|
|
|
|
@patch("timmy_serve.app.create_timmy")
|
|
def test_agent_cached_at_startup(self, mock_create):
|
|
"""Verify create_timmy is called once at startup, not per request."""
|
|
mock_agent = MagicMock()
|
|
mock_result = MagicMock()
|
|
mock_result.content = "reply"
|
|
mock_agent.run.return_value = mock_result
|
|
mock_create.return_value = mock_agent
|
|
|
|
from timmy_serve.app import create_timmy_serve_app
|
|
|
|
app = create_timmy_serve_app()
|
|
with TestClient(app) as client:
|
|
# Two requests — create_timmy should only be called once (at startup)
|
|
client.post("/serve/chat", json={"message": "hello"})
|
|
client.post("/serve/chat", json={"message": "world"})
|
|
mock_create.assert_called_once()
|