initial tests
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
"""
|
||||
Shared test fixtures and config.
|
||||
|
||||
Fixtures defined here available to all tests
|
||||
"""
|
||||
|
||||
from statistics import mode
|
||||
from unittest.mock import AsyncMock, MagicMock
|
||||
|
||||
import pytest
|
||||
from anthropic.types import ContentBlock, Message, TextBlock, Usage
|
||||
|
||||
from agent.config import Settings
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def settings():
|
||||
"""provide test settings don't load from .env"""
|
||||
return Settings(
|
||||
anthropic_api_key="test-key-12345",
|
||||
model="claude-test-model",
|
||||
max_tokens=100,
|
||||
safedir="./test-workspace",
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_anthropic_client():
|
||||
"""Mock anthropic client that returns a fake response."""
|
||||
mock_client = AsyncMock()
|
||||
|
||||
# create a realistic fake response
|
||||
fake_message = Message(
|
||||
id="msg_test123",
|
||||
type="message",
|
||||
role="assistant",
|
||||
content=[TextBlock(type="text", text="42")],
|
||||
model="claude-test-model",
|
||||
stop_reason="end_turn",
|
||||
usage=Usage(input_tokens=10, output_tokens=5),
|
||||
)
|
||||
|
||||
# make messages.create() return this fake message
|
||||
mock_client.messages.create = AsyncMock(return_value=fake_message)
|
||||
|
||||
return mock_client
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_history():
|
||||
"""sample conversation history for testing"""
|
||||
return [
|
||||
{"role": "user", "content": "Hello"},
|
||||
{"role": "assistance", "content": "Hi there!"},
|
||||
{"role": "user", "content": "What's 2+2?"},
|
||||
]
|
||||
@@ -0,0 +1,49 @@
|
||||
"""test config"""
|
||||
|
||||
import pytest
|
||||
from pydantic import ValidationError
|
||||
|
||||
from agent.config import Settings
|
||||
|
||||
|
||||
def test_settings_with_all_values():
|
||||
"""Test Settings loads correctly with all values provided."""
|
||||
settings = Settings(
|
||||
anthropic_api_key="sk-ant-test",
|
||||
model="claude-test",
|
||||
max_tokens=500,
|
||||
safedir="/tmp/test",
|
||||
)
|
||||
|
||||
assert settings.anthropic_api_key == "sk-ant-test"
|
||||
assert settings.model == "claude-test"
|
||||
assert settings.max_tokens == 500
|
||||
|
||||
|
||||
def test_settings_defaults():
|
||||
"""Test Settings uses defaults for optional values."""
|
||||
settings = Settings(
|
||||
anthropic_api_key="sk-ant-test" # Only required field
|
||||
)
|
||||
|
||||
# Should use defaults
|
||||
assert settings.model == "claude-sonnet-4-5-20250929"
|
||||
assert settings.max_tokens == 500
|
||||
|
||||
|
||||
def test_settings_missing_required_field():
|
||||
"""Test Settings raises error when required field is missing."""
|
||||
with pytest.raises(ValidationError) as exc_info:
|
||||
Settings(_env_file=None) # Missing anthropic_api_key
|
||||
|
||||
# Verify the error mentions the missing field
|
||||
assert "anthropic_api_key" in str(exc_info.value)
|
||||
|
||||
|
||||
def test_settings_type_validation():
|
||||
"""Test Settings validates types correctly."""
|
||||
with pytest.raises(ValidationError):
|
||||
Settings(
|
||||
anthropic_api_key="sk-ant-test",
|
||||
max_tokens="not-a-number", # Should be int
|
||||
)
|
||||
@@ -0,0 +1,38 @@
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from agent.loop import run_turn
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_run_turn_basic(mock_anthropic_client):
|
||||
"""test that run_turn calls the API and returns a message"""
|
||||
|
||||
# patch the client with our mock
|
||||
with patch("agent.loop.client", mock_anthropic_client):
|
||||
result = await run_turn("What is 2+2?")
|
||||
|
||||
# verify client was called
|
||||
mock_anthropic_client.messages.create.assert_called_once()
|
||||
|
||||
# verify message returned
|
||||
assert result.content[0].text == "42"
|
||||
|
||||
# verify call has correct parameters
|
||||
call_args = mock_anthropic_client.messages.create.call_args
|
||||
assert call_args.kwargs["messages"][0]["content"] == "What is 2+2?"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_run_turn_uses_settings(mock_anthropic_client, settings):
|
||||
"""Test that run_turn uses settings correctly."""
|
||||
|
||||
with patch("agent.loop.client", mock_anthropic_client):
|
||||
with patch("agent.loop.settings", settings):
|
||||
await run_turn("test message")
|
||||
|
||||
# Verify settings were used
|
||||
call_args = mock_anthropic_client.messages.create.call_args
|
||||
assert call_args.kwargs["model"] == settings.model
|
||||
assert call_args.kwargs["max_tokens"] == settings.max_tokens
|
||||
Reference in New Issue
Block a user