Anpassung an den Wrappern für sn_plan41

This commit is contained in:
2026-01-08 17:13:51 +01:00
parent f88b5da51f
commit b805f78f02
26 changed files with 401 additions and 125 deletions

1
tests/__init__.py Normal file
View File

@@ -0,0 +1 @@
#Testordner

154
tests/run_tests.py Normal file
View File

@@ -0,0 +1,154 @@
"""
sn_basis/test/run_tests.py
Zentraler Test-Runner für sn_basis.
Wrapper-konform, QGIS-unabhängig, CI- und IDE-fähig.
"""
import unittest
import datetime
import inspect
import os
import sys
from pathlib import Path
# ---------------------------------------------------------
# Pre-Bootstrap: Plugin-Root in sys.path eintragen
# ---------------------------------------------------------
THIS_FILE = Path(__file__).resolve()
PLUGIN_ROOT = THIS_FILE.parents[2]
if str(PLUGIN_ROOT) not in sys.path:
sys.path.insert(0, str(PLUGIN_ROOT))
from sn_basis.functions import (
get_plugin_root,
add_to_sys_path,
)
# ---------------------------------------------------------
# Bootstrap: Plugin-Root in sys.path eintragen
# ---------------------------------------------------------
def bootstrap():
"""
Simuliert das QGIS-Plugin-Startverhalten:
stellt sicher, dass sn_basis importierbar ist.
"""
plugin_root = get_plugin_root()
add_to_sys_path(plugin_root)
bootstrap()
# ---------------------------------------------------------
# Farben
# ---------------------------------------------------------
RED = "\033[91m"
YELLOW = "\033[93m"
GREEN = "\033[92m"
CYAN = "\033[96m"
MAGENTA = "\033[95m"
RESET = "\033[0m"
GLOBAL_TEST_COUNTER = 0
# ---------------------------------------------------------
# Farbige TestResult-Klasse
# ---------------------------------------------------------
class ColoredTestResult(unittest.TextTestResult):
_last_test_class: type | None = None
def startTest(self, test):
global GLOBAL_TEST_COUNTER
GLOBAL_TEST_COUNTER += 1
self.stream.write(f"{CYAN}[Test {GLOBAL_TEST_COUNTER}]{RESET}\n")
super().startTest(test)
def startTestClass(self, test):
cls = test.__class__
file = inspect.getfile(cls)
filename = os.path.basename(file)
self.stream.write(
f"\n{MAGENTA}{'=' * 70}\n"
f"Starte Testklasse: {filename}{cls.__name__}\n"
f"{'=' * 70}{RESET}\n"
)
def addError(self, test, err):
super().addError(test, err)
self.stream.write(f"{RED}ERROR{RESET}\n")
def addFailure(self, test, err):
super().addFailure(test, err)
self.stream.write(f"{RED}FAILURE{RESET}\n")
def addSkip(self, test, reason):
super().addSkip(test, reason)
self.stream.write(f"{YELLOW}SKIPPED{RESET}: {reason}\n")
def addSuccess(self, test):
super().addSuccess(test)
self.stream.write(f"{GREEN}OK{RESET}\n")
# ---------------------------------------------------------
# Farbiger TestRunner
# ---------------------------------------------------------
class ColoredTestRunner(unittest.TextTestRunner):
def _makeResult(self):
result = ColoredTestResult(
self.stream,
self.descriptions,
self.verbosity,
)
original_start_test = result.startTest
def patched_start_test(test):
if not hasattr(result, "_last_test_class") or \
result._last_test_class != test.__class__:
result.startTestClass(test)
result._last_test_class = test.__class__
original_start_test(test)
result.startTest = patched_start_test
return result
# ---------------------------------------------------------
# Testlauf starten
# ---------------------------------------------------------
def main():
print("\n" + "=" * 70)
print(
f"{CYAN}Testlauf gestartet am: "
f"{datetime.datetime.now():%Y-%m-%d %H:%M:%S}{RESET}"
)
print("=" * 70 + "\n")
loader = unittest.TestLoader()
suite = loader.discover(
start_dir=os.path.dirname(__file__),
pattern="test_*.py"
)
runner = ColoredTestRunner(verbosity=2)
result = runner.run(suite)
# Exit-Code für CI / Skripte
return 0 if result.wasSuccessful() else 1
if __name__ == "__main__":
raise SystemExit(main())

