Files
Plugin_SN_Verfahrensgebiet/tests/test_flurstueck_suche.py
T
DanielandClaude Opus 5.5 c8b380b5d3 Tab „Eigentümer“ mit Flurstückssuche (#56)
Gemarkung (Name oder Nummer) und Flurstücksnummer eingeben, die Treffer
werden im Layer „Flurstücke“ ausgewählt, angezoomt und kurz hervorgehoben.
Verglichen wird das flurstueckskennzeichen, Gemarkungsnamen werden über
den Layer „Gemarkungen“ aufgelöst. Ohne Layer „Flurstücke“ weist ein
Dialog darauf hin, zuerst Verfahrensgebiet und Flurstücke zu laden.

Erster Schritt von #56; Eigentümersuche und Anzeigefenster folgen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 12:44:45 +02:00

147 lines
6.5 KiB
Python

"""Tests für die Flurstückssuche im Layer „Flurstücke“ (#56)."""
import types
import unittest
from unittest.mock import patch
from sn_verfahrensgebiet.functions import flurstueck_suche as fs
class _Feature(dict):
def __init__(self, fid, **attribute):
super().__init__(attribute)
self._fid = fid
def id(self):
return self._fid
class _Layer:
def __init__(self, name, features, felder=("flurstueckskennzeichen",)):
self._name = name
self._features = features
self._felder = list(felder)
def name(self):
return self._name
def fields(self):
return types.SimpleNamespace(
indexFromName=lambda n: self._felder.index(n) if n in self._felder else -1
)
def getFeatures(self):
return iter(self._features)
def _flurstuecke():
return _Layer("Flurstücke", [
_Feature(1, flurstueckskennzeichen="140268___00562____00"),
_Feature(2, flurstueckskennzeichen="140268___00562000100"),
_Feature(3, flurstueckskennzeichen="140268___00012000300"),
_Feature(4, flurstueckskennzeichen="140269___00562____00"),
_Feature(5, flurstueckskennzeichen="140268___00012000a00"),
_Feature(6, flurstueckskennzeichen=None),
])
def _gemarkungen():
return _Layer("Gemarkungen", [
_Feature(1, schluessel="140640268", ave_name="Beispielhausen"),
_Feature(2, schluessel="140640269", ave_name="Musterdorf"),
_Feature(3, schluessel="140650270", ave_name="Musterdorf"),
], felder=("schluessel", "ave_name"))
def _projekt(*layer):
nach_name = {lyr.name(): lyr for lyr in layer}
projekt = types.SimpleNamespace(
mapLayersByName=lambda name: [nach_name[name]] if name in nach_name else []
)
return types.SimpleNamespace(instance=lambda: projekt)
class TestEingabe(unittest.TestCase):
def test_flurstuecksnummer_mit_und_ohne_nenner(self):
"""Prüft, dass Zähler und Nenner getrennt und führende Nullen entfernt werden."""
self.assertEqual(fs.zerlege_flurstuecksnummer("562"), ("562", ""))
self.assertEqual(fs.zerlege_flurstuecksnummer(" 0012 / 03 "), ("12", "3"))
self.assertEqual(fs.zerlege_flurstuecksnummer("12/A"), ("12", "a"))
def test_ungueltige_flurstuecksnummer(self):
"""Prüft, dass leere oder unzulässige Flurstücksnummern abgelehnt werden."""
for text in ("", "abc", "12/", "12/3/4", "12-3"):
with self.subTest(text=text):
with self.assertRaises(fs.FlurstueckSucheFehler):
fs.zerlege_flurstuecksnummer(text)
def test_kennzeichen_zerlegen(self):
"""Prüft, dass Gemarkung, Zähler und Nenner aus dem ALKIS-Kennzeichen gelesen werden."""
self.assertEqual(fs.zerlege_kennzeichen("140268___00562____00"), ("0268", "562", ""))
self.assertEqual(fs.zerlege_kennzeichen("140268___00012000300"), ("0268", "12", "3"))
self.assertEqual(fs.zerlege_kennzeichen("140268___00012000a00"), ("0268", "12", "a"))
self.assertIsNone(fs.zerlege_kennzeichen("1402"))
self.assertIsNone(fs.zerlege_kennzeichen(None))
def test_gemarkungsnummer_aus_ziffern(self):
"""Prüft, dass Ziffern als Gemarkungsnummer gelten, auch ohne führende Nullen oder als langer Schlüssel."""
self.assertEqual(fs.gemarkungsnummern("268"), ["0268"])
self.assertEqual(fs.gemarkungsnummern("140268"), ["0268"])
def test_gemarkungsname_ueber_gemarkungslayer(self):
"""Prüft, dass ein Gemarkungsname ohne Rücksicht auf Großschreibung in alle passenden Nummern übersetzt wird."""
self.assertEqual(fs.gemarkungsnummern("beispielhausen", _gemarkungen()), ["0268"])
self.assertEqual(fs.gemarkungsnummern("Musterdorf", _gemarkungen()), ["0269", "0270"])
def test_gemarkungsname_ohne_layer_oder_unbekannt(self):
"""Prüft, dass ein Name ohne Gemarkungslayer oder ohne Treffer eine verständliche Meldung ergibt."""
with self.assertRaisesRegex(fs.FlurstueckSucheFehler, "Gemarkungsnummer"):
fs.gemarkungsnummern("Beispielhausen", None)
with self.assertRaisesRegex(fs.FlurstueckSucheFehler, "keine Gemarkung"):
fs.gemarkungsnummern("Nirgendwo", _gemarkungen())
with self.assertRaises(fs.FlurstueckSucheFehler):
fs.gemarkungsnummern(" ")
class TestSuche(unittest.TestCase):
def test_mit_nenner_genau_ein_treffer(self):
"""Prüft, dass mit Nenner nur das passende Flurstück der Gemarkung gefunden wird."""
self.assertEqual(fs.finde_flurstuecke(_flurstuecke(), ["0268"], "12", "3"), [3])
self.assertEqual(fs.finde_flurstuecke(_flurstuecke(), ["0268"], "12", "a"), [5])
def test_ohne_nenner_alle_mit_diesem_zaehler(self):
"""Prüft, dass ohne Nenner alle Flurstücke mit dem Zähler gefunden werden, aber nur in der gesuchten Gemarkung."""
self.assertEqual(fs.finde_flurstuecke(_flurstuecke(), ["0268"], "562", ""), [1, 2])
self.assertEqual(fs.finde_flurstuecke(_flurstuecke(), ["0268", "0269"], "562", ""), [1, 2, 4])
def test_kein_treffer(self):
"""Prüft, dass ein nicht vorhandenes Flurstück eine leere Trefferliste ergibt."""
self.assertEqual(fs.finde_flurstuecke(_flurstuecke(), ["0268"], "999", ""), [])
def test_layer_ohne_kennzeichenfeld(self):
"""Prüft, dass ein Flurstückslayer ohne Feld „flurstueckskennzeichen“ gemeldet wird."""
layer = _Layer("Flurstücke", [], felder=("gml_id",))
with self.assertRaisesRegex(fs.FlurstueckSucheFehler, "flurstueckskennzeichen"):
fs.finde_flurstuecke(layer, ["0268"], "562", "")
def test_fehlender_flurstueckslayer_bricht_ab(self):
"""Prüft, dass die Suche ohne Layer „Flurstücke“ mit dem Hinweis abbricht, zuerst Verfahrensgebiet und Flurstücke zu laden."""
with patch.object(fs, "QgsProject", _projekt(_gemarkungen())):
with self.assertRaises(fs.KeinFlurstueckslayer) as kontext:
fs.flurstueck_suchen("0268", "562")
self.assertIn("Flurstücke aus ALKIS laden", str(kontext.exception))
def test_suche_im_projekt_mit_gemarkungsname(self):
"""Prüft, dass die Suche im Projekt den Gemarkungsnamen auflöst und Layer samt Treffern liefert."""
flurstuecke = _flurstuecke()
with patch.object(fs, "QgsProject", _projekt(flurstuecke, _gemarkungen())):
ergebnis = fs.flurstueck_suchen("Beispielhausen", "12/3")
self.assertIs(ergebnis.layer, flurstuecke)
self.assertEqual(ergebnis.feature_ids, [3])
if __name__ == "__main__":
unittest.main()