Picarones / tests /architecture /test_s8_metrics_endpoint.py
Claude
feat(sprint-S8): cohรฉrence finale โ€” renames test dirs, /metrics endpoint, SBOM workflow
43478ec unverified
Raw
History Blame
5.55 kB
"""Sprint S8.2 โ€” Endpoint Prometheus ``/metrics``.
Vรฉrifie :
1. Dรฉsactivรฉ par dรฉfaut โ†’ 404.
2. Activรฉ via ``PICARONES_METRICS_ENABLED=1`` โ†’ 200 avec format
Prometheus exposition.
3. Mรฉtriques attendues : ``picarones_app_info``,
``picarones_jobs_total{status="..."}``, alias gauges.
4. Tolรฉrance store inaccessible : retourne ``picarones_app_info``
sans crasher.
"""
from __future__ import annotations
import pytest
def _make_app():
from fastapi import FastAPI
from picarones.interfaces.web.routers import system as sys_router
app = FastAPI()
app.include_router(sys_router.router)
return app
# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
# 1. Dรฉsactivรฉ par dรฉfaut
# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
class TestMetricsDisabledByDefault:
def test_404_when_env_not_set(
self, monkeypatch: pytest.MonkeyPatch,
) -> None:
from fastapi.testclient import TestClient
monkeypatch.delenv("PICARONES_METRICS_ENABLED", raising=False)
app = _make_app()
with TestClient(app) as client:
r = client.get("/metrics")
assert r.status_code == 404
assert "PICARONES_METRICS_ENABLED" in r.text
# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
# 2. Format Prometheus quand activรฉ
# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
class TestMetricsFormat:
def test_200_with_prometheus_content_type(
self, monkeypatch: pytest.MonkeyPatch,
) -> None:
from fastapi.testclient import TestClient
monkeypatch.setenv("PICARONES_METRICS_ENABLED", "1")
app = _make_app()
with TestClient(app) as client:
r = client.get("/metrics")
assert r.status_code == 200
ct = r.headers.get("content-type", "")
assert "text/plain" in ct
assert "version=0.0.4" in ct
def test_exposes_app_info(
self, monkeypatch: pytest.MonkeyPatch,
) -> None:
from fastapi.testclient import TestClient
monkeypatch.setenv("PICARONES_METRICS_ENABLED", "1")
app = _make_app()
with TestClient(app) as client:
r = client.get("/metrics")
text = r.text
assert "# TYPE picarones_app_info gauge" in text
assert 'picarones_app_info{version=' in text
assert text.rstrip().endswith("1") or "} 1" in text
def test_exposes_jobs_total_per_status(
self, monkeypatch: pytest.MonkeyPatch,
) -> None:
from fastapi.testclient import TestClient
monkeypatch.setenv("PICARONES_METRICS_ENABLED", "1")
app = _make_app()
with TestClient(app) as client:
r = client.get("/metrics")
text = r.text
# Chaque statut connu apparaรฎt, mรชme ร  0
for status in ("pending", "running", "complete", "error",
"cancelled", "interrupted"):
assert f'status="{status}"' in text, (
f"Statut ``{status}`` absent du payload"
)
def test_exposes_alias_gauges(
self, monkeypatch: pytest.MonkeyPatch,
) -> None:
from fastapi.testclient import TestClient
monkeypatch.setenv("PICARONES_METRICS_ENABLED", "1")
app = _make_app()
with TestClient(app) as client:
r = client.get("/metrics")
text = r.text
assert "picarones_jobs_pending" in text
assert "picarones_jobs_running" in text
# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
# 3. Activation insensible casse / yes / true
# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
class TestEnvVarParsing:
@pytest.mark.parametrize("value", ["1", "true", "yes"])
def test_truthy_values_enable(
self, monkeypatch: pytest.MonkeyPatch, value: str,
) -> None:
from fastapi.testclient import TestClient
monkeypatch.setenv("PICARONES_METRICS_ENABLED", value)
app = _make_app()
with TestClient(app) as client:
r = client.get("/metrics")
assert r.status_code == 200
@pytest.mark.parametrize("value", ["0", "false", "no", "", "off"])
def test_falsy_values_keep_disabled(
self, monkeypatch: pytest.MonkeyPatch, value: str,
) -> None:
from fastapi.testclient import TestClient
monkeypatch.setenv("PICARONES_METRICS_ENABLED", value)
app = _make_app()
with TestClient(app) as client:
r = client.get("/metrics")
assert r.status_code == 404