feat: endpoint /health avec tests (8 tests)
Ajoute GET /health retournant un JSON avec : - status: "ok" - version: "2.1.0" - ollama: true/false (connectivité testée avec timeout 2s) - timestamp: ISO 8601 UTC Tests couvrent : format JSON, champs requis, Ollama joignable/injoignable, format timestamp ISO, type booléen du champ ollama. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -616,4 +616,21 @@ def create_app() -> Flask:
|
|||||||
metrics=metrics, total_selection=len(selection),
|
metrics=metrics, total_selection=len(selection),
|
||||||
groups=groups)
|
groups=groups)
|
||||||
|
|
||||||
|
# --- Health check endpoint ---
|
||||||
|
@app.route("/health")
|
||||||
|
def health():
|
||||||
|
from datetime import datetime, timezone
|
||||||
|
ollama_ok = False
|
||||||
|
try:
|
||||||
|
r = requests.get(f"{OLLAMA_URL}/api/tags", timeout=2)
|
||||||
|
ollama_ok = r.status_code == 200
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return jsonify({
|
||||||
|
"status": "ok",
|
||||||
|
"version": "2.1.0",
|
||||||
|
"ollama": ollama_ok,
|
||||||
|
"timestamp": datetime.now(timezone.utc).isoformat(),
|
||||||
|
})
|
||||||
|
|
||||||
return app
|
return app
|
||||||
|
|||||||
79
tests/test_health_endpoint.py
Normal file
79
tests/test_health_endpoint.py
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
"""Tests pour le endpoint /health du viewer Flask."""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
from unittest.mock import patch, MagicMock
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
import requests
|
||||||
|
|
||||||
|
from src.viewer.app import create_app
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def app():
|
||||||
|
with patch.dict(os.environ, {"T2A_DEMO_USER": "", "T2A_DEMO_PASS": ""}):
|
||||||
|
app = create_app()
|
||||||
|
app.config["TESTING"] = True
|
||||||
|
yield app
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def client(app):
|
||||||
|
return app.test_client()
|
||||||
|
|
||||||
|
|
||||||
|
class TestHealthEndpoint:
|
||||||
|
|
||||||
|
def test_health_returns_200(self, client):
|
||||||
|
response = client.get("/health")
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
def test_health_returns_json(self, client):
|
||||||
|
response = client.get("/health")
|
||||||
|
data = response.get_json()
|
||||||
|
assert data is not None
|
||||||
|
assert data["status"] == "ok"
|
||||||
|
|
||||||
|
def test_health_contains_required_fields(self, client):
|
||||||
|
response = client.get("/health")
|
||||||
|
data = response.get_json()
|
||||||
|
assert "status" in data
|
||||||
|
assert "version" in data
|
||||||
|
assert "ollama" in data
|
||||||
|
assert "timestamp" in data
|
||||||
|
|
||||||
|
def test_health_version_format(self, client):
|
||||||
|
response = client.get("/health")
|
||||||
|
data = response.get_json()
|
||||||
|
assert data["version"] == "2.1.0"
|
||||||
|
|
||||||
|
def test_health_timestamp_is_iso(self, client):
|
||||||
|
from datetime import datetime
|
||||||
|
response = client.get("/health")
|
||||||
|
data = response.get_json()
|
||||||
|
# Should parse without error
|
||||||
|
ts = datetime.fromisoformat(data["timestamp"])
|
||||||
|
assert ts is not None
|
||||||
|
|
||||||
|
@patch("src.viewer.app.requests.get")
|
||||||
|
def test_health_ollama_reachable(self, mock_get, client):
|
||||||
|
"""Quand Ollama répond, ollama=True."""
|
||||||
|
mock_resp = MagicMock()
|
||||||
|
mock_resp.status_code = 200
|
||||||
|
mock_get.return_value = mock_resp
|
||||||
|
response = client.get("/health")
|
||||||
|
data = response.get_json()
|
||||||
|
assert data["ollama"] is True
|
||||||
|
|
||||||
|
@patch("src.viewer.app.requests.get", side_effect=requests.ConnectionError("refused"))
|
||||||
|
def test_health_ollama_unreachable(self, mock_get, client):
|
||||||
|
"""Quand Ollama est injoignable, ollama=False."""
|
||||||
|
response = client.get("/health")
|
||||||
|
data = response.get_json()
|
||||||
|
assert data["ollama"] is False
|
||||||
|
|
||||||
|
def test_health_ollama_is_bool(self, client):
|
||||||
|
response = client.get("/health")
|
||||||
|
data = response.get_json()
|
||||||
|
assert isinstance(data["ollama"], bool)
|
||||||
Reference in New Issue
Block a user