View File

@@ -0,0 +1,9 @@
@echo off
SET OSGEO4W_ROOT=D:\QGISQT5
call %OSGEO4W_ROOT%\bin\o4w_env.bat
set QGIS_PREFIX_PATH=%OSGEO4W_ROOT%\apps\qgis
set PYTHONPATH=%QGIS_PREFIX_PATH%\python;%PYTHONPATH%
set PATH=%OSGEO4W_ROOT%\bin;%QGIS_PREFIX_PATH%\bin;%PATH%
REM Neue Eingabeaufforderung starten und Python-Skript ausführen
start cmd /k "python run_tests.py"

2
tests/test_bootstrap.py Normal file
View File

@@ -0,0 +1,2 @@
from sn_basis.functions import sys_wrapper
sys_wrapper.add_to_sys_path(sys_wrapper.get_plugin_root())

104
tests/test_dateipruefer.py Normal file
View File

@@ -0,0 +1,104 @@
# sn_basis/test/test_dateipruefer.py
import unittest
from pathlib import Path
from unittest.mock import patch
from sn_basis.modules.Dateipruefer import Dateipruefer
class TestDateipruefer(unittest.TestCase):
# -----------------------------------------------------
# 1. Leere Eingabe erlaubt
# -----------------------------------------------------
def test_leereingabe_erlaubt(self):
pruefer = Dateipruefer(
pfad="",
leereingabe_erlaubt=True
)
result = pruefer.pruefe()
self.assertFalse(result.ok)
self.assertEqual(result.aktion, "leereingabe_erlaubt")
self.assertIsNone(result.kontext)
# -----------------------------------------------------
# 2. Leere Eingabe nicht erlaubt
# -----------------------------------------------------
def test_leereingabe_nicht_erlaubt(self):
pruefer = Dateipruefer(
pfad="",
leereingabe_erlaubt=False
)
result = pruefer.pruefe()
self.assertFalse(result.ok)
self.assertEqual(result.aktion, "leereingabe_nicht_erlaubt")
self.assertIsNone(result.kontext)
# -----------------------------------------------------
# 3. Standarddatei vorschlagen
# -----------------------------------------------------
def test_standarddatei_vorschlagen(self):
pruefer = Dateipruefer(
pfad="",
standarddatei="/tmp/std.txt"
)
result = pruefer.pruefe()
self.assertFalse(result.ok)
self.assertEqual(result.aktion, "standarddatei_vorschlagen")
self.assertEqual(result.kontext, Path("/tmp/std.txt"))
# -----------------------------------------------------
# 4. Temporäre Datei erlaubt
# -----------------------------------------------------
def test_temporaer_erlaubt(self):
pruefer = Dateipruefer(
pfad="",
temporaer_erlaubt=True
)
result = pruefer.pruefe()
self.assertFalse(result.ok)
self.assertEqual(result.aktion, "temporaer_erlaubt")
self.assertIsNone(result.kontext)
# -----------------------------------------------------
# 5. Datei existiert nicht
# -----------------------------------------------------
@patch("sn_basis.modules.Dateipruefer.file_exists", return_value=False)
def test_datei_nicht_gefunden(self, mock_exists):
pruefer = Dateipruefer(
pfad="/tmp/nichtvorhanden.txt"
)
result = pruefer.pruefe()
self.assertFalse(result.ok)
self.assertEqual(result.aktion, "datei_nicht_gefunden")
self.assertEqual(result.kontext, Path("/tmp/nichtvorhanden.txt"))
# -----------------------------------------------------
# 6. Datei existiert
# -----------------------------------------------------
@patch("sn_basis.modules.Dateipruefer.file_exists", return_value=True)
def test_datei_ok(self, mock_exists):
pruefer = Dateipruefer(
pfad="/tmp/test.txt"
)
result = pruefer.pruefe()
self.assertTrue(result.ok)
self.assertEqual(result.aktion, "ok")
self.assertEqual(result.kontext, Path("/tmp/test.txt"))
if __name__ == "__main__":
unittest.main()

