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
300 lines
10 KiB
Python
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"
|