Files
breakpilot-compliance/backend-compliance/compliance/tests/test_audit_report.py
T
Benjamin Admin d720db07dd feat(audit-report): deterministischer Textreport je Audit (MD + PDF) + Bericht-Tab
Firmen-tauglicher Bericht aus den Snapshot-Modulergebnissen (kein Re-Crawl, kein
LLM): Einleitung, Testumfang+Methodik, Management-Summary (4-Status), Detail-
befunde je Modul, Maßnahmen, Rechtlicher Hinweis. Co-Pilot-Tonalität, Tracking-
statt Cookie-Rohzahl, Norm nur referenziert (kein Normtext).
- audit_report.py: assemble_report (pur) + render_markdown + render_pdf (reportlab)
- snapshot_check_routes: GET /report (struktur+md) + GET /report.pdf
- Frontend: AuditReportTab + Proxys (report, report/pdf) + "Bericht"-Tab
- Tests: 5 Assembler (compliance/tests → CI-geprüft) + 1 Vitest

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-13 14:50:45 +02:00

66 lines
2.8 KiB
Python

"""Audit-Report-Assembler (pur) — Sektionen, 4-Status-/Severity-Zählung,
Co-Pilot-Tonalität, kein Normtext."""
from compliance.services.audit_report import assemble_report, render_markdown
META = {"site_label": "BMW", "site_domain": "bmw.de",
"created_at": "2026-06-11T14:15:00", "check_id": "508983ec"}
MODULES = {
"cookie": {"findings": [
{"title": "Cookie als notwendig deklariert, real Marketing",
"severity": "HIGH", "legal_ref": "§ 25 TDDDG",
"measure": "Als einwilligungspflichtig (§ 25) einstufen."},
{"title": "Laufzeit überschreitet Empfehlung", "severity": "LOW"},
]},
"impressum": {"findings": [
{"title": "Vertretungsberechtigte fehlen", "severity": "MEDIUM",
"status": "APPLICABLE", "recommendation": "Vertretungsberechtigte ergänzen."},
], "status": "APPLICABLE", "confidence": 0.8},
"browser": {"cross_findings": [
{"title": "Tracking vor der Einwilligung — in allen Browsern",
"severity": "HIGH", "detail": "Chrome + Firefox setzen Tracker vor Consent",
"measure": "Tracking-Skripte erst nach aktiver Einwilligung laden."},
]},
}
def test_sections_present():
r = assemble_report(META, MODULES)
titles = [s["title"] for s in r["sections"]]
for t in ["Einleitung", "Testumfang & Methodik", "Management-Summary",
"Detailbefunde", "Empfohlene Maßnahmen", "Rechtlicher Hinweis"]:
assert t in titles, f"Sektion fehlt: {t}"
def test_severity_counts():
r = assemble_report(META, MODULES)
c = r["totals"]["by_severity"]
assert c["HIGH"] == 2 and c["MEDIUM"] == 1 and c["LOW"] == 1
assert r["totals"]["findings"] == 4
def test_markdown_has_header_findings_and_copilot_disclaimer():
md = render_markdown(assemble_report(META, MODULES))
assert "Compliance-Audit-Bericht — BMW" in md
assert "Tracking vor der Einwilligung" in md # Browser-Cross-Finding
assert "Vertretungsberechtigte ergänzen" in md # Maßnahme aus recommendation
assert "DSB" in md and "Anwalt" in md # Co-Pilot-Disclaimer
assert "Wahrscheinlichkeit" in md # keine Garantie
assert "BreakPilot" in md
def test_empty_modules_graceful():
r = assemble_report({"site_domain": "example.com"}, {})
assert r["totals"]["findings"] == 0
md = render_markdown(r)
assert "keine wesentlichen auffälligkeiten" in md.lower()
# Auch ohne Befunde: Disclaimer + Methodik vorhanden.
assert "Rechtlicher Hinweis" in md
def test_essential_cookie_framing_in_methodik():
# Tonalität/Recht: technisch notwendige Cookies ausgenommen (§ 25 Abs. 2).
md = render_markdown(assemble_report(META, MODULES))
assert "§ 25 Abs. 2" in md
assert "nicht-essentielle" in md.lower()