This commit is contained in:
rUv
2025-06-07 11:44:19 +00:00
parent 43e92c5494
commit c378b705ca
95 changed files with 43677 additions and 0 deletions

View File

@@ -0,0 +1,338 @@
"""
Integration tests for WiFi-DensePose API endpoints.
Tests all REST API endpoints with real service dependencies.
"""
import pytest
import asyncio
from datetime import datetime, timedelta
from typing import Dict, Any
from unittest.mock import AsyncMock, MagicMock
from fastapi.testclient import TestClient
from fastapi import FastAPI
import httpx
from src.api.dependencies import (
get_pose_service,
get_stream_service,
get_hardware_service,
get_current_user
)
from src.api.routers.health import router as health_router
from src.api.routers.pose import router as pose_router
from src.api.routers.stream import router as stream_router
class TestAPIEndpoints:
"""Integration tests for API endpoints."""
@pytest.fixture
def app(self):
"""Create FastAPI app with test dependencies."""
app = FastAPI()
app.include_router(health_router, prefix="/health", tags=["health"])
app.include_router(pose_router, prefix="/pose", tags=["pose"])
app.include_router(stream_router, prefix="/stream", tags=["stream"])
return app
@pytest.fixture
def mock_pose_service(self):
"""Mock pose service."""
service = AsyncMock()
service.health_check.return_value = {
"status": "healthy",
"message": "Service operational",
"uptime_seconds": 3600.0,
"metrics": {"processed_frames": 1000}
}
service.is_ready.return_value = True
service.estimate_poses.return_value = {
"timestamp": datetime.utcnow(),
"frame_id": "test-frame-001",
"persons": [],
"zone_summary": {"zone1": 0},
"processing_time_ms": 50.0,
"metadata": {}
}
return service
@pytest.fixture
def mock_stream_service(self):
"""Mock stream service."""
service = AsyncMock()
service.health_check.return_value = {
"status": "healthy",
"message": "Stream service operational",
"uptime_seconds": 1800.0
}
service.is_ready.return_value = True
service.get_status.return_value = {
"is_active": True,
"active_streams": [],
"uptime_seconds": 1800.0
}
service.is_active.return_value = True
return service
@pytest.fixture
def mock_hardware_service(self):
"""Mock hardware service."""
service = AsyncMock()
service.health_check.return_value = {
"status": "healthy",
"message": "Hardware connected",
"uptime_seconds": 7200.0,
"metrics": {"connected_routers": 3}
}
service.is_ready.return_value = True
return service
@pytest.fixture
def mock_user(self):
"""Mock authenticated user."""
return {
"id": "test-user-001",
"username": "testuser",
"email": "test@example.com",
"is_admin": False,
"is_active": True,
"permissions": ["read", "write"]
}
@pytest.fixture
def client(self, app, mock_pose_service, mock_stream_service, mock_hardware_service, mock_user):
"""Create test client with mocked dependencies."""
app.dependency_overrides[get_pose_service] = lambda: mock_pose_service
app.dependency_overrides[get_stream_service] = lambda: mock_stream_service
app.dependency_overrides[get_hardware_service] = lambda: mock_hardware_service
app.dependency_overrides[get_current_user] = lambda: mock_user
with TestClient(app) as client:
yield client
def test_health_check_endpoint_should_fail_initially(self, client):
"""Test health check endpoint - should fail initially."""
# This test should fail because we haven't implemented the endpoint properly
response = client.get("/health/health")
# This assertion will fail initially, driving us to implement the endpoint
assert response.status_code == 200
assert "status" in response.json()
assert "components" in response.json()
assert "system_metrics" in response.json()
def test_readiness_check_endpoint_should_fail_initially(self, client):
"""Test readiness check endpoint - should fail initially."""
response = client.get("/health/ready")
# This will fail initially
assert response.status_code == 200
data = response.json()
assert "ready" in data
assert "checks" in data
assert isinstance(data["checks"], dict)
def test_liveness_check_endpoint_should_fail_initially(self, client):
"""Test liveness check endpoint - should fail initially."""
response = client.get("/health/live")
# This will fail initially
assert response.status_code == 200
data = response.json()
assert "status" in data
assert data["status"] == "alive"
def test_version_info_endpoint_should_fail_initially(self, client):
"""Test version info endpoint - should fail initially."""
response = client.get("/health/version")
# This will fail initially
assert response.status_code == 200
data = response.json()
assert "name" in data
assert "version" in data
assert "environment" in data
def test_pose_current_endpoint_should_fail_initially(self, client):
"""Test current pose estimation endpoint - should fail initially."""
response = client.get("/pose/current")
# This will fail initially
assert response.status_code == 200
data = response.json()
assert "timestamp" in data
assert "frame_id" in data
assert "persons" in data
assert "zone_summary" in data
def test_pose_analyze_endpoint_should_fail_initially(self, client):
"""Test pose analysis endpoint - should fail initially."""
request_data = {
"zone_ids": ["zone1", "zone2"],
"confidence_threshold": 0.7,
"max_persons": 10,
"include_keypoints": True,
"include_segmentation": False
}
response = client.post("/pose/analyze", json=request_data)
# This will fail initially
assert response.status_code == 200
data = response.json()
assert "timestamp" in data
assert "persons" in data
def test_zone_occupancy_endpoint_should_fail_initially(self, client):
"""Test zone occupancy endpoint - should fail initially."""
response = client.get("/pose/zones/zone1/occupancy")
# This will fail initially
assert response.status_code == 200
data = response.json()
assert "zone_id" in data
assert "current_occupancy" in data
def test_zones_summary_endpoint_should_fail_initially(self, client):
"""Test zones summary endpoint - should fail initially."""
response = client.get("/pose/zones/summary")
# This will fail initially
assert response.status_code == 200
data = response.json()
assert "total_persons" in data
assert "zones" in data
def test_stream_status_endpoint_should_fail_initially(self, client):
"""Test stream status endpoint - should fail initially."""
response = client.get("/stream/status")
# This will fail initially
assert response.status_code == 200
data = response.json()
assert "is_active" in data
assert "connected_clients" in data
def test_stream_start_endpoint_should_fail_initially(self, client):
"""Test stream start endpoint - should fail initially."""
response = client.post("/stream/start")
# This will fail initially
assert response.status_code == 200
data = response.json()
assert "message" in data
def test_stream_stop_endpoint_should_fail_initially(self, client):
"""Test stream stop endpoint - should fail initially."""
response = client.post("/stream/stop")
# This will fail initially
assert response.status_code == 200
data = response.json()
assert "message" in data
class TestAPIErrorHandling:
"""Test API error handling scenarios."""
@pytest.fixture
def app_with_failing_services(self):
"""Create app with failing service dependencies."""
app = FastAPI()
app.include_router(health_router, prefix="/health", tags=["health"])
app.include_router(pose_router, prefix="/pose", tags=["pose"])
# Mock failing services
failing_pose_service = AsyncMock()
failing_pose_service.health_check.side_effect = Exception("Service unavailable")
app.dependency_overrides[get_pose_service] = lambda: failing_pose_service
return app
def test_health_check_with_failing_service_should_fail_initially(self, app_with_failing_services):
"""Test health check with failing service - should fail initially."""
with TestClient(app_with_failing_services) as client:
response = client.get("/health/health")
# This will fail initially
assert response.status_code == 200
data = response.json()
assert data["status"] == "unhealthy"
assert "hardware" in data["components"]
assert data["components"]["pose"]["status"] == "unhealthy"
class TestAPIAuthentication:
"""Test API authentication scenarios."""
@pytest.fixture
def app_with_auth(self):
"""Create app with authentication enabled."""
app = FastAPI()
app.include_router(pose_router, prefix="/pose", tags=["pose"])
# Mock authenticated user dependency
def get_authenticated_user():
return {
"id": "auth-user-001",
"username": "authuser",
"is_admin": True,
"permissions": ["read", "write", "admin"]
}
app.dependency_overrides[get_current_user] = get_authenticated_user
return app
def test_authenticated_endpoint_access_should_fail_initially(self, app_with_auth):
"""Test authenticated endpoint access - should fail initially."""
with TestClient(app_with_auth) as client:
response = client.post("/pose/analyze", json={
"confidence_threshold": 0.8,
"include_keypoints": True
})
# This will fail initially
assert response.status_code == 200
class TestAPIValidation:
"""Test API request validation."""
@pytest.fixture
def validation_app(self):
"""Create app for validation testing."""
app = FastAPI()
app.include_router(pose_router, prefix="/pose", tags=["pose"])
# Mock service
mock_service = AsyncMock()
app.dependency_overrides[get_pose_service] = lambda: mock_service
return app
def test_invalid_confidence_threshold_should_fail_initially(self, validation_app):
"""Test invalid confidence threshold validation - should fail initially."""
with TestClient(validation_app) as client:
response = client.post("/pose/analyze", json={
"confidence_threshold": 1.5, # Invalid: > 1.0
"include_keypoints": True
})
# This will fail initially
assert response.status_code == 422
assert "validation error" in response.json()["detail"][0]["msg"].lower()
def test_invalid_max_persons_should_fail_initially(self, validation_app):
"""Test invalid max_persons validation - should fail initially."""
with TestClient(validation_app) as client:
response = client.post("/pose/analyze", json={
"max_persons": 0, # Invalid: < 1
"include_keypoints": True
})
# This will fail initially
assert response.status_code == 422