homelab_automation/tests/backend/test_routes_metrics.py
Bruno Charest ecefbc8611
Some checks failed
Tests / Backend Tests (Python) (3.10) (push) Has been cancelled
Tests / Backend Tests (Python) (3.11) (push) Has been cancelled
Tests / Backend Tests (Python) (3.12) (push) Has been cancelled
Tests / Frontend Tests (JS) (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / All Tests Passed (push) Has been cancelled
Clean up test files and debug artifacts, add node_modules to gitignore, export DashboardManager for testing, and enhance pytest configuration with comprehensive test markers and settings
2025-12-15 08:15:49 -05:00

300 lines
10 KiB
Python

"""
Tests pour les routes metrics.
"""
import pytest
from unittest.mock import patch, AsyncMock, MagicMock
from httpx import AsyncClient
from sqlalchemy.ext.asyncio import AsyncSession
pytestmark = pytest.mark.unit
class TestGetMetrics:
"""Tests pour GET /api/metrics."""
@pytest.mark.asyncio
async def test_get_metrics(self, client: AsyncClient):
"""Récupération des métriques globales."""
response = await client.get("/api/metrics")
assert response.status_code == 200
data = response.json()
assert "online_hosts" in data or "total_tasks" in data
class TestGetAllHostsMetrics:
"""Tests pour GET /api/metrics/all-hosts."""
@pytest.mark.asyncio
async def test_get_all_hosts_metrics_empty(self, client: AsyncClient, db_session: AsyncSession):
"""Métriques vides."""
response = await client.get("/api/metrics/all-hosts")
assert response.status_code == 200
data = response.json()
assert isinstance(data, dict)
@pytest.mark.asyncio
async def test_get_all_hosts_metrics_with_data(self, client: AsyncClient, db_session: AsyncSession, host_factory):
"""Métriques avec données."""
from app.crud.host_metrics import HostMetricsRepository
host = await host_factory.create(db_session, name="metrics-test-host")
repo = HostMetricsRepository(db_session)
await repo.create(
host_id=host.id,
metric_type="system_info",
cpu_usage_percent=50.0,
memory_usage_percent=60.0
)
await db_session.commit()
response = await client.get("/api/metrics/all-hosts")
assert response.status_code == 200
class TestGetCollectionSchedule:
"""Tests pour GET /api/metrics/collection-schedule."""
@pytest.mark.asyncio
async def test_get_schedule_default(self, client: AsyncClient):
"""Intervalle par défaut."""
response = await client.get("/api/metrics/collection-schedule")
assert response.status_code == 200
data = response.json()
assert "interval" in data
@pytest.mark.asyncio
async def test_get_schedule_with_setting(self, client: AsyncClient, db_session: AsyncSession):
"""Intervalle configuré."""
from app.crud.app_setting import AppSettingRepository
repo = AppSettingRepository(db_session)
await repo.set("metrics_collection_interval", "15min")
await db_session.commit()
response = await client.get("/api/metrics/collection-schedule")
assert response.status_code == 200
data = response.json()
assert data["interval"] == "15min"
class TestSetCollectionSchedule:
"""Tests pour POST /api/metrics/collection-schedule."""
@pytest.mark.asyncio
async def test_set_schedule_valid(self, client: AsyncClient):
"""Définition d'un intervalle valide."""
response = await client.post(
"/api/metrics/collection-schedule",
json={"interval": "30min"}
)
assert response.status_code == 200
data = response.json()
assert data["interval"] == "30min"
@pytest.mark.asyncio
async def test_set_schedule_off(self, client: AsyncClient):
"""Désactivation de la collecte."""
response = await client.post(
"/api/metrics/collection-schedule",
json={"interval": "off"}
)
assert response.status_code == 200
data = response.json()
assert data["interval"] == "off"
@pytest.mark.asyncio
async def test_set_schedule_invalid(self, client: AsyncClient):
"""Intervalle invalide."""
response = await client.post(
"/api/metrics/collection-schedule",
json={"interval": "invalid"}
)
assert response.status_code == 400
class TestGetHostMetrics:
"""Tests pour GET /api/metrics/{host_id}."""
@pytest.mark.asyncio
async def test_get_host_metrics_no_data(self, client: AsyncClient):
"""Hôte sans métriques."""
response = await client.get("/api/metrics/nonexistent-host")
assert response.status_code == 200
data = response.json()
assert data["collection_status"] == "no_data"
@pytest.mark.asyncio
async def test_get_host_metrics_with_data(self, client: AsyncClient, db_session: AsyncSession, host_factory):
"""Hôte avec métriques."""
from app.crud.host_metrics import HostMetricsRepository
host = await host_factory.create(db_session, name="host-with-metrics")
repo = HostMetricsRepository(db_session)
await repo.create(
host_id=host.id,
metric_type="system_info",
cpu_usage_percent=45.5,
memory_usage_percent=70.0,
disk_root_usage_percent=55.0
)
await db_session.commit()
response = await client.get(f"/api/metrics/{host.id}")
assert response.status_code == 200
data = response.json()
assert data["host_id"] == host.id
assert data["cpu_usage_percent"] == 45.5
class TestMetricsWithErrors:
"""Tests pour les cas d'erreur des métriques."""
@pytest.mark.asyncio
async def test_get_all_hosts_metrics_exception(self, client: AsyncClient):
"""Gestion des exceptions pour all-hosts."""
with patch("app.routes.metrics.HostMetricsRepository") as mock_repo:
mock_repo.return_value.get_all_latest = AsyncMock(side_effect=Exception("DB error"))
response = await client.get("/api/metrics/all-hosts")
# Should return empty dict on error
assert response.status_code == 200
assert response.json() == {}
@pytest.mark.asyncio
async def test_get_collection_schedule_exception(self, client: AsyncClient):
"""Gestion des exceptions pour collection-schedule."""
with patch("app.routes.metrics.AppSettingRepository") as mock_repo:
mock_repo.return_value.get = AsyncMock(side_effect=Exception("DB error"))
response = await client.get("/api/metrics/collection-schedule")
# Should return default "off" on error
assert response.status_code == 200
assert response.json()["interval"] == "off"
@pytest.mark.asyncio
async def test_set_collection_schedule_exception(self, client: AsyncClient):
"""Gestion des exceptions pour set collection-schedule."""
with patch("app.routes.metrics.AppSettingRepository") as mock_repo:
mock_repo.return_value.set = AsyncMock(side_effect=Exception("DB error"))
response = await client.post(
"/api/metrics/collection-schedule",
json={"interval": "5min"}
)
assert response.status_code == 500
@pytest.mark.asyncio
async def test_get_host_metrics_exception(self, client: AsyncClient):
"""Gestion des exceptions pour host metrics."""
with patch("app.routes.metrics.HostMetricsRepository") as mock_repo:
mock_repo.return_value.get_latest_for_host = AsyncMock(side_effect=Exception("DB error"))
response = await client.get("/api/metrics/test-host")
assert response.status_code == 200
data = response.json()
assert data["collection_status"] == "error"
assert "error_message" in data
@pytest.mark.asyncio
async def test_get_host_metrics_with_error_message(self, client: AsyncClient, db_session: AsyncSession, host_factory):
"""Métriques avec message d'erreur."""
from app.crud.host_metrics import HostMetricsRepository
host = await host_factory.create(db_session, name="host-with-error")
repo = HostMetricsRepository(db_session)
await repo.create(
host_id=host.id,
metric_type="system_info",
error_message="Connection failed"
)
await db_session.commit()
response = await client.get(f"/api/metrics/{host.id}")
assert response.status_code == 200
data = response.json()
assert data["collection_status"] == "failed"
assert data["error_message"] == "Connection failed"
class TestSetCollectionScheduleAllIntervals:
"""Tests pour tous les intervalles valides."""
@pytest.mark.asyncio
async def test_set_schedule_5min(self, client: AsyncClient):
"""Intervalle 5min."""
response = await client.post(
"/api/metrics/collection-schedule",
json={"interval": "5min"}
)
assert response.status_code == 200
assert response.json()["interval"] == "5min"
@pytest.mark.asyncio
async def test_set_schedule_15min(self, client: AsyncClient):
"""Intervalle 15min."""
response = await client.post(
"/api/metrics/collection-schedule",
json={"interval": "15min"}
)
assert response.status_code == 200
assert response.json()["interval"] == "15min"
@pytest.mark.asyncio
async def test_set_schedule_1h(self, client: AsyncClient):
"""Intervalle 1h."""
response = await client.post(
"/api/metrics/collection-schedule",
json={"interval": "1h"}
)
assert response.status_code == 200
assert response.json()["interval"] == "1h"
@pytest.mark.asyncio
async def test_set_schedule_6h(self, client: AsyncClient):
"""Intervalle 6h."""
response = await client.post(
"/api/metrics/collection-schedule",
json={"interval": "6h"}
)
assert response.status_code == 200
assert response.json()["interval"] == "6h"
@pytest.mark.asyncio
async def test_set_schedule_12h(self, client: AsyncClient):
"""Intervalle 12h."""
response = await client.post(
"/api/metrics/collection-schedule",
json={"interval": "12h"}
)
assert response.status_code == 200
assert response.json()["interval"] == "12h"
@pytest.mark.asyncio
async def test_set_schedule_24h(self, client: AsyncClient):
"""Intervalle 24h."""
response = await client.post(
"/api/metrics/collection-schedule",
json={"interval": "24h"}
)
assert response.status_code == 200
assert response.json()["interval"] == "24h"