171
tests/test_layerpruefer.py Normal file
View File

@@ -0,0 +1,171 @@
# sn_basis/test/test_layerpruefer.py
import unittest
from sn_basis.modules.layerpruefer import Layerpruefer
from sn_basis.modules.pruef_ergebnis import pruef_ergebnis
# ---------------------------------------------------------
# Mock-Layer für Wrapper-Tests
# ---------------------------------------------------------
class MockLayer:
def __init__(
self,
exists=True,
visible=True,
layer_type="vector",
geometry_type="Polygon",
feature_count=10,
crs="EPSG:25833",
fields=None,
source="/tmp/test.shp",
editable=True,
):
self.exists = exists
self.visible = visible
self.layer_type = layer_type
self.geometry_type = geometry_type
self.feature_count = feature_count
self.crs = crs
self.fields = fields or []
self.source = source
self.editable = editable
# ---------------------------------------------------------
# Wrapper-Mocks (monkeypatching)
# ---------------------------------------------------------
def mock_layer_exists(layer):
return layer is not None and layer.exists
def mock_is_layer_visible(layer):
return layer.visible
def mock_get_layer_type(layer):
return layer.layer_type
def mock_get_layer_geometry_type(layer):
return layer.geometry_type
def mock_get_layer_feature_count(layer):
return layer.feature_count
def mock_get_layer_crs(layer):
return layer.crs
def mock_get_layer_fields(layer):
return layer.fields
def mock_get_layer_source(layer):
return layer.source
def mock_is_layer_editable(layer):
return layer.editable
# ---------------------------------------------------------
# Testklasse
# ---------------------------------------------------------
class TestLayerpruefer(unittest.TestCase):
def setUp(self):
# Monkeypatching der im Layerpruefer verwendeten Wrapper-Funktionen
import sn_basis.modules.layerpruefer as module
module.layer_exists = mock_layer_exists
module.is_layer_visible = mock_is_layer_visible
module.get_layer_type = mock_get_layer_type
module.get_layer_geometry_type = mock_get_layer_geometry_type
module.get_layer_feature_count = mock_get_layer_feature_count
module.get_layer_crs = mock_get_layer_crs
module.get_layer_fields = mock_get_layer_fields
module.get_layer_source = mock_get_layer_source
module.is_layer_editable = mock_is_layer_editable
# -----------------------------------------------------
# Tests
# -----------------------------------------------------
def test_layer_exists(self):
layer = MockLayer(exists=False)
pruefer = Layerpruefer(layer)
ergebnis = pruefer.pruefe()
self.assertFalse(ergebnis.ok)
self.assertEqual(ergebnis.aktion, "layer_nicht_gefunden")
def test_layer_unsichtbar(self):
layer = MockLayer(visible=False)
pruefer = Layerpruefer(layer, muss_sichtbar_sein=True)
ergebnis = pruefer.pruefe()
self.assertFalse(ergebnis.ok)
self.assertEqual(ergebnis.aktion, "layer_unsichtbar")
def test_falscher_layertyp(self):
layer = MockLayer(layer_type="raster")
pruefer = Layerpruefer(layer, erwarteter_layertyp="vector")
ergebnis = pruefer.pruefe()
self.assertFalse(ergebnis.ok)
self.assertEqual(ergebnis.aktion, "falscher_layertyp")
def test_falscher_geotyp(self):
layer = MockLayer(geometry_type="Point")
pruefer = Layerpruefer(layer, erwarteter_geotyp="Polygon")
ergebnis = pruefer.pruefe()
self.assertFalse(ergebnis.ok)
self.assertEqual(ergebnis.aktion, "falscher_geotyp")
def test_layer_leer(self):
layer = MockLayer(feature_count=0)
pruefer = Layerpruefer(layer)
ergebnis = pruefer.pruefe()
self.assertFalse(ergebnis.ok)
self.assertEqual(ergebnis.aktion, "layer_leer")
def test_falsches_crs(self):
layer = MockLayer(crs="EPSG:4326")
pruefer = Layerpruefer(layer, erwartetes_crs="EPSG:25833")
ergebnis = pruefer.pruefe()
self.assertFalse(ergebnis.ok)
self.assertEqual(ergebnis.aktion, "falsches_crs")
def test_felder_fehlen(self):
layer = MockLayer(fields=["id"])
pruefer = Layerpruefer(layer, erforderliche_felder=["id", "name"])
ergebnis = pruefer.pruefe()
self.assertFalse(ergebnis.ok)
self.assertEqual(ergebnis.aktion, "felder_fehlen")
def test_datenquelle_unerwartet(self):
layer = MockLayer(source="/tmp/test.shp")
pruefer = Layerpruefer(layer, erlaubte_datenquellen=["/tmp/allowed.shp"])
ergebnis = pruefer.pruefe()
self.assertFalse(ergebnis.ok)
self.assertEqual(ergebnis.aktion, "datenquelle_unerwartet")
def test_layer_nicht_editierbar(self):
layer = MockLayer(editable=False)
pruefer = Layerpruefer(layer, muss_editierbar_sein=True)
ergebnis = pruefer.pruefe()
self.assertFalse(ergebnis.ok)
self.assertEqual(ergebnis.aktion, "layer_nicht_editierbar")
def test_layer_ok(self):
layer = MockLayer()
pruefer = Layerpruefer(layer)
ergebnis = pruefer.pruefe()
self.assertTrue(ergebnis.ok)
self.assertEqual(ergebnis.aktion, "ok")
if __name__ == "__main__":
unittest.main()

