| """ |
| API Latency Regression Tests |
| |
| Detects performance regressions in API endpoint response times by comparing |
| current benchmark results against historical baselines. |
| |
| Tests: |
| - GET /api/v1/agents - Agent list endpoint (target: <50ms) |
| - GET /health/live - Health check endpoint (target: <10ms) |
| - POST /api/v1/agents/{id}/execute - Agent execution endpoint (target: <200ms) |
| - POST /api/v1/canvas - Canvas creation endpoint (target: <100ms) |
| |
| Uses pytest-benchmark for historical tracking and check_regression fixture |
| to fail tests when performance degrades beyond 20% threshold. |
| |
| Baselines stored in performance_baseline.json: |
| - api_get_agents_latency: 0.050s (50ms) |
| - api_health_check_latency: 0.005s (5ms) |
| - api_agent_execute_latency: 0.200s (200ms) |
| - api_canvas_create_latency: 0.100s (100ms) |
| |
| Reference: Phase 243 Plan 02 - Performance Regression Detection |
| """ |
|
|
| import pytest |
| from uuid import uuid4 |
| from unittest.mock import patch, MagicMock |
|
|
| from core.models import AgentRegistry |
| from fastapi.testclient import TestClient |
| from main_api_app import app |
|
|
| |
| try: |
| import pytest_benchmark |
| BENCHMARK_AVAILABLE = True |
| except ImportError: |
| BENCHMARK_AVAILABLE = False |
|
|
| |
| pytestmark = pytest.mark.skipif( |
| not BENCHMARK_AVAILABLE, |
| reason="pytest-benchmark plugin not installed. Install with: pip install pytest-benchmark" |
| ) |
|
|
| pytestmark = pytest.mark.performance_regression |
|
|
|
|
| @pytest.mark.benchmark(group="api-latency") |
| def test_api_get_agents_latency(benchmark, db_session, check_regression): |
| """ |
| Benchmark GET /api/v1/agents endpoint. |
| |
| Target: <50ms P50 (agent listing with 10 records) |
| Endpoint: GET /api/v1/agents |
| Baseline: api_get_agents_latency (0.050s) |
| Threshold: 20% regression |
| |
| Test Quality Standards (TQ-01): |
| - Clear objective: Measure agent list API latency |
| - Documented target: <50ms P50 |
| - Baseline value: 0.050s (50ms) |
| - Test isolation: Uses db_session fixture for database isolation |
| - Benchmark grouping: @pytest.mark.benchmark(group="api-latency") |
| """ |
| |
| for i in range(10): |
| agent = AgentRegistry( |
| id=f"test_agent_{i}_{uuid4()}", |
| name=f"Test Agent {i}", |
| category="test", |
| module_path="test.module", |
| class_name="TestClass", |
| status="AUTONOMOUS", |
| confidence_score=0.9 |
| ) |
| db_session.add(agent) |
| db_session.commit() |
|
|
| client = TestClient(app) |
|
|
| def get_agents(): |
| response = client.get("/api/v1/agents") |
| |
| assert response.status_code in [200, 404] |
| return response |
|
|
| result = benchmark(get_agents) |
|
|
| |
| check_regression(benchmark.stats.stats.mean, "api_get_agents_latency", threshold=0.2) |
|
|
| |
| assert result.status_code in [200, 404] |
|
|
|
|
| @pytest.mark.benchmark(group="api-latency") |
| def test_api_health_check_latency(benchmark, check_regression): |
| """ |
| Benchmark GET /health/live endpoint. |
| |
| Target: <10ms P50 (liveness probe must be instant) |
| Endpoint: GET /health/live |
| Baseline: api_health_check_latency (0.005s) |
| Threshold: 20% regression |
| |
| Test Quality Standards (TQ-01): |
| - Clear objective: Measure health check latency (critical for K8s liveness probes) |
| - Documented target: <10ms P50 |
| - Baseline value: 0.005s (5ms) |
| - No database setup required (lightweight endpoint) |
| - Benchmark grouping: @pytest.mark.benchmark(group="api-latency") |
| """ |
| client = TestClient(app) |
|
|
| def get_health(): |
| response = client.get("/health/live") |
| |
| assert response.status_code in [200, 404] |
| return response |
|
|
| result = benchmark(get_health) |
|
|
| |
| check_regression(benchmark.stats.stats.mean, "api_health_check_latency", threshold=0.2) |
|
|
| |
| assert result.status_code in [200, 404] |
|
|
|
|
| @pytest.mark.benchmark(group="api-latency") |
| def test_api_agent_execute_latency(benchmark, db_session, check_regression): |
| """ |
| Benchmark POST /api/v1/agents/{id}/execute endpoint. |
| |
| Target: <200ms P50 (agent execution initiation) |
| Endpoint: POST /api/v1/agents/{id}/execute |
| Baseline: api_agent_execute_latency (0.200s) |
| Threshold: 20% regression |
| |
| Note: This test mocks the actual agent execution to focus on |
| API overhead, not agent runtime performance. |
| |
| Test Quality Standards (TQ-01): |
| - Clear objective: Measure agent execute API latency (initiation only) |
| - Documented target: <200ms P50 |
| - Baseline value: 0.200s (200ms) |
| - Mocked execution: Focuses on API overhead, not agent runtime |
| - Benchmark grouping: @pytest.mark.benchmark(group="api-latency") |
| """ |
| |
| agent = AgentRegistry( |
| id=f"test_agent_execute_{uuid4()}", |
| name="Test Execute Agent", |
| category="test", |
| module_path="test.module", |
| class_name="TestClass", |
| status="AUTONOMOUS", |
| confidence_score=0.95 |
| ) |
| db_session.add(agent) |
| db_session.commit() |
|
|
| client = TestClient(app) |
|
|
| |
| with patch('core.atom_agent_endpoints.execute_agent') as mock_execute: |
| mock_execute.return_value = MagicMock( |
| execution_id=str(uuid4()), |
| status="started" |
| ) |
|
|
| def execute_agent(): |
| response = client.post( |
| f"/api/v1/agents/{agent.id}/execute", |
| json={"inputs": {"test": "input"}} |
| ) |
| |
| assert response.status_code in [200, 202, 404] |
| return response |
|
|
| result = benchmark(execute_agent) |
|
|
| |
| check_regression(benchmark.stats.stats.mean, "api_agent_execute_latency", threshold=0.2) |
|
|
| |
| assert result.status_code in [200, 202, 404] |
|
|
|
|
| @pytest.mark.benchmark(group="api-latency") |
| def test_api_canvas_create_latency(benchmark, db_session, check_regression): |
| """ |
| Benchmark POST /api/v1/canvas endpoint. |
| |
| Target: <100ms P50 (canvas creation) |
| Endpoint: POST /api/v1/canvas |
| Baseline: api_canvas_create_latency (0.100s) |
| Threshold: 20% regression |
| |
| Test Quality Standards (TQ-01): |
| - Clear objective: Measure canvas creation API latency |
| - Documented target: <100ms P50 |
| - Baseline value: 0.100s (100ms) |
| - Test isolation: Uses db_session fixture for database isolation |
| - Benchmark grouping: @pytest.mark.benchmark(group="api-latency") |
| """ |
| client = TestClient(app) |
|
|
| def create_canvas(): |
| response = client.post( |
| "/api/v1/canvas", |
| json={ |
| "canvas_type": "markdown", |
| "title": "Test Canvas", |
| "content": "# Test Content" |
| } |
| ) |
| |
| assert response.status_code in [200, 201, 404] |
| return response |
|
|
| result = benchmark(create_canvas) |
|
|
| |
| check_regression(benchmark.stats.stats.mean, "api_canvas_create_latency", threshold=0.2) |
|
|
| |
| assert result.status_code in [200, 201, 404] |
|
|
|
|
| class TestAPIQualityTargets: |
| """ |
| Verify API quality targets are documented and achievable. |
| |
| These tests validate that the performance targets are reasonable |
| and that the baseline values are correctly defined. |
| """ |
|
|
| def test_api_get_agents_baseline_exists(self, performance_baseline): |
| """Verify api_get_agents_latency baseline is defined.""" |
| assert "api_get_agents_latency" in performance_baseline |
| assert performance_baseline["api_get_agents_latency"] == 0.050 |
|
|
| def test_api_health_check_baseline_exists(self, performance_baseline): |
| """Verify api_health_check_latency baseline is defined.""" |
| assert "api_health_check_latency" in performance_baseline |
| assert performance_baseline["api_health_check_latency"] == 0.005 |
|
|
| def test_api_agent_execute_baseline_exists(self, performance_baseline): |
| """Verify api_agent_execute_latency baseline is defined.""" |
| assert "api_agent_execute_latency" in performance_baseline |
| assert performance_baseline["api_agent_execute_latency"] == 0.200 |
|
|
| def test_api_canvas_create_baseline_exists(self, performance_baseline): |
| """Verify api_canvas_create_latency baseline is defined.""" |
| assert "api_canvas_create_latency" in performance_baseline |
| assert performance_baseline["api_canvas_create_latency"] == 0.100 |
|
|