Files
fastapi-sqlalchemy-asyncpg/tests/test_ollama_chat_agent_attrs.py

137 lines
5.5 KiB
Python

"""Test suite for refactored OllamaChatAgent with attrs features."""
import httpx
import pytest
from app.config import ChatConfig
from app.services.chat_agent import LocalEchoAgent, OllamaChatAgent, build_chat_agent
class TestOllamaChatAgentAttrsFeatures:
"""Test the attrs library implementation and features."""
def test_instantiation_with_valid_config(self):
"""Test basic instantiation with valid configuration."""
agent = OllamaChatAgent(model="llama3.2", base_url="http://localhost:11434/v1")
assert agent.model == "llama3.2"
assert agent.base_url == "http://localhost:11434/v1"
assert agent.timeout == 60.0
def test_url_validation_rejects_non_http_schemes(self):
"""Test that base_url validator rejects non-HTTP schemes."""
with pytest.raises(ValueError, match="must be HTTP"):
OllamaChatAgent(model="llama3.2", base_url="ftp://invalid.com")
def test_url_validation_rejects_missing_host(self):
"""Test that base_url validator rejects URLs without a host."""
with pytest.raises(ValueError, match="must include a host"):
OllamaChatAgent(model="llama3.2", base_url="http://")
def test_timeout_validation_rejects_negative(self):
"""Test that timeout validator rejects negative values."""
with pytest.raises(ValueError, match="must be positive"):
OllamaChatAgent(
model="llama3.2",
base_url="http://localhost:11434/v1",
timeout=-5.0,
)
def test_timeout_validation_rejects_zero(self):
"""Test that timeout validator rejects zero."""
with pytest.raises(ValueError, match="must be positive"):
OllamaChatAgent(
model="llama3.2",
base_url="http://localhost:11434/v1",
timeout=0.0,
)
def test_timeout_converter_string_to_float(self):
"""Test that timeout converter coerces strings to float."""
agent = OllamaChatAgent(
model="llama3.2",
base_url="http://localhost:11434/v1",
timeout="30", # Pass as string
)
assert isinstance(agent.timeout, float)
assert agent.timeout == 30.0
def test_factory_initialization_of_client(self):
"""Test that _client is created via factory function."""
agent = OllamaChatAgent(model="llama3.2", base_url="http://localhost:11434/v1")
assert hasattr(agent, "_client")
assert isinstance(agent._client, httpx.AsyncClient)
# httpx normalizes URLs by adding a trailing slash
assert str(agent._client.base_url) == "http://localhost:11434/v1/"
assert agent._client.timeout == httpx.Timeout(60.0)
def test_slots_enabled_no_dict(self):
"""Test that slots=True prevents __dict__ attribute."""
agent = OllamaChatAgent(model="llama3.2", base_url="http://localhost:11434/v1")
# With slots=True, instances shouldn't have __dict__
# (unless also inherited from a class with __dict__)
assert not hasattr(agent, "__dict__")
def test_equality_disabled(self):
"""Test that eq=False means instances are not equal even with same values."""
agent1 = OllamaChatAgent(
model="llama3.2", base_url="http://localhost:11434/v1"
)
agent2 = OllamaChatAgent(
model="llama3.2", base_url="http://localhost:11434/v1"
)
# With eq=False, only identity comparison works
assert agent1 != agent2
assert agent1 == agent1
def test_repr_hides_client(self):
"""Test that repr=False on _client hides it from string representation."""
agent = OllamaChatAgent(model="llama3.2", base_url="http://localhost:11434/v1")
agent_repr = repr(agent)
# _client should not appear in repr
assert "_client" not in agent_repr
# But model and base_url should
assert "llama3.2" in agent_repr
assert "localhost" in agent_repr
def test_build_chat_agent_factory_still_works(self):
"""Test that the build_chat_agent factory function works unchanged."""
config = ChatConfig(backend="stub")
local_agent = build_chat_agent(config)
assert isinstance(local_agent, LocalEchoAgent)
def test_build_chat_agent_ollama_backend(self):
"""Test that build_chat_agent can create OllamaChatAgent."""
config = ChatConfig(
backend="ollama",
base_url="http://localhost:11434/v1",
model="llama3.2",
)
agent = build_chat_agent(config)
assert isinstance(agent, OllamaChatAgent)
assert agent.model == "llama3.2"
assert agent.base_url == "http://localhost:11434/v1"
def test_https_urls_accepted(self):
"""Test that HTTPS URLs are properly accepted."""
agent = OllamaChatAgent(
model="llama3.2", base_url="https://api.example.com/v1"
)
assert agent.base_url == "https://api.example.com/v1"
def test_metadata_annotations_present(self):
"""Test that metadata is properly attached to fields."""
import attrs
fields = attrs.fields(OllamaChatAgent)
model_field = fields.model
assert "description" in model_field.metadata
assert "LLM model identifier" in model_field.metadata["description"]
base_url_field = fields.base_url
assert "description" in base_url_field.metadata
assert "OpenAI-compatible" in base_url_field.metadata["description"]
if __name__ == "__main__":
pytest.main([__file__, "-v"])