79
tests/test_linkpruefer.py Normal file
View File

@@ -0,0 +1,79 @@
# sn_basis/test/test_linkpruefer.py
import unittest
from pathlib import Path
from unittest.mock import patch
from sn_basis.modules.linkpruefer import Linkpruefer
from sn_basis.functions.qgiscore_wrapper import NetworkReply
class TestLinkpruefer(unittest.TestCase):
# -----------------------------------------------------
# 1. Remote-Link erreichbar
# -----------------------------------------------------
@patch("sn_basis.modules.linkpruefer.network_head")
def test_remote_link_ok(self, mock_head):
mock_head.return_value = NetworkReply(error=0)
lp = Linkpruefer()
result = lp.pruefe("http://example.com")
self.assertTrue(result.ok)
self.assertEqual(result.aktion, "ok")
self.assertEqual(result.kontext, "http://example.com")
# -----------------------------------------------------
# 2. Remote-Link nicht erreichbar
# -----------------------------------------------------
@patch("sn_basis.modules.linkpruefer.network_head")
def test_remote_link_error(self, mock_head):
mock_head.return_value = NetworkReply(error=1)
lp = Linkpruefer()
result = lp.pruefe("http://example.com")
self.assertFalse(result.ok)
self.assertEqual(result.aktion, "url_nicht_erreichbar")
self.assertEqual(result.kontext, "http://example.com")
# -----------------------------------------------------
# 3. Netzwerkfehler (None)
# -----------------------------------------------------
@patch("sn_basis.modules.linkpruefer.network_head", return_value=None)
def test_remote_link_network_error(self, mock_head):
lp = Linkpruefer()
result = lp.pruefe("http://example.com")
self.assertFalse(result.ok)
self.assertEqual(result.aktion, "netzwerkfehler")
self.assertEqual(result.kontext, "http://example.com")
# -----------------------------------------------------
# 4. Lokaler Pfad existiert nicht
# -----------------------------------------------------
@patch("sn_basis.modules.linkpruefer.file_exists", return_value=False)
def test_local_link_not_found(self, mock_exists):
lp = Linkpruefer()
result = lp.pruefe("/path/to/missing/file.shp")
self.assertFalse(result.ok)
self.assertEqual(result.aktion, "pfad_nicht_gefunden")
self.assertEqual(result.kontext, Path("/path/to/missing/file.shp"))
# -----------------------------------------------------
# 5. Lokaler Pfad existiert
# -----------------------------------------------------
@patch("sn_basis.modules.linkpruefer.file_exists", return_value=True)
def test_local_link_ok(self, mock_exists):
lp = Linkpruefer()
result = lp.pruefe("/path/to/file.shp")
self.assertTrue(result.ok)
self.assertEqual(result.aktion, "ok")
self.assertEqual(result.kontext, Path("/path/to/file.shp"))
if __name__ == "__main__":
unittest.main()

