933 lines
37 KiB
Python
933 lines
37 KiB
Python
"""sn_verfahrensgebiet/tests/test_verfahrensgebiet_shape_komplett.py
|
|||
|
|
|
||
|
|
Unit-Tests für :mod:`sn_verfahrensgebiet.functions.verfahrensgebiet_shape_komplett`.
|
||
|
|
|
||
|
|
Getestete Szenarien:
|
||
|
|
|
||
|
|
lade_vg_aus_zip:
|
||
|
|
- Dateidialog abgebrochen (leerer Pfad) → None
|
||
|
|
- ZIP-Entpacken schlägt fehl (Exception) → None + QMessageBox.warning
|
||
|
|
- Kein .shp in ZIP → None + Warning "gültiges Shape-Dateiset angeben"
|
||
|
|
- QgsVectorLayer nicht valid → None + Warning
|
||
|
|
- Leere Geometrien im Shapefile → None + Warning
|
||
|
|
- Erfolgspfad → Memory-Layer mit Union-Geometrie, Name "Verfahrensgebiet"
|
||
|
|
|
||
|
|
verfahrensgebiet_shape_komplett:
|
||
|
|
- lade_vg_aus_zip None (Abbruch) → (None, None, None, NONE)
|
||
|
|
- flurstueck_alkis NONE → (None, None, None, NONE)
|
||
|
|
- Keine Flurstücke selektiert → (None, flst, None, NONE) + QMessageBox.warning
|
||
|
|
- erstelle_verfahrensgebiet_aus_auswahl ungültig → Workflow noch immer abgeschlossen
|
||
|
|
(temp_enriched-Fehler: stimmt_ueberein=True wegen 0-Fläche)
|
||
|
|
- Flächenübereinstimmung → show_info_dialog, return (shape_vg, flst, None, FIRST)
|
||
|
|
- Flächenabweichung + abbrechen → return (shape_vg, flst, None, FIRST)
|
||
|
|
- Flächenabweichung + detailpruefung → lade_punktort_ta + knickpunkt_pruefung aufgerufen
|
||
|
|
- Cleanup: TempVerfahrensgebiet stets aus Projekt entfernt
|
||
|
|
"""
|
||
|
|
|
||
|
|
import sys
|
||
|
|
import os
|
||
|
|
import types
|
||
|
|
import unittest
|
||
|
|
from unittest.mock import patch, MagicMock, call
|
||
|
|
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
# 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.verfahrensgebiet_alkis import LoadStatus
|
||
|
|
from sn_verfahrensgebiet.functions.verfahrensgebiet_shape_komplett import (
|
||
|
|
verfahrensgebiet_shape_komplett,
|
||
|
|
lade_vg_aus_zip,
|
||
|
|
_finde_shp,
|
||
|
|
_erstelle_memory_layer_aus_shp,
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
# Hilfs-Dummies
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
def _make_layer(valid=True, name="Layer", lid="L1", feature_count=1, area=1000.0):
|
||
|
|
layer = MagicMock()
|
||
|
|
layer.isValid.return_value = valid
|
||
|
|
layer.id.return_value = lid
|
||
|
|
layer.name.return_value = name
|
||
|
|
layer.featureCount.return_value = feature_count
|
||
|
|
layer.selectedFeatureCount.return_value = feature_count
|
||
|
|
|
||
|
|
mock_geom = MagicMock()
|
||
|
|
mock_geom.isEmpty.return_value = False
|
||
|
|
mock_geom.area.return_value = area
|
||
|
|
mock_feat = MagicMock()
|
||
|
|
mock_feat.geometry.return_value = mock_geom
|
||
|
|
layer.getFeatures.return_value = [mock_feat]
|
||
|
|
|
||
|
|
mock_crs = MagicMock()
|
||
|
|
mock_crs.authid.return_value = "EPSG:25833"
|
||
|
|
layer.crs.return_value = mock_crs
|
||
|
|
return layer
|
||
|
|
|
||
|
|
|
||
|
|
class _DummyProject:
|
||
|
|
def __init__(self):
|
||
|
|
self.added = []
|
||
|
|
self.removed = []
|
||
|
|
self._layers_by_name: dict = {}
|
||
|
|
|
||
|
|
def addMapLayer(self, layer):
|
||
|
|
self.added.append(layer)
|
||
|
|
|
||
|
|
def removeMapLayer(self, lid):
|
||
|
|
self.removed.append(lid)
|
||
|
|
|
||
|
|
def mapLayersByName(self, name):
|
||
|
|
return self._layers_by_name.get(name, [])
|
||
|
|
|
||
|
|
def mapLayer(self, lid):
|
||
|
|
return None
|
||
|
|
|
||
|
|
def instance(self):
|
||
|
|
return self
|
||
|
|
|
||
|
|
|
||
|
|
def _make_progress_mock(canceled=False):
|
||
|
|
prog = MagicMock()
|
||
|
|
prog.is_canceled.return_value = canceled
|
||
|
|
return prog
|
||
|
|
|
||
|
|
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
# Patch-Konstanten
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
_MOD = "sn_verfahrensgebiet.functions.verfahrensgebiet_shape_komplett"
|
||
|
|
_PATCH_LADE_ZIP = f"{_MOD}.lade_vg_aus_zip"
|
||
|
|
_PATCH_GEM = f"{_MOD}.gemarkung_schluessel_und_namen_von_vg_geometrie"
|
||
|
|
_PATCH_FLST = f"{_MOD}.flurstueck_alkis"
|
||
|
|
_PATCH_SELECT = f"{_MOD}._select_by_location"
|
||
|
|
_PATCH_ERSTELLE = f"{_MOD}.erstelle_verfahrensgebiet_aus_auswahl"
|
||
|
|
_PATCH_PROJECT = f"{_MOD}.QgsProject"
|
||
|
|
_PATCH_MSGBOX = f"{_MOD}.QMessageBox"
|
||
|
|
_PATCH_WARNING = f"{_MOD}.warning"
|
||
|
|
_PATCH_PROGRESS = f"{_MOD}.create_progress_dialog"
|
||
|
|
_PATCH_VERGLEICHE = f"{_MOD}._vergleiche_flaechen"
|
||
|
|
_PATCH_SHOW_INFO = f"{_MOD}.show_info_dialog"
|
||
|
|
_PATCH_ASK_DIALOG = f"{_MOD}.ask_detailpruefung_oder_abbrechen"
|
||
|
|
_PATCH_GP_ALKIS = f"{_MOD}.lade_punktort_ta"
|
||
|
|
_PATCH_KNICK = f"{_MOD}.knickpunkt_pruefung"
|
||
|
|
_PATCH_EXTRAHIERE = f"{_MOD}._extrahiere_knickpunkte"
|
||
|
|
_PATCH_LESE_TOL = f"{_MOD}._lese_flaechen_toleranz"
|
||
|
|
|
||
|
|
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
# Tests: _finde_shp
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
class TestFindShp(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_findet_shp_in_root(self):
|
||
|
|
with patch("os.walk") as mock_walk:
|
||
|
|
mock_walk.return_value = [
|
||
|
|
("/extract", [], ["shape.shp", "shape.dbf"]),
|
||
|
|
]
|
||
|
|
result = _finde_shp("/extract")
|
||
|
|
self.assertEqual(result, os.path.join("/extract", "shape.shp"))
|
||
|
|
|
||
|
|
def test_findet_shp_in_unterordner(self):
|
||
|
|
with patch("os.walk") as mock_walk:
|
||
|
|
mock_walk.return_value = [
|
||
|
|
("/extract", ["sub"], []),
|
||
|
|
("/extract/sub", [], ["daten.shp"]),
|
||
|
|
]
|
||
|
|
result = _finde_shp("/extract")
|
||
|
|
self.assertEqual(result, os.path.join("/extract/sub", "daten.shp"))
|
||
|
|
|
||
|
|
def test_kein_shp_gibt_none_zurueck(self):
|
||
|
|
with patch("os.walk") as mock_walk:
|
||
|
|
mock_walk.return_value = [
|
||
|
|
("/extract", [], ["shape.dbf", "shape.prj"]),
|
||
|
|
]
|
||
|
|
result = _finde_shp("/extract")
|
||
|
|
self.assertIsNone(result)
|
||
|
|
|
||
|
|
def test_case_insensitive_erkennung(self):
|
||
|
|
with patch("os.walk") as mock_walk:
|
||
|
|
mock_walk.return_value = [
|
||
|
|
("/extract", [], ["DATEN.SHP"]),
|
||
|
|
]
|
||
|
|
result = _finde_shp("/extract")
|
||
|
|
self.assertIsNotNone(result)
|
||
|
|
|
||
|
|
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
# Tests: _erstelle_memory_layer_aus_shp
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
class TestErstelleMemoryLayerAusShp(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_leere_geometrien_geben_none(self):
|
||
|
|
shp_layer = MagicMock()
|
||
|
|
geom = MagicMock()
|
||
|
|
geom.isEmpty.return_value = True
|
||
|
|
feat = MagicMock()
|
||
|
|
feat.geometry.return_value = geom
|
||
|
|
shp_layer.getFeatures.return_value = [feat]
|
||
|
|
shp_layer.crs.return_value.authid.return_value = "EPSG:25833"
|
||
|
|
|
||
|
|
result = _erstelle_memory_layer_aus_shp(shp_layer)
|
||
|
|
self.assertIsNone(result)
|
||
|
|
|
||
|
|
def test_keine_features_gibt_none(self):
|
||
|
|
shp_layer = MagicMock()
|
||
|
|
shp_layer.getFeatures.return_value = []
|
||
|
|
shp_layer.crs.return_value.authid.return_value = "EPSG:25833"
|
||
|
|
|
||
|
|
result = _erstelle_memory_layer_aus_shp(shp_layer)
|
||
|
|
self.assertIsNone(result)
|
||
|
|
|
||
|
|
@patch(f"{_MOD}.QgsGeometry")
|
||
|
|
@patch(f"{_MOD}.QgsVectorLayer")
|
||
|
|
@patch(f"{_MOD}.QgsFeature")
|
||
|
|
def test_attribute_von_erstem_feature_werden_gesetzt(
|
||
|
|
self, mock_feat_cls, mock_vl_cls, mock_geom_cls
|
||
|
|
):
|
||
|
|
"""Attributwerte des ersten Features werden auf das Union-Feature übertragen."""
|
||
|
|
# Geometrie-Mock
|
||
|
|
mock_union = MagicMock()
|
||
|
|
mock_union.isEmpty.return_value = False
|
||
|
|
mock_geom_cls.unaryUnion.return_value = mock_union
|
||
|
|
|
||
|
|
# Memory-Layer-Mock
|
||
|
|
mock_mem = MagicMock()
|
||
|
|
mock_mem.isValid.return_value = True
|
||
|
|
mock_mem.featureCount.return_value = 1
|
||
|
|
mock_vl_cls.return_value = mock_mem
|
||
|
|
mock_pr = MagicMock()
|
||
|
|
mock_mem.dataProvider.return_value = mock_pr
|
||
|
|
|
||
|
|
# Feature-Mock (Output)
|
||
|
|
mock_feat_out = MagicMock()
|
||
|
|
mock_feat_cls.return_value = mock_feat_out
|
||
|
|
|
||
|
|
# Shapefile-Layer-Mock
|
||
|
|
shp_layer = MagicMock()
|
||
|
|
shp_layer.crs.return_value.authid.return_value = "EPSG:25833"
|
||
|
|
shp_layer.fields.return_value = [MagicMock(), MagicMock()] # list → iterable
|
||
|
|
|
||
|
|
mock_geom = MagicMock()
|
||
|
|
mock_geom.isEmpty.return_value = False
|
||
|
|
src_feat = MagicMock()
|
||
|
|
src_feat.geometry.return_value = mock_geom
|
||
|
|
src_feat.attributes.return_value = ["wert_a", 42]
|
||
|
|
shp_layer.getFeatures.return_value = [src_feat]
|
||
|
|
|
||
|
|
result = _erstelle_memory_layer_aus_shp(shp_layer)
|
||
|
|
|
||
|
|
# Felder sollen übernommen werden
|
||
|
|
mock_pr.addAttributes.assert_called_once()
|
||
|
|
# Attributwerte sollen vom ersten Feature gesetzt werden
|
||
|
|
mock_feat_out.setAttributes.assert_called_once_with(["wert_a", 42])
|
||
|
|
self.assertIs(result, mock_mem)
|
||
|
|
|
||
|
|
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
# Tests: lade_vg_aus_zip
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
class TestLadeVgAusZip(unittest.TestCase):
|
||
|
|
|
||
|
|
def _patch(self, **kwargs):
|
||
|
|
"""Hilfsmethode: kombinierter Patch-Kontext für lade_vg_aus_zip."""
|
||
|
|
return kwargs
|
||
|
|
|
||
|
|
@patch(f"{_MOD}.QFileDialog")
|
||
|
|
def test_dialog_abgebrochen_gibt_none_zurueck(self, mock_fd):
|
||
|
|
mock_fd.getOpenFileName.return_value = ("", "")
|
||
|
|
result = lade_vg_aus_zip(None)
|
||
|
|
self.assertIsNone(result)
|
||
|
|
|
||
|
|
@patch(f"{_MOD}.QMessageBox")
|
||
|
|
@patch(f"{_MOD}.zipfile")
|
||
|
|
@patch(f"{_MOD}.QFileDialog")
|
||
|
|
def test_zip_fehler_gibt_none_und_warning(self, mock_fd, mock_zf, mock_mb):
|
||
|
|
mock_fd.getOpenFileName.return_value = ("/tmp/vg.zip", "")
|
||
|
|
mock_zf.ZipFile.side_effect = Exception("bad zip")
|
||
|
|
|
||
|
|
with patch("os.path.dirname", return_value="/tmp"), \
|
||
|
|
patch("os.path.splitext", return_value=("/tmp/vg", ".zip")), \
|
||
|
|
patch("os.path.basename", return_value="vg.zip"), \
|
||
|
|
patch("os.path.join", return_value="/tmp/vg"):
|
||
|
|
result = lade_vg_aus_zip(None)
|
||
|
|
|
||
|
|
self.assertIsNone(result)
|
||
|
|
mock_mb.warning.assert_called_once()
|
||
|
|
|
||
|
|
@patch(f"{_MOD}.QMessageBox")
|
||
|
|
@patch(f"{_MOD}._finde_shp", return_value=None)
|
||
|
|
@patch(f"{_MOD}.zipfile")
|
||
|
|
@patch(f"{_MOD}.QFileDialog")
|
||
|
|
def test_kein_shp_in_zip_gibt_none_und_warning(self, mock_fd, mock_zf, mock_find, mock_mb):
|
||
|
|
mock_fd.getOpenFileName.return_value = ("/tmp/vg.zip", "")
|
||
|
|
mock_zf.ZipFile.return_value.__enter__ = MagicMock(return_value=MagicMock())
|
||
|
|
mock_zf.ZipFile.return_value.__exit__ = MagicMock(return_value=False)
|
||
|
|
|
||
|
|
with patch("os.path.dirname", return_value="/tmp"), \
|
||
|
|
patch("os.path.splitext", return_value=("/tmp/vg", ".zip")), \
|
||
|
|
patch("os.path.basename", return_value="vg.zip"), \
|
||
|
|
patch("os.path.join", return_value="/tmp/vg"):
|
||
|
|
result = lade_vg_aus_zip(None)
|
||
|
|
|
||
|
|
self.assertIsNone(result)
|
||
|
|
mock_mb.warning.assert_called_once()
|
||
|
|
args = mock_mb.warning.call_args[0]
|
||
|
|
self.assertIn("gültiges Shape-Dateiset angeben", args)
|
||
|
|
|
||
|
|
@patch(f"{_MOD}.QMessageBox")
|
||
|
|
@patch(f"{_MOD}.QgsVectorLayer")
|
||
|
|
@patch(f"{_MOD}._finde_shp", return_value="/tmp/vg/shape.shp")
|
||
|
|
@patch(f"{_MOD}.zipfile")
|
||
|
|
@patch(f"{_MOD}.QFileDialog")
|
||
|
|
def test_invalider_qgslayer_gibt_none_und_warning(
|
||
|
|
self, mock_fd, mock_zf, mock_find, mock_vl, mock_mb
|
||
|
|
):
|
||
|
|
mock_fd.getOpenFileName.return_value = ("/tmp/vg.zip", "")
|
||
|
|
mock_zf.ZipFile.return_value.__enter__ = MagicMock(return_value=MagicMock())
|
||
|
|
mock_zf.ZipFile.return_value.__exit__ = MagicMock(return_value=False)
|
||
|
|
|
||
|
|
invalid_layer = MagicMock()
|
||
|
|
invalid_layer.isValid.return_value = False
|
||
|
|
mock_vl.return_value = invalid_layer
|
||
|
|
|
||
|
|
with patch("os.path.dirname", return_value="/tmp"), \
|
||
|
|
patch("os.path.splitext", return_value=("/tmp/vg", ".zip")), \
|
||
|
|
patch("os.path.basename", return_value="vg.zip"), \
|
||
|
|
patch("os.path.join", return_value="/tmp/vg"):
|
||
|
|
result = lade_vg_aus_zip(None)
|
||
|
|
|
||
|
|
self.assertIsNone(result)
|
||
|
|
mock_mb.warning.assert_called_once()
|
||
|
|
args = mock_mb.warning.call_args[0]
|
||
|
|
self.assertIn("gültiges Shape-Dateiset angeben", args)
|
||
|
|
|
||
|
|
@patch(f"{_MOD}.QMessageBox")
|
||
|
|
@patch(f"{_MOD}._erstelle_memory_layer_aus_shp", return_value=None)
|
||
|
|
@patch(f"{_MOD}.QgsVectorLayer")
|
||
|
|
@patch(f"{_MOD}._finde_shp", return_value="/tmp/vg/shape.shp")
|
||
|
|
@patch(f"{_MOD}.zipfile")
|
||
|
|
@patch(f"{_MOD}.QFileDialog")
|
||
|
|
def test_leere_geometrien_geben_none_und_warning(
|
||
|
|
self, mock_fd, mock_zf, mock_find, mock_vl, mock_mem, mock_mb
|
||
|
|
):
|
||
|
|
mock_fd.getOpenFileName.return_value = ("/tmp/vg.zip", "")
|
||
|
|
mock_zf.ZipFile.return_value.__enter__ = MagicMock(return_value=MagicMock())
|
||
|
|
mock_zf.ZipFile.return_value.__exit__ = MagicMock(return_value=False)
|
||
|
|
valid_layer = MagicMock()
|
||
|
|
valid_layer.isValid.return_value = True
|
||
|
|
mock_vl.return_value = valid_layer
|
||
|
|
|
||
|
|
with patch("os.path.dirname", return_value="/tmp"), \
|
||
|
|
patch("os.path.splitext", return_value=("/tmp/vg", ".zip")), \
|
||
|
|
patch("os.path.basename", return_value="vg.zip"), \
|
||
|
|
patch("os.path.join", return_value="/tmp/vg"):
|
||
|
|
result = lade_vg_aus_zip(None)
|
||
|
|
|
||
|
|
self.assertIsNone(result)
|
||
|
|
mock_mb.warning.assert_called_once()
|
||
|
|
|
||
|
|
@patch(f"{_MOD}._erstelle_memory_layer_aus_shp")
|
||
|
|
@patch(f"{_MOD}.QgsVectorLayer")
|
||
|
|
@patch(f"{_MOD}._finde_shp", return_value="/tmp/vg/shape.shp")
|
||
|
|
@patch(f"{_MOD}.zipfile")
|
||
|
|
@patch(f"{_MOD}.QFileDialog")
|
||
|
|
def test_erfolg_gibt_memory_layer_zurueck(
|
||
|
|
self, mock_fd, mock_zf, mock_find, mock_vl, mock_mem
|
||
|
|
):
|
||
|
|
mock_fd.getOpenFileName.return_value = ("/tmp/vg.zip", "")
|
||
|
|
mock_zf.ZipFile.return_value.__enter__ = MagicMock(return_value=MagicMock())
|
||
|
|
mock_zf.ZipFile.return_value.__exit__ = MagicMock(return_value=False)
|
||
|
|
valid_layer = MagicMock()
|
||
|
|
valid_layer.isValid.return_value = True
|
||
|
|
mock_vl.return_value = valid_layer
|
||
|
|
|
||
|
|
mem_layer = _make_layer(name="Verfahrensgebiet", lid="MEM1")
|
||
|
|
mock_mem.return_value = mem_layer
|
||
|
|
|
||
|
|
with patch("os.path.dirname", return_value="/tmp"), \
|
||
|
|
patch("os.path.splitext", return_value=("/tmp/vg", ".zip")), \
|
||
|
|
patch("os.path.basename", return_value="vg.zip"), \
|
||
|
|
patch("os.path.join", return_value="/tmp/vg"):
|
||
|
|
result = lade_vg_aus_zip(None)
|
||
|
|
|
||
|
|
self.assertIs(result, mem_layer)
|
||
|
|
|
||
|
|
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
# Tests: verfahrensgebiet_shape_komplett (Hauptworkflow)
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
class TestVerfahrensgebietShapeKomplett(unittest.TestCase):
|
||
|
|
|
||
|
|
# ------------------------------------------------------------------ #
|
||
|
|
# Abbruchpfade
|
||
|
|
# ------------------------------------------------------------------ #
|
||
|
|
|
||
|
|
@patch(_PATCH_PROGRESS)
|
||
|
|
@patch(_PATCH_PROJECT)
|
||
|
|
@patch(_PATCH_LADE_ZIP)
|
||
|
|
def test_lade_zip_none_aborts(self, mock_lade, mock_proj, mock_prog):
|
||
|
|
mock_proj.instance.return_value = _DummyProject()
|
||
|
|
mock_lade.return_value = None
|
||
|
|
mock_prog.return_value = _make_progress_mock()
|
||
|
|
|
||
|
|
enriched, flst, bror, status = verfahrensgebiet_shape_komplett(None)
|
||
|
|
|
||
|
|
self.assertIsNone(enriched)
|
||
|
|
self.assertIsNone(flst)
|
||
|
|
self.assertIsNone(bror)
|
||
|
|
self.assertEqual(status, LoadStatus.NONE)
|
||
|
|
|
||
|
|
@patch(_PATCH_PROGRESS)
|
||
|
|
@patch(_PATCH_PROJECT)
|
||
|
|
@patch(_PATCH_GEM)
|
||
|
|
@patch(_PATCH_LADE_ZIP)
|
||
|
|
def test_shape_vg_sofort_ins_projekt_nach_laden(self, mock_lade, mock_gem, mock_proj, mock_prog):
|
||
|
|
"""Shape-VG wird unmittelbar nach dem Laden ins Projekt eingefügt."""
|
||
|
|
proj = _DummyProject()
|
||
|
|
mock_proj.instance.return_value = proj
|
||
|
|
shape_vg = _make_layer(name="Verfahrensgebiet", lid="S1")
|
||
|
|
mock_lade.return_value = shape_vg
|
||
|
|
mock_gem.return_value = []
|
||
|
|
mock_prog.return_value = _make_progress_mock()
|
||
|
|
|
||
|
|
with patch(_PATCH_FLST, return_value=(None, LoadStatus.NONE)):
|
||
|
|
verfahrensgebiet_shape_komplett(None)
|
||
|
|
|
||
|
|
# Shape-VG muss ins Projekt eingefügt worden sein
|
||
|
|
self.assertIn(shape_vg, proj.added)
|
||
|
|
|
||
|
|
@patch(_PATCH_PROGRESS)
|
||
|
|
@patch(_PATCH_PROJECT)
|
||
|
|
@patch(_PATCH_GEM)
|
||
|
|
@patch(_PATCH_LADE_ZIP)
|
||
|
|
def test_shape_vg_wird_bei_abbruch_aus_projekt_entfernt(
|
||
|
|
self, mock_lade, mock_gem, mock_proj, mock_prog
|
||
|
|
):
|
||
|
|
"""Shape-VG wird bei Fehler/Abbruch aus dem Projekt entfernt."""
|
||
|
|
proj = _DummyProject()
|
||
|
|
mock_proj.instance.return_value = proj
|
||
|
|
shape_vg = _make_layer(name="Verfahrensgebiet", lid="S1")
|
||
|
|
mock_lade.return_value = shape_vg
|
||
|
|
mock_gem.return_value = []
|
||
|
|
mock_prog.return_value = _make_progress_mock()
|
||
|
|
|
||
|
|
with patch(_PATCH_FLST, return_value=(None, LoadStatus.NONE)):
|
||
|
|
_, _, _, status = verfahrensgebiet_shape_komplett(None)
|
||
|
|
|
||
|
|
self.assertEqual(status, LoadStatus.NONE)
|
||
|
|
# Layer-ID muss in removed sein
|
||
|
|
self.assertIn("S1", proj.removed)
|
||
|
|
|
||
|
|
@patch(_PATCH_PROGRESS)
|
||
|
|
@patch(_PATCH_PROJECT)
|
||
|
|
@patch(_PATCH_GEM)
|
||
|
|
@patch(_PATCH_LADE_ZIP)
|
||
|
|
def test_shape_vg_bleibt_im_projekt_bei_erfolg(self, mock_lade, mock_gem, mock_proj, mock_prog):
|
||
|
|
"""Bei erfolgreichem Abschluss wird shape_vg NICHT aus dem Projekt entfernt."""
|
||
|
|
proj = _DummyProject()
|
||
|
|
mock_proj.instance.return_value = proj
|
||
|
|
shape_vg = _make_layer(name="Verfahrensgebiet", lid="S1")
|
||
|
|
mock_lade.return_value = shape_vg
|
||
|
|
mock_gem.return_value = []
|
||
|
|
flst_layer = _make_layer(name="Flurstücke", lid="F1")
|
||
|
|
mock_prog.return_value = _make_progress_mock()
|
||
|
|
|
||
|
|
with patch(_PATCH_FLST, return_value=(flst_layer, LoadStatus.FIRST)), \
|
||
|
|
patch(_PATCH_SELECT, return_value=5), \
|
||
|
|
patch(_PATCH_ERSTELLE, return_value=(_make_layer(lid="T1"), 5, 0)), \
|
||
|
|
patch(_PATCH_VERGLEICHE, return_value=(1000.0, 1000.0, True)), \
|
||
|
|
patch(_PATCH_SHOW_INFO):
|
||
|
|
verfahrensgebiet_shape_komplett(None)
|
||
|
|
|
||
|
|
# Layer-ID darf NICHT in removed sein
|
||
|
|
self.assertNotIn("S1", proj.removed)
|
||
|
|
|
||
|
|
@patch(_PATCH_PROGRESS)
|
||
|
|
@patch(_PATCH_PROJECT)
|
||
|
|
@patch(_PATCH_GEM)
|
||
|
|
@patch(_PATCH_LADE_ZIP)
|
||
|
|
def test_flst_none_aborts(self, mock_lade, mock_gem, mock_proj, mock_prog):
|
||
|
|
mock_proj.instance.return_value = _DummyProject()
|
||
|
|
mock_lade.return_value = _make_layer(name="Verfahrensgebiet")
|
||
|
|
mock_gem.return_value = [("1234", "Muster")]
|
||
|
|
mock_prog.return_value = _make_progress_mock()
|
||
|
|
|
||
|
|
with patch(_PATCH_FLST, return_value=(None, LoadStatus.NONE)):
|
||
|
|
enriched, flst, bror, status = verfahrensgebiet_shape_komplett(None)
|
||
|
|
|
||
|
|
self.assertIsNone(enriched)
|
||
|
|
self.assertIsNone(flst)
|
||
|
|
self.assertEqual(status, LoadStatus.NONE)
|
||
|
|
|
||
|
|
@patch(_PATCH_PROGRESS)
|
||
|
|
@patch(_PATCH_MSGBOX)
|
||
|
|
@patch(_PATCH_SELECT)
|
||
|
|
@patch(_PATCH_PROJECT)
|
||
|
|
@patch(_PATCH_GEM)
|
||
|
|
@patch(_PATCH_FLST)
|
||
|
|
@patch(_PATCH_LADE_ZIP)
|
||
|
|
def test_keine_flurstuecke_selektiert_gibt_warning(
|
||
|
|
self, mock_lade, mock_flst, mock_gem, mock_proj, mock_select, mock_mb, mock_prog
|
||
|
|
):
|
||
|
|
mock_proj.instance.return_value = _DummyProject()
|
||
|
|
mock_lade.return_value = _make_layer(name="Verfahrensgebiet")
|
||
|
|
mock_gem.return_value = []
|
||
|
|
flst_layer = _make_layer(name="Flurstücke")
|
||
|
|
mock_flst.return_value = (flst_layer, LoadStatus.FIRST)
|
||
|
|
mock_select.return_value = 0
|
||
|
|
mock_prog.return_value = _make_progress_mock()
|
||
|
|
|
||
|
|
enriched, flst, bror, status = verfahrensgebiet_shape_komplett(None)
|
||
|
|
|
||
|
|
self.assertIsNone(enriched)
|
||
|
|
self.assertIs(flst, flst_layer)
|
||
|
|
self.assertIsNone(bror)
|
||
|
|
self.assertEqual(status, LoadStatus.NONE)
|
||
|
|
mock_mb.warning.assert_called_once()
|
||
|
|
|
||
|
|
# ------------------------------------------------------------------ #
|
||
|
|
# Flächenübereinstimmung
|
||
|
|
# ------------------------------------------------------------------ #
|
||
|
|
|
||
|
|
@patch(_PATCH_SHOW_INFO)
|
||
|
|
@patch(_PATCH_PROGRESS)
|
||
|
|
@patch(_PATCH_VERGLEICHE)
|
||
|
|
@patch(_PATCH_ERSTELLE)
|
||
|
|
@patch(_PATCH_SELECT)
|
||
|
|
@patch(_PATCH_PROJECT)
|
||
|
|
@patch(_PATCH_GEM)
|
||
|
|
@patch(_PATCH_FLST)
|
||
|
|
@patch(_PATCH_LADE_ZIP)
|
||
|
|
def test_flaechen_uebereinstimmung_gibt_info_und_kein_dialog(
|
||
|
|
self, mock_lade, mock_flst, mock_gem, mock_proj,
|
||
|
|
mock_select, mock_erstelle, mock_vergleiche, mock_prog, mock_info
|
||
|
|
):
|
||
|
|
proj = _DummyProject()
|
||
|
|
mock_proj.instance.return_value = proj
|
||
|
|
shape_vg = _make_layer(name="Verfahrensgebiet", lid="S1")
|
||
|
|
mock_lade.return_value = shape_vg
|
||
|
|
mock_gem.return_value = [("1234", "Muster")]
|
||
|
|
flst_layer = _make_layer(name="Flurstücke", lid="F1")
|
||
|
|
mock_flst.return_value = (flst_layer, LoadStatus.FIRST)
|
||
|
|
mock_select.return_value = 5
|
||
|
|
temp_enriched = _make_layer(name="Verfahrensgebiet", lid="T1")
|
||
|
|
mock_erstelle.return_value = (temp_enriched, 5, 0)
|
||
|
|
mock_vergleiche.return_value = (1000.0, 1000.0, True)
|
||
|
|
mock_prog.return_value = _make_progress_mock()
|
||
|
|
|
||
|
|
enriched, flst, bror, status = verfahrensgebiet_shape_komplett(None)
|
||
|
|
|
||
|
|
self.assertIs(enriched, shape_vg)
|
||
|
|
self.assertIs(flst, flst_layer)
|
||
|
|
self.assertIsNone(bror)
|
||
|
|
self.assertEqual(status, LoadStatus.FIRST)
|
||
|
|
mock_info.assert_called_once()
|
||
|
|
|
||
|
|
# ------------------------------------------------------------------ #
|
||
|
|
# Flächenabweichung + Abbrechen
|
||
|
|
# ------------------------------------------------------------------ #
|
||
|
|
|
||
|
|
@patch(_PATCH_ASK_DIALOG)
|
||
|
|
@patch(_PATCH_SHOW_INFO)
|
||
|
|
@patch(_PATCH_PROGRESS)
|
||
|
|
@patch(_PATCH_VERGLEICHE)
|
||
|
|
@patch(_PATCH_ERSTELLE)
|
||
|
|
@patch(_PATCH_SELECT)
|
||
|
|
@patch(_PATCH_PROJECT)
|
||
|
|
@patch(_PATCH_GEM)
|
||
|
|
@patch(_PATCH_FLST)
|
||
|
|
@patch(_PATCH_LADE_ZIP)
|
||
|
|
def test_abweichung_abbrechen_gibt_shape_vg_zurueck(
|
||
|
|
self, mock_lade, mock_flst, mock_gem, mock_proj,
|
||
|
|
mock_select, mock_erstelle, mock_vergleiche, mock_prog, mock_info, mock_ask
|
||
|
|
):
|
||
|
|
proj = _DummyProject()
|
||
|
|
mock_proj.instance.return_value = proj
|
||
|
|
shape_vg = _make_layer(name="Verfahrensgebiet", lid="S1")
|
||
|
|
mock_lade.return_value = shape_vg
|
||
|
|
mock_gem.return_value = []
|
||
|
|
flst_layer = _make_layer(name="Flurstücke", lid="F1")
|
||
|
|
mock_flst.return_value = (flst_layer, LoadStatus.FIRST)
|
||
|
|
mock_select.return_value = 5
|
||
|
|
temp_enriched = _make_layer(name="Verfahrensgebiet", lid="T1")
|
||
|
|
mock_erstelle.return_value = (temp_enriched, 5, 0)
|
||
|
|
mock_vergleiche.return_value = (1000.0, 800.0, False)
|
||
|
|
mock_prog.return_value = _make_progress_mock()
|
||
|
|
mock_ask.return_value = "abbrechen"
|
||
|
|
|
||
|
|
enriched, flst, bror, status = verfahrensgebiet_shape_komplett(None)
|
||
|
|
|
||
|
|
self.assertIs(enriched, shape_vg)
|
||
|
|
self.assertIs(flst, flst_layer)
|
||
|
|
self.assertIsNone(bror)
|
||
|
|
self.assertEqual(status, LoadStatus.FIRST)
|
||
|
|
mock_info.assert_not_called()
|
||
|
|
|
||
|
|
# ------------------------------------------------------------------ #
|
||
|
|
# Detailprüfung
|
||
|
|
# ------------------------------------------------------------------ #
|
||
|
|
|
||
|
|
@patch(_PATCH_SHOW_INFO)
|
||
|
|
@patch(_PATCH_KNICK)
|
||
|
|
@patch(_PATCH_GP_ALKIS)
|
||
|
|
@patch(_PATCH_EXTRAHIERE)
|
||
|
|
@patch(_PATCH_ASK_DIALOG)
|
||
|
|
@patch(_PATCH_PROGRESS)
|
||
|
|
@patch(_PATCH_VERGLEICHE)
|
||
|
|
@patch(_PATCH_ERSTELLE)
|
||
|
|
@patch(_PATCH_SELECT)
|
||
|
|
@patch(_PATCH_PROJECT)
|
||
|
|
@patch(_PATCH_GEM)
|
||
|
|
@patch(_PATCH_FLST)
|
||
|
|
@patch(_PATCH_LADE_ZIP)
|
||
|
|
def test_abweichung_detailpruefung_ruft_knickpunkt_pruefung_auf(
|
||
|
|
self, mock_lade, mock_flst, mock_gem, mock_proj,
|
||
|
|
mock_select, mock_erstelle, mock_vergleiche, mock_prog,
|
||
|
|
mock_ask, mock_extrahiere, mock_gp, mock_knick, mock_info
|
||
|
|
):
|
||
|
|
proj = _DummyProject()
|
||
|
|
mock_proj.instance.return_value = proj
|
||
|
|
shape_vg = _make_layer(name="Verfahrensgebiet", lid="S1")
|
||
|
|
mock_lade.return_value = shape_vg
|
||
|
|
mock_gem.return_value = [("1234", "Muster")]
|
||
|
|
flst_layer = _make_layer(name="Flurstücke", lid="F1")
|
||
|
|
mock_flst.return_value = (flst_layer, LoadStatus.FIRST)
|
||
|
|
mock_select.return_value = 5
|
||
|
|
temp_enriched = _make_layer(name="Verfahrensgebiet", lid="T1")
|
||
|
|
mock_erstelle.return_value = (temp_enriched, 5, 0)
|
||
|
|
mock_vergleiche.return_value = (1000.0, 800.0, False)
|
||
|
|
mock_prog.return_value = _make_progress_mock()
|
||
|
|
mock_ask.return_value = "detailpruefung"
|
||
|
|
|
||
|
|
knickpunkte_mock = [MagicMock() for _ in range(3)]
|
||
|
|
mock_extrahiere.return_value = knickpunkte_mock
|
||
|
|
|
||
|
|
pta_layer = _make_layer(name="PunktortTA", lid="P1")
|
||
|
|
mock_gp.return_value = pta_layer
|
||
|
|
|
||
|
|
ergebnis = _make_layer(name="Knickpunkte", lid="K1")
|
||
|
|
mock_knick.return_value = (ergebnis, 2, 1, 0)
|
||
|
|
|
||
|
|
enriched, flst, bror, status = verfahrensgebiet_shape_komplett(None)
|
||
|
|
|
||
|
|
mock_gp.assert_called_once()
|
||
|
|
mock_knick.assert_called_once()
|
||
|
|
self.assertIs(enriched, shape_vg)
|
||
|
|
self.assertEqual(status, LoadStatus.FIRST)
|
||
|
|
|
||
|
|
@patch(_PATCH_SHOW_INFO)
|
||
|
|
@patch(_PATCH_KNICK)
|
||
|
|
@patch(_PATCH_GP_ALKIS, return_value=None)
|
||
|
|
@patch(_PATCH_EXTRAHIERE)
|
||
|
|
@patch(_PATCH_ASK_DIALOG)
|
||
|
|
@patch(_PATCH_PROGRESS)
|
||
|
|
@patch(_PATCH_VERGLEICHE)
|
||
|
|
@patch(_PATCH_ERSTELLE)
|
||
|
|
@patch(_PATCH_SELECT)
|
||
|
|
@patch(_PATCH_PROJECT)
|
||
|
|
@patch(_PATCH_GEM)
|
||
|
|
@patch(_PATCH_FLST)
|
||
|
|
@patch(_PATCH_LADE_ZIP)
|
||
|
|
def test_punktort_ta_none_gibt_shape_vg_zurueck_und_zeigt_fehler(
|
||
|
|
self, mock_lade, mock_flst, mock_gem, mock_proj,
|
||
|
|
mock_select, mock_erstelle, mock_vergleiche, mock_prog,
|
||
|
|
mock_ask, mock_extrahiere, mock_gp, mock_knick, mock_info
|
||
|
|
):
|
||
|
|
proj = _DummyProject()
|
||
|
|
mock_proj.instance.return_value = proj
|
||
|
|
shape_vg = _make_layer(name="Verfahrensgebiet", lid="S1")
|
||
|
|
mock_lade.return_value = shape_vg
|
||
|
|
mock_gem.return_value = []
|
||
|
|
flst_layer = _make_layer(name="Flurstücke", lid="F1")
|
||
|
|
mock_flst.return_value = (flst_layer, LoadStatus.FIRST)
|
||
|
|
mock_select.return_value = 5
|
||
|
|
temp_enriched = _make_layer(name="Verfahrensgebiet", lid="T1")
|
||
|
|
mock_erstelle.return_value = (temp_enriched, 5, 0)
|
||
|
|
mock_vergleiche.return_value = (1000.0, 800.0, False)
|
||
|
|
mock_prog.return_value = _make_progress_mock()
|
||
|
|
mock_ask.return_value = "detailpruefung"
|
||
|
|
mock_extrahiere.return_value = [MagicMock()]
|
||
|
|
|
||
|
|
with patch(f"{_MOD}.QMessageBox") as mock_mb:
|
||
|
|
enriched, flst, bror, status = verfahrensgebiet_shape_komplett(None)
|
||
|
|
|
||
|
|
mock_knick.assert_not_called()
|
||
|
|
self.assertIs(enriched, shape_vg)
|
||
|
|
mock_mb.critical.assert_called_once()
|
||
|
|
|
||
|
|
# ------------------------------------------------------------------ #
|
||
|
|
# Cleanup: TempVerfahrensgebiet
|
||
|
|
# ------------------------------------------------------------------ #
|
||
|
|
|
||
|
|
@patch(_PATCH_PROGRESS)
|
||
|
|
@patch(_PATCH_GEM)
|
||
|
|
@patch(_PATCH_PROJECT)
|
||
|
|
@patch(_PATCH_LADE_ZIP)
|
||
|
|
def test_temp_layer_wird_stets_entfernt(self, mock_lade, mock_proj, mock_gem, mock_prog):
|
||
|
|
proj = _DummyProject()
|
||
|
|
temp_layer = _make_layer(name="TempVerfahrensgebiet", lid="TEMP")
|
||
|
|
proj._layers_by_name["TempVerfahrensgebiet"] = [temp_layer]
|
||
|
|
mock_proj.instance.return_value = proj
|
||
|
|
mock_lade.return_value = None # → sofortiger Abbruch nach Schritt 1
|
||
|
|
mock_gem.return_value = []
|
||
|
|
mock_prog.return_value = _make_progress_mock()
|
||
|
|
|
||
|
|
verfahrensgebiet_shape_komplett(None)
|
||
|
|
|
||
|
|
self.assertIn("TEMP", proj.removed)
|
||
|
|
|
||
|
|
# ------------------------------------------------------------------ #
|
||
|
|
# Rückgabe-Konsistenz
|
||
|
|
# ------------------------------------------------------------------ #
|
||
|
|
|
||
|
|
@patch(_PATCH_SHOW_INFO)
|
||
|
|
@patch(_PATCH_PROGRESS)
|
||
|
|
@patch(_PATCH_VERGLEICHE)
|
||
|
|
@patch(_PATCH_ERSTELLE)
|
||
|
|
@patch(_PATCH_SELECT)
|
||
|
|
@patch(_PATCH_PROJECT)
|
||
|
|
@patch(_PATCH_GEM)
|
||
|
|
@patch(_PATCH_FLST)
|
||
|
|
@patch(_PATCH_LADE_ZIP)
|
||
|
|
def test_bror_layer_ist_stets_none(
|
||
|
|
self, mock_lade, mock_flst, mock_gem, mock_proj,
|
||
|
|
mock_select, mock_erstelle, mock_vergleiche, mock_prog, mock_info
|
||
|
|
):
|
||
|
|
"""Dritter Rückgabewert ist im Shape-Workflow immer None (kein BROR)."""
|
||
|
|
mock_proj.instance.return_value = _DummyProject()
|
||
|
|
shape_vg = _make_layer(name="Verfahrensgebiet", lid="S1")
|
||
|
|
mock_lade.return_value = shape_vg
|
||
|
|
mock_gem.return_value = []
|
||
|
|
flst_layer = _make_layer(name="Flurstücke", lid="F1")
|
||
|
|
mock_flst.return_value = (flst_layer, LoadStatus.FIRST)
|
||
|
|
mock_select.return_value = 5
|
||
|
|
temp_enriched = _make_layer(lid="T1")
|
||
|
|
mock_erstelle.return_value = (temp_enriched, 5, 0)
|
||
|
|
mock_vergleiche.return_value = (1000.0, 1000.0, True)
|
||
|
|
mock_prog.return_value = _make_progress_mock()
|
||
|
|
|
||
|
|
_, _, bror, _ = verfahrensgebiet_shape_komplett(None)
|
||
|
|
self.assertIsNone(bror)
|
||
|
|
|
||
|
|
# ------------------------------------------------------------------ #
|
||
|
|
# BROR-Ladelogik
|
||
|
|
# ------------------------------------------------------------------ #
|
||
|
|
|
||
|
|
@patch(_PATCH_SHOW_INFO)
|
||
|
|
@patch(_PATCH_PROGRESS)
|
||
|
|
@patch(_PATCH_VERGLEICHE)
|
||
|
|
@patch(_PATCH_SELECT)
|
||
|
|
@patch(_PATCH_PROJECT)
|
||
|
|
@patch(_PATCH_GEM)
|
||
|
|
@patch(_PATCH_FLST)
|
||
|
|
@patch(f"{_MOD}.verfahrensgebiet_alkis")
|
||
|
|
@patch(f"{_MOD}.get_variable", return_value="VF-2026-001")
|
||
|
|
@patch(_PATCH_LADE_ZIP)
|
||
|
|
def test_bror_geladen_und_zurueckgegeben_wenn_vkz_gesetzt(
|
||
|
|
self, mock_lade, mock_get_var, mock_vg_alkis, mock_flst,
|
||
|
|
mock_gem, mock_proj, mock_select, mock_vergleiche, mock_prog, mock_info
|
||
|
|
):
|
||
|
|
"""VKZ gesetzt → verfahrensgebiet_alkis aufgerufen, bror_layer zurückgegeben."""
|
||
|
|
proj = _DummyProject()
|
||
|
|
mock_proj.instance.return_value = proj
|
||
|
|
shape_vg = _make_layer(name="Verfahrensgebiet", lid="S1")
|
||
|
|
mock_lade.return_value = shape_vg
|
||
|
|
mock_gem.return_value = []
|
||
|
|
flst_layer = _make_layer(name="Flurstücke", lid="F1")
|
||
|
|
mock_flst.return_value = (flst_layer, LoadStatus.FIRST)
|
||
|
|
mock_select.return_value = 5
|
||
|
|
bror = _make_layer(name="Verfahrensgebiet", lid="BROR")
|
||
|
|
mock_vg_alkis.return_value = (bror, LoadStatus.FIRST, [])
|
||
|
|
mock_vergleiche.return_value = (1000.0, 1000.0, True)
|
||
|
|
mock_prog.return_value = _make_progress_mock()
|
||
|
|
|
||
|
|
enriched, flst, bror_ret, status = verfahrensgebiet_shape_komplett(None)
|
||
|
|
|
||
|
|
mock_vg_alkis.assert_called_once()
|
||
|
|
self.assertIs(bror_ret, bror)
|
||
|
|
self.assertIs(enriched, shape_vg)
|
||
|
|
self.assertEqual(status, LoadStatus.FIRST)
|
||
|
|
|
||
|
|
@patch(_PATCH_SHOW_INFO)
|
||
|
|
@patch(_PATCH_PROGRESS)
|
||
|
|
@patch(_PATCH_VERGLEICHE)
|
||
|
|
@patch(_PATCH_SELECT)
|
||
|
|
@patch(_PATCH_PROJECT)
|
||
|
|
@patch(_PATCH_GEM)
|
||
|
|
@patch(_PATCH_FLST)
|
||
|
|
@patch(f"{_MOD}.verfahrensgebiet_alkis")
|
||
|
|
@patch(f"{_MOD}.get_variable", return_value="VF-2026-001")
|
||
|
|
@patch(_PATCH_LADE_ZIP)
|
||
|
|
def test_bror_wird_vor_shape_vg_ins_projekt_eingefuegt(
|
||
|
|
self, mock_lade, mock_get_var, mock_vg_alkis, mock_flst,
|
||
|
|
mock_gem, mock_proj, mock_select, mock_vergleiche, mock_prog, mock_info
|
||
|
|
):
|
||
|
|
"""BROR wird VOR shape_vg ins Projekt eingefügt (kein Namenskonflikt)."""
|
||
|
|
proj = _DummyProject()
|
||
|
|
mock_proj.instance.return_value = proj
|
||
|
|
shape_vg = _make_layer(name="Verfahrensgebiet", lid="S1")
|
||
|
|
mock_lade.return_value = shape_vg
|
||
|
|
mock_gem.return_value = []
|
||
|
|
flst_layer = _make_layer(name="Flurstücke", lid="F1")
|
||
|
|
mock_flst.return_value = (flst_layer, LoadStatus.FIRST)
|
||
|
|
mock_select.return_value = 5
|
||
|
|
bror = _make_layer(name="Verfahrensgebiet", lid="BROR")
|
||
|
|
mock_vg_alkis.return_value = (bror, LoadStatus.FIRST, [])
|
||
|
|
mock_vergleiche.return_value = (1000.0, 1000.0, True)
|
||
|
|
mock_prog.return_value = _make_progress_mock()
|
||
|
|
|
||
|
|
verfahrensgebiet_shape_komplett(None)
|
||
|
|
|
||
|
|
# BROR muss in added sein
|
||
|
|
self.assertIn(bror, proj.added)
|
||
|
|
# BROR muss vor shape_vg hinzugefügt werden
|
||
|
|
bror_idx = proj.added.index(bror)
|
||
|
|
shape_idx = proj.added.index(shape_vg)
|
||
|
|
self.assertLess(bror_idx, shape_idx, "BROR muss vor shape_vg eingefügt werden")
|
||
|
|
|
||
|
|
@patch(_PATCH_PROGRESS)
|
||
|
|
@patch(_PATCH_VERGLEICHE)
|
||
|
|
@patch(_PATCH_SELECT)
|
||
|
|
@patch(_PATCH_PROJECT)
|
||
|
|
@patch(_PATCH_GEM)
|
||
|
|
@patch(_PATCH_FLST)
|
||
|
|
@patch(f"{_MOD}.verfahrensgebiet_alkis")
|
||
|
|
@patch(f"{_MOD}.get_variable", return_value="VF-2026-001")
|
||
|
|
@patch(_PATCH_LADE_ZIP)
|
||
|
|
def test_bror_wird_bei_abbruch_aus_projekt_entfernt(
|
||
|
|
self, mock_lade, mock_get_var, mock_vg_alkis, mock_flst,
|
||
|
|
mock_gem, mock_proj, mock_select, mock_vergleiche, mock_prog
|
||
|
|
):
|
||
|
|
"""BROR und shape_vg werden bei Fehler aus dem Projekt entfernt."""
|
||
|
|
proj = _DummyProject()
|
||
|
|
mock_proj.instance.return_value = proj
|
||
|
|
shape_vg = _make_layer(name="Verfahrensgebiet", lid="S1")
|
||
|
|
mock_lade.return_value = shape_vg
|
||
|
|
mock_gem.return_value = []
|
||
|
|
bror = _make_layer(name="Verfahrensgebiet", lid="BROR")
|
||
|
|
mock_vg_alkis.return_value = (bror, LoadStatus.FIRST, [])
|
||
|
|
mock_flst.return_value = (None, LoadStatus.NONE) # → Abbruch
|
||
|
|
mock_prog.return_value = _make_progress_mock()
|
||
|
|
|
||
|
|
_, _, _, status = verfahrensgebiet_shape_komplett(None)
|
||
|
|
|
||
|
|
self.assertEqual(status, LoadStatus.NONE)
|
||
|
|
self.assertIn("S1", proj.removed)
|
||
|
|
self.assertIn("BROR", proj.removed)
|
||
|
|
|
||
|
|
@patch(_PATCH_PROGRESS)
|
||
|
|
@patch(_PATCH_PROJECT)
|
||
|
|
@patch(_PATCH_GEM)
|
||
|
|
@patch(f"{_MOD}.verfahrensgebiet_alkis")
|
||
|
|
@patch(f"{_MOD}.get_variable", return_value="")
|
||
|
|
@patch(_PATCH_LADE_ZIP)
|
||
|
|
def test_verfahrensgebiet_alkis_nicht_aufgerufen_wenn_vkz_leer(
|
||
|
|
self, mock_lade, mock_get_var, mock_vg_alkis, mock_gem, mock_proj, mock_prog
|
||
|
|
):
|
||
|
|
"""Leere VKZ → verfahrensgebiet_alkis wird NICHT aufgerufen."""
|
||
|
|
mock_proj.instance.return_value = _DummyProject()
|
||
|
|
mock_lade.return_value = _make_layer(name="Verfahrensgebiet")
|
||
|
|
mock_gem.return_value = []
|
||
|
|
mock_prog.return_value = _make_progress_mock()
|
||
|
|
|
||
|
|
with patch(_PATCH_FLST, return_value=(None, LoadStatus.NONE)):
|
||
|
|
verfahrensgebiet_shape_komplett(None)
|
||
|
|
|
||
|
|
mock_vg_alkis.assert_not_called()
|
||
|
|
|
||
|
|
@patch(_PATCH_SHOW_INFO)
|
||
|
|
@patch(_PATCH_PROGRESS)
|
||
|
|
@patch(_PATCH_VERGLEICHE)
|
||
|
|
@patch(_PATCH_SELECT)
|
||
|
|
@patch(_PATCH_PROJECT)
|
||
|
|
@patch(_PATCH_GEM)
|
||
|
|
@patch(_PATCH_FLST)
|
||
|
|
@patch(f"{_MOD}.verfahrensgebiet_alkis")
|
||
|
|
@patch(f"{_MOD}.get_variable", return_value="VF-2026-001")
|
||
|
|
@patch(_PATCH_LADE_ZIP)
|
||
|
|
def test_bror_als_erstes_argument_beim_flaechenvergleich(
|
||
|
|
self, mock_lade, mock_get_var, mock_vg_alkis, mock_flst,
|
||
|
|
mock_gem, mock_proj, mock_select, mock_vergleiche, mock_prog, mock_info
|
||
|
|
):
|
||
|
|
"""Mit BROR: _vergleiche_flaechen wird (bror, shape_vg, ...) aufgerufen."""
|
||
|
|
proj = _DummyProject()
|
||
|
|
mock_proj.instance.return_value = proj
|
||
|
|
shape_vg = _make_layer(name="Verfahrensgebiet", lid="S1")
|
||
|
|
mock_lade.return_value = shape_vg
|
||
|
|
mock_gem.return_value = []
|
||
|
|
flst_layer = _make_layer(name="Flurstücke", lid="F1")
|
||
|
|
mock_flst.return_value = (flst_layer, LoadStatus.FIRST)
|
||
|
|
mock_select.return_value = 5
|
||
|
|
bror = _make_layer(name="Verfahrensgebiet", lid="BROR")
|
||
|
|
mock_vg_alkis.return_value = (bror, LoadStatus.FIRST, [])
|
||
|
|
mock_vergleiche.return_value = (1000.0, 1000.0, True)
|
||
|
|
mock_prog.return_value = _make_progress_mock()
|
||
|
|
|
||
|
|
verfahrensgebiet_shape_komplett(None)
|
||
|
|
|
||
|
|
# Erster Arg = bror, zweiter Arg = shape_vg
|
||
|
|
call_args = mock_vergleiche.call_args[0]
|
||
|
|
self.assertIs(call_args[0], bror)
|
||
|
|
self.assertIs(call_args[1], shape_vg)
|
||
|
|
|
||
|
|
@patch(_PATCH_SHOW_INFO)
|
||
|
|
@patch(_PATCH_PROGRESS)
|
||
|
|
@patch(_PATCH_VERGLEICHE)
|
||
|
|
@patch(_PATCH_ERSTELLE)
|
||
|
|
@patch(_PATCH_SELECT)
|
||
|
|
@patch(_PATCH_PROJECT)
|
||
|
|
@patch(_PATCH_GEM)
|
||
|
|
@patch(_PATCH_FLST)
|
||
|
|
@patch(f"{_MOD}.verfahrensgebiet_alkis", return_value=(None, LoadStatus.NONE, []))
|
||
|
|
@patch(f"{_MOD}.get_variable", return_value="VF-2026-001")
|
||
|
|
@patch(_PATCH_LADE_ZIP)
|
||
|
|
def test_fallback_auf_temp_enriched_wenn_bror_ladeversagen(
|
||
|
|
self, mock_lade, mock_get_var, mock_vg_alkis, mock_flst,
|
||
|
|
mock_gem, mock_proj, mock_select, mock_erstelle, mock_vergleiche, mock_prog, mock_info
|
||
|
|
):
|
||
|
|
"""BROR-Ladeversagen → Fallback: _vergleiche_flaechen mit shape_vg vs temp_enriched."""
|
||
|
|
proj = _DummyProject()
|
||
|
|
mock_proj.instance.return_value = proj
|
||
|
|
shape_vg = _make_layer(name="Verfahrensgebiet", lid="S1")
|
||
|
|
mock_lade.return_value = shape_vg
|
||
|
|
mock_gem.return_value = []
|
||
|
|
flst_layer = _make_layer(name="Flurstücke", lid="F1")
|
||
|
|
mock_flst.return_value = (flst_layer, LoadStatus.FIRST)
|
||
|
|
mock_select.return_value = 5
|
||
|
|
temp_enriched = _make_layer(lid="T1")
|
||
|
|
mock_erstelle.return_value = (temp_enriched, 5, 0)
|
||
|
|
mock_vergleiche.return_value = (1000.0, 1000.0, True)
|
||
|
|
mock_prog.return_value = _make_progress_mock()
|
||
|
|
|
||
|
|
_, _, bror_ret, _ = verfahrensgebiet_shape_komplett(None)
|
||
|
|
|
||
|
|
# kein BROR zurückgegeben
|
||
|
|
self.assertIsNone(bror_ret)
|
||
|
|
# Fallback: erste Arg = shape_vg
|
||
|
|
call_args = mock_vergleiche.call_args[0]
|
||
|
|
self.assertIs(call_args[0], shape_vg)
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
unittest.main()
|