#!/usr/bin/env python3 """pruefen(): was tatsächlich in der Tagesliste landet - und was nicht. Ergänzt test_messzeitpunkt.py um den ganzen Weg: der Helfer entscheidet, diese Tests belegen, dass die Entscheidung auch ankommt. Zwei Dinge stehen hier auf dem Prüfstand, beide am Bestand des Testcontainers gemessen (06.09.2026): 1. Eine veraltete Messung darf keinen Eintrag erzeugen. Der 16.08.2026 trug einen Tageseintrag, obwohl der Spannungssensor an diesem Tag kein einziges Mal gemeldet hatte. 2. Sie darf auch nicht alle fünf Minuten dieselbe Warnung erzeugen. Im laufenden Container standen 77 identische Zeilen "Batteriespannung 0.0 V unter der Plausibilitätsgrenze" in 3000 Protokollzeilen - über einen Wert, der sich seit 5½ Stunden nicht gerührt hatte. Deshalb kommt die Frischeprüfung VOR der Plausibilitätsgrenze. Aufruf: python3 tests/batterie/test_pruefen.py (braucht das homeassistant-Paket, weil die Integration es importiert - also z. B. im Test-Container) """ import asyncio import datetime import logging import os import sys import unittest _HIER = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, os.path.dirname(os.path.dirname(_HIER))) from custom_components.audi_dashboard import batterie as b # noqa: E402 SPANNUNGSSENSOR = "sensor.spannung" class Zustand: def __init__(self, last_updated, state=""): self.last_updated = last_updated self.state = state class Zustaende: def __init__(self, daten): self._daten = daten def get(self, entity_id): return self._daten.get(entity_id) class Hass: def __init__(self, daten): self.states = Zustaende(daten) class Werte: BATTERIE_SENSOR = SPANNUNGSSENSOR AUSSENTEMP_SENSOR = "" MELDEZEIT_SENSOR = "" class Zuordnung: def __init__(self): self.werte = Werte() class Ablage: def __init__(self): self.eintraege = [] async def batterieverlauf_tageswert_aktualisieren(self, tag, ts, spannung, temp): self.eintraege.append({"tag": tag, "ts": ts, "spannung": spannung, "temp": temp}) class Koordinator: def __init__(self, alter_s, spannung): gemessen = datetime.datetime.now(datetime.UTC) - datetime.timedelta(seconds=alter_s) self.gemessen = gemessen self.hass = Hass({SPANNUNGSSENSOR: Zustand(gemessen, str(spannung))}) self.zuordnung = Zuordnung() self.ablage = Ablage() self.veroeffentlicht = 0 async def batterieverlauf_veroeffentlichen(self): self.veroeffentlicht += 1 def lauf(k): asyncio.run(b.pruefen(k)) return k class WasErfasstWird(unittest.TestCase): def test_frische_messung_landet_mit_ihrer_eigenen_zeit(self): k = lauf(Koordinator(alter_s=12, spannung=12.4)) self.assertEqual(len(k.ablage.eintraege), 1) e = k.ablage.eintraege[0] # Der entscheidende Unterschied zum alten Stand: nicht "jetzt", sondern # der Zeitpunkt der Messung - und der Tag wird aus ihm abgeleitet. self.assertEqual(e["ts"], k.gemessen.isoformat()) self.assertEqual(e["tag"], k.gemessen.date().isoformat()) self.assertEqual(e["spannung"], 12.4) self.assertEqual(k.veroeffentlicht, 1) def test_veraltete_messung_landet_gar_nicht(self): """Der Fall 16.08.2026 - Eintrag ohne eine einzige Meldung an dem Tag.""" k = lauf(Koordinator(alter_s=885 * 60, spannung=13.024)) self.assertEqual(k.ablage.eintraege, []) self.assertEqual(k.veroeffentlicht, 0) def test_unplausible_messung_landet_nicht(self): k = lauf(Koordinator(alter_s=12, spannung=0.0)) self.assertEqual(k.ablage.eintraege, []) class WieOftGewarntWird(unittest.TestCase): def test_frische_unplausible_messung_warnt(self): with self.assertLogs("custom_components.audi_dashboard.batterie", level="DEBUG") as p: lauf(Koordinator(alter_s=12, spannung=0.0)) self.assertTrue(any(r.levelno == logging.WARNING for r in p.records)) def test_veraltete_unplausible_messung_warnt_nicht(self): """Sonst steht dieselbe Zeile alle fünf Minuten im Protokoll.""" with self.assertLogs("custom_components.audi_dashboard.batterie", level="DEBUG") as p: lauf(Koordinator(alter_s=5 * 3600, spannung=0.0)) self.assertFalse(any(r.levelno >= logging.WARNING for r in p.records)) if __name__ == "__main__": unittest.main(verbosity=2)