146
tests/test_pruefmanager.py Normal file
View File

@@ -0,0 +1,146 @@
# sn_basis/test/test_pruefmanager.py
import unittest
from unittest.mock import patch
from sn_basis.modules.Pruefmanager import Pruefmanager
from sn_basis.modules.pruef_ergebnis import pruef_ergebnis
class TestPruefmanager(unittest.TestCase):
def setUp(self):
self.manager = Pruefmanager()
# -----------------------------------------------------
# 1. OK-Ergebnis → keine Interaktion
# -----------------------------------------------------
def test_ok(self):
ergebnis = pruef_ergebnis(True, "Alles gut", "ok", None)
entscheidung = self.manager.verarbeite(ergebnis)
self.assertTrue(entscheidung.ok)
self.assertEqual(entscheidung.aktion, "ok")
# -----------------------------------------------------
# 2. Leere Eingabe erlaubt → Nutzer sagt JA
# -----------------------------------------------------
@patch("sn_basis.modules.Pruefmanager.ask_yes_no", return_value=True)
def test_leereingabe_erlaubt_ja(self, mock_ask):
ergebnis = pruef_ergebnis(False, "Leer?", "leereingabe_erlaubt", None)
entscheidung = self.manager.verarbeite(ergebnis)
self.assertTrue(entscheidung.ok)
self.assertEqual(entscheidung.aktion, "ok")
# -----------------------------------------------------
# 3. Leere Eingabe erlaubt → Nutzer sagt NEIN
# -----------------------------------------------------
@patch("sn_basis.modules.Pruefmanager.ask_yes_no", return_value=False)
def test_leereingabe_erlaubt_nein(self, mock_ask):
ergebnis = pruef_ergebnis(False, "Leer?", "leereingabe_erlaubt", None)
entscheidung = self.manager.verarbeite(ergebnis)
self.assertFalse(entscheidung.ok)
self.assertEqual(entscheidung.aktion, "leereingabe_erlaubt")
# -----------------------------------------------------
# 4. Standarddatei vorschlagen → Nutzer sagt JA
# -----------------------------------------------------
@patch("sn_basis.modules.Pruefmanager.ask_yes_no", return_value=True)
def test_standarddatei_vorschlagen_ja(self, mock_ask):
ergebnis = pruef_ergebnis(
False,
"Standarddatei verwenden?",
"standarddatei_vorschlagen",
"/tmp/std.txt",
)
entscheidung = self.manager.verarbeite(ergebnis)
self.assertTrue(entscheidung.ok)
self.assertEqual(entscheidung.aktion, "ok")
self.assertEqual(entscheidung.kontext, "/tmp/std.txt")
# -----------------------------------------------------
# 5. Standarddatei vorschlagen → Nutzer sagt NEIN
# -----------------------------------------------------
@patch("sn_basis.modules.Pruefmanager.ask_yes_no", return_value=False)
def test_standarddatei_vorschlagen_nein(self, mock_ask):
ergebnis = pruef_ergebnis(
False,
"Standarddatei verwenden?",
"standarddatei_vorschlagen",
"/tmp/std.txt",
)
entscheidung = self.manager.verarbeite(ergebnis)
self.assertFalse(entscheidung.ok)
self.assertEqual(entscheidung.aktion, "standarddatei_vorschlagen")
# -----------------------------------------------------
# 6. Temporäre Datei erzeugen → Nutzer sagt JA
# -----------------------------------------------------
@patch("sn_basis.modules.Pruefmanager.ask_yes_no", return_value=True)
def test_temporaer_erlaubt_ja(self, mock_ask):
ergebnis = pruef_ergebnis(False, "Temporär?", "temporaer_erlaubt", None)
entscheidung = self.manager.verarbeite(ergebnis)
self.assertTrue(entscheidung.ok)
self.assertEqual(entscheidung.aktion, "temporaer_erzeugen")
# -----------------------------------------------------
# 7. Temporäre Datei erzeugen → Nutzer sagt NEIN
# -----------------------------------------------------
@patch("sn_basis.modules.Pruefmanager.ask_yes_no", return_value=False)
def test_temporaer_erlaubt_nein(self, mock_ask):
ergebnis = pruef_ergebnis(False, "Temporär?", "temporaer_erlaubt", None)
entscheidung = self.manager.verarbeite(ergebnis)
self.assertFalse(entscheidung.ok)
self.assertEqual(entscheidung.aktion, "temporaer_erlaubt")
# -----------------------------------------------------
# 8. Layer unsichtbar → Nutzer sagt JA
# -----------------------------------------------------
@patch("sn_basis.modules.Pruefmanager.ask_yes_no", return_value=True)
@patch("sn_basis.modules.Pruefmanager.set_layer_visible")
def test_layer_unsichtbar_ja(self, mock_set, mock_ask):
fake_layer = object()
ergebnis = pruef_ergebnis(False, "Layer unsichtbar", "layer_unsichtbar", fake_layer)
entscheidung = self.manager.verarbeite(ergebnis)
mock_set.assert_called_once_with(fake_layer, True)
self.assertTrue(entscheidung.ok)
self.assertEqual(entscheidung.aktion, "ok")
# -----------------------------------------------------
# 9. Layer unsichtbar → Nutzer sagt NEIN
# -----------------------------------------------------
@patch("sn_basis.modules.Pruefmanager.ask_yes_no", return_value=False)
def test_layer_unsichtbar_nein(self, mock_ask):
fake_layer = object()
ergebnis = pruef_ergebnis(False, "Layer unsichtbar", "layer_unsichtbar", fake_layer)
entscheidung = self.manager.verarbeite(ergebnis)
self.assertFalse(entscheidung.ok)
self.assertEqual(entscheidung.aktion, "layer_unsichtbar")
# -----------------------------------------------------
# 10. Fehlerhafte Aktion → Fallback
# -----------------------------------------------------
@patch("sn_basis.modules.Pruefmanager.warning")
def test_unbekannte_aktion(self, mock_warn):
ergebnis = pruef_ergebnis(False, "???", "unbekannt", None)
entscheidung = self.manager.verarbeite(ergebnis)
mock_warn.assert_called_once()
self.assertFalse(entscheidung.ok)
self.assertEqual(entscheidung.aktion, "unbekannt")
if __name__ == "__main__":
unittest.main()

