Das Szenario-Vergleich-Panel zeichnet die Projektion (Zukunft, horizon_days ab heute). Kein Panel nutzt $__timeFilter, daher begrenzt allein das Dashboard-Zeitfenster die Anzeige. Mit time.to='now' wurde die gesamte Kurve ab morgen abgeschnitten (nur ~4 Tage <= heute sichtbar, Y-Achse auf deren schmalen Bereich fixiert). Fix: time.to='now+19M' deckt den 548-Tage-Horizont ab. Regressionstest tests/test_grafana_dashboard.py haelt die Invariante fest. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
52 lines
1.8 KiB
Python
52 lines
1.8 KiB
Python
"""Regressionstests fuer das provisionierte Grafana-Dashboard finanzen.json.
|
|
|
|
Hintergrund: Kein Panel nutzt $__timeFilter, jedes liefert alle Zeilen und
|
|
Grafana beschneidet auf das Dashboard-Zeitfenster. Das Szenario-Vergleich-Panel
|
|
zeichnet die Projektion (Zukunft, horizon_days ab heute). Steht 'to' auf 'now',
|
|
wird die gesamte Kurve ab morgen abgeschnitten (nur die ~4 Tage <= heute
|
|
sichtbar, Y-Achse auf deren schmalen Bereich fixiert). Dieser Test haelt fest,
|
|
dass 'to' weit genug in die Zukunft reicht.
|
|
"""
|
|
import json
|
|
import re
|
|
from pathlib import Path
|
|
|
|
from app.config import get_settings
|
|
|
|
DASHBOARD = Path(__file__).resolve().parent.parent / "grafana" / "dashboards" / "finanzen.json"
|
|
|
|
_UNIT_DAYS = {"y": 365, "M": 30, "w": 7, "d": 1, "h": 1 / 24}
|
|
|
|
|
|
def _relative_to_days(expr: str) -> float:
|
|
"""Grafana-Relativausdruck ('now', 'now+19M', 'now-1y') -> vorzeichen-
|
|
behafteter Tages-Offset relativ zu 'now' (Zukunft positiv)."""
|
|
expr = expr.strip()
|
|
if expr == "now":
|
|
return 0.0
|
|
m = re.fullmatch(r"now([+-])(\d+)([yMwdh])", expr)
|
|
if not m:
|
|
raise ValueError(f"Unerwarteter Grafana-Zeitausdruck: {expr!r}")
|
|
sign = 1 if m.group(1) == "+" else -1
|
|
return sign * int(m.group(2)) * _UNIT_DAYS[m.group(3)]
|
|
|
|
|
|
def _load() -> dict:
|
|
return json.loads(DASHBOARD.read_text())
|
|
|
|
|
|
def test_dashboard_has_szenario_panel():
|
|
titles = [p.get("title") for p in _load().get("panels", [])]
|
|
assert "Szenario-Vergleich" in titles
|
|
|
|
|
|
def test_time_window_covers_projection_horizon():
|
|
d = _load()
|
|
horizon = get_settings().horizon_days
|
|
to_days = _relative_to_days(d["time"]["to"])
|
|
assert to_days >= horizon, (
|
|
f"time.to reicht nur {to_days} Tage in die Zukunft, deckt aber den "
|
|
f"Projektionshorizont von {horizon} Tagen nicht ab -> Projektionskurve "
|
|
f"wird abgeschnitten"
|
|
)
|