Flst_Laden, VerfGebiet bilden

This commit is contained in:
2026-04-21 21:50:26 +02:00
parent 72c9d6fa15
commit 189855e63b
8 changed files with 2247 additions and 124 deletions
+223
View File
@@ -0,0 +1,223 @@
"""sn_verfahrensgebiet/tests/test_flurstueck_alkis.py
Unit-Tests für das flurstueck_alkis-Modul.
Getestet werden:
- Nutzerabbruch bei ask_text → (None, LoadStatus.NONE)
- Ungültiger WFS-Layer → (None, LoadStatus.NONE)
- Erfolgreicher Ladevorgang → gültiger Layer + LoadStatus.FIRST
- Bestehender Layer: Nutzer wählt "Neu laden" → LoadStatus.RELOAD
- Bestehender Layer: Nutzer wählt "Behalten" → LoadStatus.KEEP
"""
import sys
import types
import unittest
from unittest.mock import patch, MagicMock
# ---------------------------------------------------------------------------
# Minimales QGIS-Mock-Setup
# ---------------------------------------------------------------------------
if "qgis" not in sys.modules:
qgis_mod = types.ModuleType("qgis")
qgis_core = types.ModuleType("qgis.core")
qgis_utils = types.ModuleType("qgis.utils")
qgis_utils.iface = types.SimpleNamespace()
qgis_utils.plugins = {}
qgis_mod.utils = qgis_utils
qgis_mod.core = qgis_core
sys.modules["qgis"] = qgis_mod
sys.modules["qgis.core"] = qgis_core
sys.modules["qgis.utils"] = qgis_utils
from sn_verfahrensgebiet.functions.flurstueck_alkis import flurstueck_alkis, FLST_LAYER_NAME
from sn_verfahrensgebiet.functions.verfahrensgebiet_alkis import LoadStatus
# ---------------------------------------------------------------------------
# Dummies
# ---------------------------------------------------------------------------
class _DummyLayer:
def __init__(self, valid: bool, layer_id="L1"):
self._valid = valid
self._id = layer_id
def isValid(self):
return self._valid
def id(self):
return self._id
def extent(self):
return object()
class _DummyProject:
def __init__(self, named_layers=None):
self._named_layers = named_layers or []
self.removed = []
def mapLayersByName(self, name):
return self._named_layers
def removeMapLayer(self, lid):
self.removed.append(lid)
# ---------------------------------------------------------------------------
# Tests
# ---------------------------------------------------------------------------
class TestFlurstueckAlkis(unittest.TestCase):
# ------------------------------------------------------------------ #
# 1. Nutzerabbruch (ask_text liefert ok=False / None) #
# ------------------------------------------------------------------ #
@patch("sn_verfahrensgebiet.functions.flurstueck_alkis.QMessageBox")
@patch("sn_verfahrensgebiet.functions.flurstueck_alkis.QgsProject.instance")
@patch("sn_verfahrensgebiet.functions.flurstueck_alkis.ask_text")
def test_user_cancel_returns_none(self, mock_ask_text, mock_project, mock_msgbox):
"""ask_text → ok=False, text="" → (None, NONE)."""
mock_ask_text.return_value = ("", False)
mock_project.return_value = _DummyProject()
layer, status = flurstueck_alkis(None)
self.assertIsNone(layer)
self.assertEqual(status, LoadStatus.NONE)
@patch("sn_verfahrensgebiet.functions.flurstueck_alkis.QMessageBox")
@patch("sn_verfahrensgebiet.functions.flurstueck_alkis.QgsProject.instance")
@patch("sn_verfahrensgebiet.functions.flurstueck_alkis.ask_text")
def test_empty_text_after_confirmation_returns_none(self, mock_ask_text, mock_project, mock_msgbox):
"""ask_text → ok=True, aber Text leer → (None, NONE)."""
mock_ask_text.return_value = (" ", True)
mock_project.return_value = _DummyProject()
layer, status = flurstueck_alkis(None)
self.assertIsNone(layer)
self.assertEqual(status, LoadStatus.NONE)
# ------------------------------------------------------------------ #
# 2. Ungültiger WFS-Layer #
# ------------------------------------------------------------------ #
@patch("sn_verfahrensgebiet.functions.flurstueck_alkis.QMessageBox")
@patch("sn_verfahrensgebiet.functions.flurstueck_alkis.QgsVectorLayer")
@patch("sn_verfahrensgebiet.functions.flurstueck_alkis.QgsProject.instance")
@patch("sn_verfahrensgebiet.functions.flurstueck_alkis.ask_text")
def test_invalid_wfs_layer_returns_none(
self, mock_ask_text, mock_project, mock_wfs_layer_cls, mock_msgbox
):
"""WFS-Layer nicht valide → (None, NONE)."""
mock_ask_text.return_value = ("1234", True)
mock_project.return_value = _DummyProject()
mock_wfs_layer_cls.return_value = _DummyLayer(valid=False)
layer, status = flurstueck_alkis(None)
self.assertIsNone(layer)
self.assertEqual(status, LoadStatus.NONE)
# ------------------------------------------------------------------ #
# 3. Erfolgreicher Erstladevorgang #
# ------------------------------------------------------------------ #
@patch("sn_verfahrensgebiet.functions.flurstueck_alkis.QgsVectorLayer")
@patch("sn_verfahrensgebiet.functions.flurstueck_alkis.QgsProject.instance")
@patch("sn_verfahrensgebiet.functions.flurstueck_alkis.ask_text")
def test_success_returns_layer_and_first_status(
self, mock_ask_text, mock_project, mock_wfs_layer_cls
):
"""Kein bestehender Layer, WFS valide → (layer, FIRST)."""
mock_ask_text.return_value = ("1234, 5678", True)
mock_project.return_value = _DummyProject()
valid_layer = _DummyLayer(valid=True, layer_id="wfs_ok")
mock_wfs_layer_cls.return_value = valid_layer
layer, status = flurstueck_alkis(None)
self.assertIs(layer, valid_layer)
self.assertEqual(status, LoadStatus.FIRST)
@patch("sn_verfahrensgebiet.functions.flurstueck_alkis.QgsVectorLayer")
@patch("sn_verfahrensgebiet.functions.flurstueck_alkis.QgsProject.instance")
@patch("sn_verfahrensgebiet.functions.flurstueck_alkis.ask_text")
def test_sql_filter_contains_all_schluessel(
self, mock_ask_text, mock_project, mock_wfs_layer_cls
):
"""Der WFS-URI enthält alle eingegebenen Gemarkungsschlüssel."""
mock_ask_text.return_value = ("1111, 2222, 3333", True)
mock_project.return_value = _DummyProject()
mock_wfs_layer_cls.return_value = _DummyLayer(valid=True)
flurstueck_alkis(None)
# Erster Positionsarg von QgsVectorLayer ist der URI-String
call_args = mock_wfs_layer_cls.call_args
uri_str = call_args[0][0] if call_args[0] else call_args[1].get("path", "")
self.assertIn("1111", uri_str)
self.assertIn("2222", uri_str)
self.assertIn("3333", uri_str)
# ------------------------------------------------------------------ #
# 4. Bestehender Layer – Nutzer wählt "Neu laden" #
# ------------------------------------------------------------------ #
@patch("sn_verfahrensgebiet.functions.flurstueck_alkis.QgsVectorLayer")
@patch("sn_verfahrensgebiet.functions.flurstueck_alkis.QMessageBox")
@patch("sn_verfahrensgebiet.functions.flurstueck_alkis.QgsProject.instance")
@patch("sn_verfahrensgebiet.functions.flurstueck_alkis.ask_text")
def test_existing_layer_reload_yes(
self, mock_ask_text, mock_project, mock_msgbox_cls, mock_wfs_layer_cls
):
"""Bestehender Layer + Nutzer: 'Ja, neu laden' → LoadStatus.RELOAD."""
existing = _DummyLayer(valid=True, layer_id="old_flst")
project = _DummyProject(named_layers=[existing])
mock_ask_text.return_value = ("1234", True)
mock_project.return_value = project
# StandardButton als int, damit | Operator funktioniert
mock_msgbox_cls.StandardButton.Yes = 0x4000
mock_msgbox_cls.StandardButton.No = 0x10000
# QMessageBox.question → Yes
mock_msgbox_cls.question.return_value = 0x4000
new_layer = _DummyLayer(valid=True, layer_id="new_flst")
mock_wfs_layer_cls.return_value = new_layer
layer, status = flurstueck_alkis(None)
self.assertIn(existing.id(), project.removed)
self.assertIs(layer, new_layer)
self.assertEqual(status, LoadStatus.RELOAD)
# ------------------------------------------------------------------ #
# 5. Bestehender Layer – Nutzer wählt "Behalten" #
# ------------------------------------------------------------------ #
@patch("sn_verfahrensgebiet.functions.flurstueck_alkis.QMessageBox")
@patch("sn_verfahrensgebiet.functions.flurstueck_alkis.QgsProject.instance")
@patch("sn_verfahrensgebiet.functions.flurstueck_alkis.ask_text")
def test_existing_layer_keep_no(
self, mock_ask_text, mock_project, mock_msgbox_cls
):
"""Bestehender Layer + Nutzer: 'Nein, behalten' → LoadStatus.KEEP."""
existing = _DummyLayer(valid=True, layer_id="keep_flst")
project = _DummyProject(named_layers=[existing])
mock_ask_text.return_value = ("1234", True)
mock_project.return_value = project
# StandardButton als int, damit | Operator funktioniert
mock_msgbox_cls.StandardButton.Yes = 0x4000
mock_msgbox_cls.StandardButton.No = 0x10000
# QMessageBox.question → No
mock_msgbox_cls.question.return_value = 0x10000
layer, status = flurstueck_alkis(None)
self.assertIs(layer, existing)
self.assertEqual(status, LoadStatus.KEEP)
self.assertEqual(project.removed, []) # nichts gelöscht
if __name__ == "__main__":
unittest.main()