Files
Plugin_SN_Verfahrensgebiet/tests/test_verfahrensgebiet_alkis.py
T

244 lines
9.6 KiB
Python

import sys
import types
import unittest
from unittest.mock import patch
if "qgis" not in sys.modules:
qgis_mod = types.ModuleType("qgis")
qgis_utils = types.ModuleType("qgis.utils")
qgis_utils.iface = types.SimpleNamespace()
qgis_utils.plugins = {}
qgis_mod.utils = qgis_utils
sys.modules["qgis"] = qgis_mod
sys.modules["qgis.utils"] = qgis_utils
from sn_verfahrensgebiet.functions import verfahrensgebiet_alkis as vg
class _DummyMessageBox:
class StandardButton:
Yes = 1
No = 2
last_critical = None
next_reply = StandardButton.No
@staticmethod
def question(_parent, _title, _message, _buttons, _default):
return _DummyMessageBox.next_reply
@staticmethod
def critical(parent, title, message):
_DummyMessageBox.last_critical = (parent, title, message)
class _DummyProject:
def __init__(self, layers=None):
self._layers = layers or []
self.removed = []
def mapLayersByName(self, _name):
return self._layers
def removeMapLayer(self, layer_id):
self.removed.append(layer_id)
class _DummyExistingLayer:
def __init__(self, layer_id="existing"):
self._id = layer_id
def id(self):
return self._id
class _DummyGeom:
def __init__(self, empty=False):
self._empty = empty
def isEmpty(self):
return self._empty
class _DummyFeature:
def __init__(self, geom=None, attrs=None):
self._geom = geom or _DummyGeom()
self._attrs = attrs or {}
def geometry(self):
return self._geom
def attribute(self, name):
return self._attrs.get(name)
class _DummyTempLayer:
def __init__(self, valid=True, features=None):
self._valid = valid
self._features = features or []
def isValid(self):
return self._valid
def getFeatures(self):
return self._features
def crs(self):
class _Crs:
@staticmethod
def authid():
return "EPSG:25833"
return _Crs()
class _DummyProvider:
def addAttributes(self, _attrs):
return True
def addFeatures(self, _features):
return True
class _DummyMemoryLayer:
def __init__(self):
self._provider = _DummyProvider()
def dataProvider(self):
return self._provider
def updateFields(self):
return None
def updateExtents(self):
return None
class TestVerfahrensgebietAlkis(unittest.TestCase):
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QgsProject.instance")
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QMessageBox", new=_DummyMessageBox)
def test_check_existing_layer_first_load(self, mock_project_instance):
mock_project_instance.return_value = _DummyProject(layers=[])
layer, status = vg._check_existing_layer(tab_widget=None)
self.assertIsNone(layer)
self.assertEqual(status, vg.LoadStatus.FIRST)
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QgsProject.instance")
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QMessageBox", new=_DummyMessageBox)
def test_check_existing_layer_keep_existing(self, mock_project_instance):
existing = _DummyExistingLayer("L1")
mock_project_instance.return_value = _DummyProject(layers=[existing])
_DummyMessageBox.next_reply = _DummyMessageBox.StandardButton.No
layer, status = vg._check_existing_layer(tab_widget=None)
self.assertIs(layer, existing)
self.assertEqual(status, vg.LoadStatus.KEEP)
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QMessageBox", new=_DummyMessageBox)
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.get_variable", return_value="")
def test_verfahrensgebiet_alkis_fails_when_verfahrensnummer_missing(self, _mock_get_var):
_DummyMessageBox.last_critical = None
layer, status, feats = vg.verfahrensgebiet_alkis(tab_widget=None)
self.assertIsNone(layer)
self.assertEqual(status, vg.LoadStatus.NONE)
self.assertIsNotNone(_DummyMessageBox.last_critical)
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis._check_existing_layer", return_value=(None, vg.LoadStatus.FIRST))
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QMessageBox", new=_DummyMessageBox)
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.get_variable", return_value="VKZ123")
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QgsVectorLayer")
def test_verfahrensgebiet_alkis_fails_on_invalid_wfs_layer(self, mock_qgsvectorlayer, _mock_get_var, _mock_check):
_DummyMessageBox.last_critical = None
mock_qgsvectorlayer.return_value = _DummyTempLayer(valid=False)
layer, status, feats = vg.verfahrensgebiet_alkis(tab_widget=None)
self.assertIsNone(layer)
self.assertEqual(status, vg.LoadStatus.NONE)
self.assertIsNotNone(_DummyMessageBox.last_critical)
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QgsFeature")
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QgsGeometry.unaryUnion", return_value=_DummyGeom(empty=False))
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis._check_existing_layer", return_value=(None, vg.LoadStatus.FIRST))
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.get_variable", return_value="VKZ123")
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QgsVectorLayer")
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QMessageBox", new=_DummyMessageBox)
def test_verfahrensgebiet_alkis_success_single_kombination(self, mock_qgsvectorlayer, _mock_get_var, _mock_check, _mock_union, mock_feature_cls):
"""Einzelne (adv_name, bezeichnung)-Kombination → kein Dialog, Memory-Layer zurück."""
feat = _DummyFeature(attrs={"adv_name": "Bodensanierung", "bezeichnung": "VKZ12/001"})
temp_layer = _DummyTempLayer(valid=True, features=[feat])
memory_layer = _DummyMemoryLayer()
mock_qgsvectorlayer.side_effect = [temp_layer, memory_layer]
mock_feature = mock_feature_cls.return_value
mock_feature.setGeometry.return_value = None
mock_feature.setAttributes.return_value = None
layer, status, feats = vg.verfahrensgebiet_alkis(tab_widget=None)
self.assertIs(layer, memory_layer)
self.assertEqual(status, vg.LoadStatus.FIRST)
self.assertEqual(len(feats), 1)
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.ask_bror_kombination")
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QgsFeature")
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QgsGeometry.unaryUnion", return_value=_DummyGeom(empty=False))
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis._check_existing_layer", return_value=(None, vg.LoadStatus.FIRST))
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.get_variable", return_value="VKZ123")
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QgsVectorLayer")
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QMessageBox", new=_DummyMessageBox)
def test_verfahrensgebiet_alkis_multi_kombination_dialog_auswahl(
self, mock_qgsvectorlayer, _mock_get_var, _mock_check, _mock_union, mock_feature_cls, mock_dialog
):
"""Zwei verschiedene Kombinationen → Dialog wird gezeigt, gewählte Features genutzt."""
feat1 = _DummyFeature(attrs={"adv_name": "ADV-A", "bezeichnung": "VKZ12/001"})
feat2 = _DummyFeature(attrs={"adv_name": "ADV-B", "bezeichnung": "VKZ12/002"})
temp_layer = _DummyTempLayer(valid=True, features=[feat1, feat2])
memory_layer = _DummyMemoryLayer()
mock_qgsvectorlayer.side_effect = [temp_layer, memory_layer]
mock_dialog.return_value = ("ADV-A", "VKZ12/001")
mock_feature = mock_feature_cls.return_value
mock_feature.setGeometry.return_value = None
mock_feature.setAttributes.return_value = None
layer, status, feats = vg.verfahrensgebiet_alkis(tab_widget=None)
mock_dialog.assert_called_once()
self.assertIs(layer, memory_layer)
self.assertEqual(status, vg.LoadStatus.FIRST)
# Nur feat1 gehört zur gewählten Kombination
self.assertEqual(feats, [feat1])
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.ask_bror_kombination")
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis._check_existing_layer", return_value=(None, vg.LoadStatus.FIRST))
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.get_variable", return_value="VKZ123")
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QgsVectorLayer")
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QMessageBox", new=_DummyMessageBox)
def test_verfahrensgebiet_alkis_multi_kombination_dialog_abbruch(
self, mock_qgsvectorlayer, _mock_get_var, _mock_check, mock_dialog
):
"""Zwei verschiedene Kombinationen → Nutzer bricht Dialog ab → NONE."""
feat1 = _DummyFeature(attrs={"adv_name": "ADV-A", "bezeichnung": "VKZ12/001"})
feat2 = _DummyFeature(attrs={"adv_name": "ADV-B", "bezeichnung": "VKZ12/002"})
temp_layer = _DummyTempLayer(valid=True, features=[feat1, feat2])
mock_qgsvectorlayer.return_value = temp_layer
mock_dialog.return_value = None # Nutzer bricht ab
layer, status, feats = vg.verfahrensgebiet_alkis(tab_widget=None)
mock_dialog.assert_called_once()
self.assertIsNone(layer)
self.assertEqual(status, vg.LoadStatus.NONE)
self.assertEqual(feats, [])
if __name__ == "__main__":
unittest.main()