erster versuch der KI mit Plan
This commit is contained in:
1 parent
c697c64f3a
commit
2faa1689dd
20 files changed
+1749
No files matched your search
@@ -0,0 +1,155 @@
|
||||
"""Tests for src/validators.py — pre-generation validation logic."""
|
||||
|
||||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from src.validators import validate
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Helpers
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def _write_config(tmp_path: Path, overrides: dict = None) -> Path:
|
||||
"""Write a valid config.json into tmp_path, optionally applying overrides."""
|
||||
cfg = {
|
||||
"antragsnummer": "12345",
|
||||
"ort": "Teststadt",
|
||||
"template_pdf": "template/sab.pdf",
|
||||
"output_dir": "output",
|
||||
"excel_year_pattern": "(19\\d{2}|20\\d{2})",
|
||||
"excel_name_header": "Name, Vorname",
|
||||
"excel_name_column": 1,
|
||||
"excel_seq_column": 0,
|
||||
"excel_day_start_col": 9,
|
||||
"excel_day_end_col": 39,
|
||||
"month_mapping": {"Feb": "02", "Jan": "01"},
|
||||
"valid_status_codes": ["K", "KK", "E", "F", "P", "U"],
|
||||
"plan_hours_value": "6",
|
||||
"pauschale_value": "8,60",
|
||||
}
|
||||
if overrides:
|
||||
cfg.update(overrides)
|
||||
cfg_path = tmp_path / "config.json"
|
||||
cfg_path.write_text(json.dumps(cfg), encoding="utf-8")
|
||||
return cfg_path
|
||||
|
||||
|
||||
def _write_dummy_xlsx(tmp_path: Path, name: str = "Anwesenheit_2026.xlsx") -> Path:
|
||||
"""Create a minimal valid xlsx file using openpyxl."""
|
||||
import openpyxl
|
||||
wb = openpyxl.Workbook()
|
||||
ws = wb.active
|
||||
ws.title = "Feb"
|
||||
# Header row
|
||||
ws.cell(row=1, column=2, value="Name, Vorname")
|
||||
# Day headers (columns J–AN = col 10–40 in 1-based)
|
||||
for col in range(10, 41):
|
||||
ws.cell(row=1, column=col, value=col - 9) # day number as header
|
||||
# Person row
|
||||
ws.cell(row=2, column=1, value=1)
|
||||
ws.cell(row=2, column=2, value="Mustermann, Max")
|
||||
ws.cell(row=2, column=10, value=6.0) # day 1 → present 6h
|
||||
xlsx_path = tmp_path / name
|
||||
wb.save(str(xlsx_path))
|
||||
return xlsx_path
|
||||
|
||||
|
||||
def _write_dummy_pdf(tmp_path: Path) -> Path:
|
||||
"""Create a 1-byte placeholder file that passes existence checks."""
|
||||
pdf_path = tmp_path / "template" / "sab.pdf"
|
||||
pdf_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
pdf_path.write_bytes(b"%PDF-1.4 placeholder")
|
||||
return pdf_path
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Tests
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class TestValidate:
|
||||
def test_all_checks_pass(self, tmp_path):
|
||||
cfg_path = _write_config(tmp_path)
|
||||
xlsx_path = _write_dummy_xlsx(tmp_path)
|
||||
_write_dummy_pdf(tmp_path)
|
||||
|
||||
# Reset config cache so the test config is used
|
||||
from src.config_loader import reset_config_cache
|
||||
reset_config_cache()
|
||||
|
||||
errors = validate(xlsx_path, "Feb", cfg_path)
|
||||
assert errors == []
|
||||
|
||||
def test_excel_file_missing(self, tmp_path):
|
||||
cfg_path = _write_config(tmp_path)
|
||||
_write_dummy_pdf(tmp_path)
|
||||
|
||||
from src.config_loader import reset_config_cache
|
||||
reset_config_cache()
|
||||
|
||||
errors = validate(tmp_path / "nonexistent.xlsx", "Feb", cfg_path)
|
||||
assert any("nicht gefunden" in e for e in errors)
|
||||
|
||||
def test_year_not_in_filename(self, tmp_path):
|
||||
cfg_path = _write_config(tmp_path)
|
||||
xlsx_path = _write_dummy_xlsx(tmp_path, name="Anwesenheit_kein_jahr.xlsx")
|
||||
_write_dummy_pdf(tmp_path)
|
||||
|
||||
from src.config_loader import reset_config_cache
|
||||
reset_config_cache()
|
||||
|
||||
errors = validate(xlsx_path, "Feb", cfg_path)
|
||||
assert any("Jahr" in e for e in errors)
|
||||
|
||||
def test_unknown_sheet_name(self, tmp_path):
|
||||
cfg_path = _write_config(tmp_path)
|
||||
xlsx_path = _write_dummy_xlsx(tmp_path)
|
||||
_write_dummy_pdf(tmp_path)
|
||||
|
||||
from src.config_loader import reset_config_cache
|
||||
reset_config_cache()
|
||||
|
||||
errors = validate(xlsx_path, "Xyz", cfg_path)
|
||||
assert any("month_mapping" in e or "Sheet" in e for e in errors)
|
||||
|
||||
def test_pdf_template_missing(self, tmp_path):
|
||||
# No _write_dummy_pdf call → template missing
|
||||
cfg_path = _write_config(tmp_path)
|
||||
xlsx_path = _write_dummy_xlsx(tmp_path)
|
||||
|
||||
from src.config_loader import reset_config_cache
|
||||
reset_config_cache()
|
||||
|
||||
errors = validate(xlsx_path, "Feb", cfg_path)
|
||||
assert any("Template" in e or "template" in e.lower() for e in errors)
|
||||
|
||||
def test_config_missing_key(self, tmp_path):
|
||||
cfg = {
|
||||
"antragsnummer": "123",
|
||||
# omit 'ort' and other required keys
|
||||
}
|
||||
cfg_path = tmp_path / "config.json"
|
||||
cfg_path.write_text(json.dumps(cfg), encoding="utf-8")
|
||||
|
||||
from src.config_loader import reset_config_cache
|
||||
reset_config_cache()
|
||||
|
||||
errors = validate(tmp_path / "file.xlsx", "Feb", cfg_path)
|
||||
assert any("Konfigurationsfehler" in e or "fehlen" in e.lower() for e in errors)
|
||||
|
||||
def test_non_xlsx_extension_flagged(self, tmp_path):
|
||||
cfg_path = _write_config(tmp_path)
|
||||
_write_dummy_pdf(tmp_path)
|
||||
|
||||
csv_path = tmp_path / "Anwesenheit_2026.csv"
|
||||
csv_path.write_text("dummy")
|
||||
|
||||
from src.config_loader import reset_config_cache
|
||||
reset_config_cache()
|
||||
|
||||
errors = validate(csv_path, "Feb", cfg_path)
|
||||
assert any(".xlsx" in e or "Excel" in e for e in errors)
|
||||
Reference in new issue
Block a user