52
tests/test_qgis.bat Normal file
View File

@@ -0,0 +1,52 @@
@echo off
setlocal
echo BATCH WIRD AUSGEFÜHRT
pause
echo ================================================
echo Starte Tests in QGIS-Python-Umgebung
echo ================================================
REM Pfad zur QGIS-Installation
set QGIS_BIN=D:\OSGeo\bin
REM Prüfen, ob python-qgis.bat existiert
if not exist "%QGIS_BIN%\python-qgis.bat" (
echo.
echo [FEHLER] python-qgis.bat wurde nicht gefunden!
echo Erwarteter Pfad:
echo %QGIS_BIN%\python-qgis.bat
echo.
echo Bitte korrigiere den Pfad in test_qgis.bat.
echo.
pause
exit /b 1
)
echo.
echo [INFO] QGIS-Python gefunden. Starte Tests...
echo.
"%QGIS_BIN%\python-qgis.bat" -m coverage run run_tests.py
if errorlevel 1 (
echo.
echo [FEHLER] Testlauf fehlgeschlagen.
echo.
pause
exit /b 1
)
echo.
echo ================================================
echo Coverage HTML-Bericht wird erzeugt...
echo ================================================
"%QGIS_BIN%\python-qgis.bat" -m coverage html
echo.
echo Fertig!
echo Öffne jetzt: coverage_html\index.html
echo ================================================
pause
endlocal

View File

