- Add pytest markers (integration, e2e, slow) with skip logic - Add command line options (--run-integration, --run-e2e) - Create sample_project and sample_project_with_bug fixtures - Add test_integration.py with 10 LLM tests - Add test_e2e.py with 12 API server tests - Update COVERAGE.md to reflect ~65% complete Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
226 lines
6.8 KiB
Python
226 lines
6.8 KiB
Python
"""
|
|
End-to-end tests for the API.
|
|
|
|
These tests require the API server to be running and are skipped by default.
|
|
Run with: pytest tests/test_e2e.py -v --run-e2e
|
|
|
|
Start the server first: ./wakeup.sh
|
|
"""
|
|
import pytest
|
|
|
|
from tests.conftest import assert_contains_any
|
|
|
|
# All tests in this module require --run-e2e
|
|
pytestmark = [pytest.mark.e2e, pytest.mark.slow]
|
|
|
|
|
|
class TestHealthEndpoint:
|
|
"""E2E tests for health endpoint."""
|
|
|
|
@pytest.mark.anyio
|
|
async def test_health_check(self, live_client):
|
|
"""Test that health endpoint responds."""
|
|
response = await live_client.get("/health")
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data.get("status") == "healthy"
|
|
|
|
|
|
class TestAgentEndpoints:
|
|
"""E2E tests for agent endpoints."""
|
|
|
|
@pytest.mark.anyio
|
|
async def test_list_agents(self, live_client):
|
|
"""Test listing agents via live API."""
|
|
response = await live_client.get("/agents/")
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert "agents" in data
|
|
assert len(data["agents"]) >= 1
|
|
|
|
# Verify explore agent exists
|
|
names = [a["name"] for a in data["agents"]]
|
|
assert "explore" in names
|
|
|
|
@pytest.mark.anyio
|
|
async def test_get_agent_info(self, live_client):
|
|
"""Test getting agent info via live API."""
|
|
response = await live_client.get("/agents/explore")
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["name"] == "explore"
|
|
assert "description" in data
|
|
|
|
@pytest.mark.anyio
|
|
async def test_run_agent(self, live_client, sample_project):
|
|
"""Test running agent via live API."""
|
|
response = await live_client.post(
|
|
"/agents/run",
|
|
json={
|
|
"agent_type": "explore",
|
|
"prompt": "List all files in this directory",
|
|
"working_dir": str(sample_project),
|
|
},
|
|
timeout=60.0, # LLM calls can be slow
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data.get("success") is True
|
|
assert "response" in data
|
|
assert len(data["response"]) > 0
|
|
|
|
|
|
class TestStreamingEndpoint:
|
|
"""E2E tests for streaming endpoint."""
|
|
|
|
@pytest.mark.anyio
|
|
async def test_stream_agent(self, live_client, sample_project):
|
|
"""Test streaming agent responses via live API."""
|
|
async with live_client.stream(
|
|
"POST",
|
|
"/agents/stream",
|
|
json={
|
|
"agent_type": "explore",
|
|
"prompt": "List all Python files",
|
|
"working_dir": str(sample_project),
|
|
},
|
|
timeout=60.0,
|
|
) as response:
|
|
assert response.status_code == 200
|
|
assert response.headers.get("content-type") == "text/event-stream; charset=utf-8"
|
|
|
|
# Collect chunks
|
|
chunks = []
|
|
async for line in response.aiter_lines():
|
|
if line.startswith("data: "):
|
|
chunks.append(line)
|
|
|
|
# Should receive some data
|
|
assert len(chunks) >= 1
|
|
|
|
@pytest.mark.anyio
|
|
async def test_stream_invalid_agent(self, live_client):
|
|
"""Test streaming with invalid agent type."""
|
|
response = await live_client.post(
|
|
"/agents/stream",
|
|
json={
|
|
"agent_type": "nonexistent",
|
|
"prompt": "test",
|
|
"working_dir": ".",
|
|
},
|
|
)
|
|
|
|
assert response.status_code == 400
|
|
|
|
|
|
class TestErrorHandling:
|
|
"""E2E tests for error handling."""
|
|
|
|
@pytest.mark.anyio
|
|
async def test_invalid_agent_type(self, live_client):
|
|
"""Test error response for invalid agent."""
|
|
response = await live_client.post(
|
|
"/agents/run",
|
|
json={
|
|
"agent_type": "nonexistent",
|
|
"prompt": "test",
|
|
"working_dir": ".",
|
|
},
|
|
)
|
|
|
|
assert response.status_code == 400
|
|
data = response.json()
|
|
assert "detail" in data
|
|
|
|
@pytest.mark.anyio
|
|
async def test_missing_required_fields(self, live_client):
|
|
"""Test validation error for missing fields."""
|
|
response = await live_client.post(
|
|
"/agents/run",
|
|
json={
|
|
"agent_type": "explore",
|
|
# Missing prompt
|
|
},
|
|
)
|
|
|
|
assert response.status_code == 422
|
|
|
|
@pytest.mark.anyio
|
|
async def test_agent_not_found(self, live_client):
|
|
"""Test 404 for unknown agent info."""
|
|
response = await live_client.get("/agents/unknown_agent")
|
|
|
|
assert response.status_code == 404
|
|
|
|
|
|
class TestRealWorldScenarios:
|
|
"""E2E tests for real-world usage scenarios."""
|
|
|
|
@pytest.mark.anyio
|
|
async def test_explore_codebase(self, live_client, sample_project):
|
|
"""Test exploring a real codebase."""
|
|
response = await live_client.post(
|
|
"/agents/run",
|
|
json={
|
|
"agent_type": "explore",
|
|
"prompt": "What functions are defined in the src directory?",
|
|
"working_dir": str(sample_project),
|
|
},
|
|
timeout=60.0,
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data.get("success") is True
|
|
|
|
# Should mention some functions
|
|
assert_contains_any(
|
|
data.get("response", ""),
|
|
["greet", "add", "divide", "factorial", "function"]
|
|
)
|
|
|
|
@pytest.mark.anyio
|
|
async def test_find_bugs(self, live_client, sample_project_with_bug):
|
|
"""Test finding bugs in code."""
|
|
response = await live_client.post(
|
|
"/agents/run",
|
|
json={
|
|
"agent_type": "explore",
|
|
"prompt": "Review buggy.py and identify any potential bugs or issues.",
|
|
"working_dir": str(sample_project_with_bug),
|
|
},
|
|
timeout=60.0,
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data.get("success") is True
|
|
|
|
# Should identify issues
|
|
assert_contains_any(
|
|
data.get("response", ""),
|
|
["zero", "division", "bug", "error", "issue", "check"]
|
|
)
|
|
|
|
@pytest.mark.anyio
|
|
async def test_read_and_summarize(self, live_client, sample_project):
|
|
"""Test reading and summarizing a file."""
|
|
response = await live_client.post(
|
|
"/agents/run",
|
|
json={
|
|
"agent_type": "explore",
|
|
"prompt": "Read README.md and give me a one-sentence summary.",
|
|
"working_dir": str(sample_project),
|
|
},
|
|
timeout=60.0,
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data.get("success") is True
|
|
assert len(data.get("response", "")) > 10
|