feat: Laientauglichkeit — Auto-Modus, Klartext-Ausgabe, einfachere Doku
Ziel: ein einziger täglicher Befehl genügt, jede Meldung ist auch ohne IT-Wissen verständlich. Auto-Modus (ein Cron-Job genügt für alles): - data/state.json merkt sich, wann die Wochen-Prüfungen zuletzt liefen (baseline.py: load_state/save_state/is_check_due/mark_check_run) - `scan` führt fällige Zusatzprüfungen (Tarnung/externe Links/Dateien) automatisch mit aus; Gesamt-Ampel = schlechtestes Teilergebnis; EIN kombinierter Report + EIN Alert - neuer Config-Abschnitt periodic_checks (Default: wöchentlich, an) Klartext (scanner/plain.py): - Ampel 🟢/🟡/🔴 + Sätze ohne Fachbegriffe, aus den strukturierten Befunden - Report: Klartext oben, "Technische Details (für Ihren Dienstleister)" unten - Terminal-Ausgabe und E-Mail (alerter.py) ebenso umgestellt Komfort: - approve --all/--rebuild legt die Datei-Überwachung automatisch mit an (Opt-out: --skip-assets); approve-assets bleibt für den Sonderfall - status zeigt Ampel zuoberst + wann die Wochen-Prüfungen zuletzt liefen - Onboarding-Text in einfacher Sprache, wenn noch kein Vergleichsstand existiert Doku: README + BEDIENUNGSANLEITUNG mit "In 3 Schritten"-Einstieg. Tests: test_state.py, test_plain.py (Fachbegriff-Assertion), Auto-Asset- Baseline-Test. 165 Tests grün. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
54ff1a6060
commit
bed20db8bd
11 changed files with 856 additions and 202 deletions
47
tests/test_state.py
Normal file
47
tests/test_state.py
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
"""Tests für die Zustandsdatei, die die Wochen-Prüfungen steuert."""
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
import pytest
|
||||
|
||||
from scanner.baseline import BaselineManager
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def bm(tmp_path):
|
||||
return BaselineManager(tmp_path)
|
||||
|
||||
|
||||
class TestRunState:
|
||||
def test_never_run_is_due(self, bm):
|
||||
assert bm.is_check_due("cloak_check", 7) is True
|
||||
|
||||
def test_just_run_is_not_due(self, bm):
|
||||
bm.mark_check_run("cloak_check")
|
||||
assert bm.is_check_due("cloak_check", 7) is False
|
||||
|
||||
def test_old_run_is_due(self, bm):
|
||||
# Lauf vor 10 Tagen → bei Intervall 7 fällig
|
||||
old = (datetime.now(timezone.utc) - timedelta(days=10)).isoformat()
|
||||
bm.save_state({"last_runs": {"assets": old}})
|
||||
assert bm.is_check_due("assets", 7) is True
|
||||
|
||||
def test_recent_run_within_interval_not_due(self, bm):
|
||||
recent = (datetime.now(timezone.utc) - timedelta(days=3)).isoformat()
|
||||
bm.save_state({"last_runs": {"assets": recent}})
|
||||
assert bm.is_check_due("assets", 7) is False
|
||||
|
||||
def test_save_load_roundtrip(self, bm):
|
||||
bm.mark_check_run("ext_links")
|
||||
state = bm.load_state()
|
||||
assert "ext_links" in state["last_runs"]
|
||||
|
||||
def test_corrupt_state_file_recovers(self, bm):
|
||||
bm._state_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
bm._state_path.write_text("{ not valid json", encoding="utf-8")
|
||||
# Darf nicht crashen, sondern als "nie gelaufen" gelten
|
||||
assert bm.load_state() == {"last_runs": {}}
|
||||
assert bm.is_check_due("cloak_check", 7) is True
|
||||
|
||||
def test_invalid_timestamp_is_due(self, bm):
|
||||
bm.save_state({"last_runs": {"assets": "kein-datum"}})
|
||||
assert bm.is_check_due("assets", 7) is True
|
||||
Loading…
Add table
Add a link
Reference in a new issue