@@ -0,0 +1,60 @@
# sn_basis/test/test_settings_logic.py
import unittest
from unittest.mock import patch
from sn_basis.functions.settings_logic import SettingsLogic
class TestSettingsLogic(unittest.TestCase):
# -----------------------------------------------------
# Test: load() liest alle Variablen über get_variable()
# -----------------------------------------------------
@patch("sn_basis.functions.settings_logic.get_variable")
def test_load(self, mock_get):
# Mock-Rückgabe für jede Variable
mock_get.side_effect = lambda key, scope="project": f"wert_{key}"
logic = SettingsLogic()
daten = logic.load()
# Alle Variablen müssen enthalten sein
for key in SettingsLogic.VARIABLEN:
self.assertIn(key, daten)
self.assertEqual(daten[key], f"wert_{key}")
# get_variable muss für jede Variable genau einmal aufgerufen werden
self.assertEqual(mock_get.call_count, len(SettingsLogic.VARIABLEN))
# -----------------------------------------------------
# Test: save() ruft set_variable() nur für bekannte Keys auf
# -----------------------------------------------------
@patch("sn_basis.functions.settings_logic.set_variable")
def test_save(self, mock_set):
logic = SettingsLogic()
# Eingabedaten enthalten gültige und ungültige Keys
daten = {
"amt": "A1",
"behoerde": "B1",
"unbekannt": "IGNORIEREN",
"gemeinden": "G1",
}
logic.save(daten)
# set_variable muss nur für gültige Keys aufgerufen werden
expected_calls = 3 # amt, behoerde, gemeinden
self.assertEqual(mock_set.call_count, expected_calls)
# Prüfen, ob die richtigen Keys gespeichert wurden
saved_keys = [call.args[0] for call in mock_set.call_args_list]
self.assertIn("amt", saved_keys)
self.assertIn("behoerde", saved_keys)
self.assertIn("gemeinden", saved_keys)
self.assertNotIn("unbekannt", saved_keys)
if __name__ == "__main__":
unittest.main()

81
tests/test_stilpruefer.py Normal file
View File

@@ -0,0 +1,81 @@
# sn_basis/test/test_stilpruefer.py
import unittest
import tempfile
import os
from pathlib import Path
from unittest.mock import patch
from sn_basis.modules.stilpruefer import Stilpruefer
class TestStilpruefer(unittest.TestCase):
def setUp(self):
self.pruefer = Stilpruefer()
# -----------------------------------------------------
# 1. Keine Datei angegeben
# -----------------------------------------------------
def test_keine_datei_angegeben(self):
result = self.pruefer.pruefe("")
self.assertTrue(result.ok)
self.assertEqual(result.aktion, "ok")
self.assertIn("Kein Stil angegeben", result.meldung)
self.assertIsNone(result.kontext)
# -----------------------------------------------------
# 2. Datei existiert und ist .qml
# -----------------------------------------------------
@patch("sn_basis.modules.stilpruefer.file_exists", return_value=True)
def test_datei_existiert_mit_qml(self, mock_exists):
with tempfile.NamedTemporaryFile(suffix=".qml", delete=False) as tmp:
tmp_path = tmp.name
try:
result = self.pruefer.pruefe(tmp_path)
self.assertTrue(result.ok)
self.assertEqual(result.aktion, "stil_anwendbar")
self.assertEqual(result.kontext, Path(tmp_path))
finally:
os.remove(tmp_path)
# -----------------------------------------------------
# 3. Datei existiert, aber falsche Endung
# -----------------------------------------------------
@patch("sn_basis.modules.stilpruefer.file_exists", return_value=True)
def test_datei_existiert_falsche_endung(self, mock_exists):
with tempfile.NamedTemporaryFile(suffix=".txt", delete=False) as tmp:
tmp_path = tmp.name
try:
result = self.pruefer.pruefe(tmp_path)
self.assertFalse(result.ok)
self.assertEqual(result.aktion, "falsche_endung")
self.assertIn(".qml", result.meldung)
self.assertEqual(result.kontext, Path(tmp_path))
finally:
os.remove(tmp_path)
# -----------------------------------------------------
# 4. Datei existiert nicht
# -----------------------------------------------------
@patch("sn_basis.modules.stilpruefer.file_exists", return_value=False)
def test_datei_existiert_nicht(self, mock_exists):
fake_path = "/tmp/nichtvorhanden.qml"
result = self.pruefer.pruefe(fake_path)
self.assertFalse(result.ok)
self.assertEqual(result.aktion, "datei_nicht_gefunden")
self.assertIn("nicht gefunden", result.meldung)
self.assertEqual(result.kontext, Path(fake_path))
if __name__ == "__main__":
unittest.main()