"""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()