diff --git a/tests/test_dateipruefer.py b/tests/test_dateipruefer.py index 84cd127..d0f62c9 100644 --- a/tests/test_dateipruefer.py +++ b/tests/test_dateipruefer.py @@ -13,6 +13,7 @@ class TestDateipruefer(unittest.TestCase): # 1. Leere Eingabe erlaubt # ----------------------------------------------------- def test_leereingabe_erlaubt(self): + """Prüft, dass eine leere Pfadangabe bei leereingabe_erlaubt=True als 'leereingabe_erlaubt' ohne Kontext gemeldet wird.""" pruefer = Dateipruefer( pfad="", leereingabe_erlaubt=True @@ -28,6 +29,7 @@ class TestDateipruefer(unittest.TestCase): # 2. Leere Eingabe nicht erlaubt # ----------------------------------------------------- def test_leereingabe_nicht_erlaubt(self): + """Prüft, dass eine leere Pfadangabe ohne leereingabe_erlaubt als 'leereingabe_nicht_erlaubt' abgelehnt wird.""" pruefer = Dateipruefer( pfad="", leereingabe_erlaubt=False @@ -43,6 +45,7 @@ class TestDateipruefer(unittest.TestCase): # 3. Standarddatei vorschlagen # ----------------------------------------------------- def test_standarddatei_vorschlagen(self): + """Prüft, dass bei leerer Pfadangabe mit gesetzter Standarddatei 'standarddatei_vorschlagen' mit dem Standardpfad als Kontext geliefert wird.""" pruefer = Dateipruefer( pfad="", standarddatei="/tmp/std.txt" @@ -58,6 +61,7 @@ class TestDateipruefer(unittest.TestCase): # 4. Temporäre Datei erlaubt # ----------------------------------------------------- def test_temporaer_erlaubt(self): + """Prüft, dass eine leere Pfadangabe bei temporaer_erlaubt=True als 'temporaer_erlaubt' ohne Kontext gemeldet wird.""" pruefer = Dateipruefer( pfad="", temporaer_erlaubt=True @@ -74,6 +78,7 @@ class TestDateipruefer(unittest.TestCase): # ----------------------------------------------------- @patch("sn_basis.modules.Dateipruefer.file_exists", return_value=False) def test_datei_nicht_gefunden(self, mock_exists): + """Prüft, dass ein nicht existierender Dateipfad als 'datei_nicht_gefunden' mit dem Pfad als Kontext abgelehnt wird.""" pruefer = Dateipruefer( pfad="/tmp/nichtvorhanden.txt" ) @@ -89,6 +94,7 @@ class TestDateipruefer(unittest.TestCase): # ----------------------------------------------------- @patch("sn_basis.modules.Dateipruefer.file_exists", return_value=True) def test_datei_ok(self, mock_exists): + """Prüft, dass ein existierender Dateipfad als 'ok' mit dem Pfad als Kontext bestätigt wird.""" pruefer = Dateipruefer( pfad="/tmp/test.txt" ) diff --git a/tests/test_laenderkennung.py b/tests/test_laenderkennung.py index 4d914d1..f3f13d7 100644 --- a/tests/test_laenderkennung.py +++ b/tests/test_laenderkennung.py @@ -10,20 +10,25 @@ from sn_basis.functions.laenderkennung import get_laenderkennung, LAENDERKENNUNG class TestGetLaenderkennung(unittest.TestCase): def test_bekannter_praefix_gibt_kennung_zurueck(self): + """Prüft, dass der Präfix 'sn' die ALKIS-Länderkennung '14' für Sachsen liefert.""" self.assertEqual(get_laenderkennung("sn"), "14") def test_praefix_gross_klein_unabhaengig(self): + """Prüft, dass die Präfixsuche groß-/kleinschreibungsunabhängig ist.""" self.assertEqual(get_laenderkennung("SN"), "14") def test_unbekannter_praefix_wirft_keyerror(self): + """Prüft, dass ein unbekannter Präfix einen KeyError auslöst.""" with self.assertRaises(KeyError): get_laenderkennung("xx") def test_ohne_argument_wird_aus_aufrufendem_modul_abgeleitet(self): + """Prüft, dass ohne Argument der Präfix aus dem Modulnamen des Aufrufers abgeleitet wird.""" # __name__ dieses Testmoduls beginnt mit "sn_basis" -> Präfix "sn" self.assertEqual(get_laenderkennung(), "14") def test_mapping_enthaelt_sachsen(self): + """Prüft, dass die Mapping-Tabelle LAENDERKENNUNGEN einen Eintrag für Sachsen ('sn' -> '14') enthält.""" self.assertEqual(LAENDERKENNUNGEN.get("sn"), "14") diff --git a/tests/test_layerpruefer.py b/tests/test_layerpruefer.py index 9bff1ad..b4b3640 100644 --- a/tests/test_layerpruefer.py +++ b/tests/test_layerpruefer.py @@ -97,6 +97,7 @@ class TestLayerpruefer(unittest.TestCase): # ----------------------------------------------------- def test_layer_exists(self): + """Prüft, dass ein nicht vorhandener Layer als 'layer_nicht_gefunden' abgelehnt wird.""" layer = MockLayer(exists=False) pruefer = Layerpruefer(layer) ergebnis = pruefer.pruefe() @@ -104,6 +105,7 @@ class TestLayerpruefer(unittest.TestCase): self.assertEqual(ergebnis.aktion, "layer_nicht_gefunden") def test_layer_unsichtbar(self): + """Prüft, dass ein unsichtbarer Layer bei geforderter Sichtbarkeit als 'layer_unsichtbar' abgelehnt wird.""" layer = MockLayer(visible=False) pruefer = Layerpruefer(layer, muss_sichtbar_sein=True) ergebnis = pruefer.pruefe() @@ -111,6 +113,7 @@ class TestLayerpruefer(unittest.TestCase): self.assertEqual(ergebnis.aktion, "layer_unsichtbar") def test_falscher_layertyp(self): + """Prüft, dass ein Layer mit abweichendem Layertyp (Raster statt Vektor) als 'falscher_layertyp' abgelehnt wird.""" layer = MockLayer(layer_type="raster") pruefer = Layerpruefer(layer, erwarteter_layertyp="vector") ergebnis = pruefer.pruefe() @@ -118,6 +121,7 @@ class TestLayerpruefer(unittest.TestCase): self.assertEqual(ergebnis.aktion, "falscher_layertyp") def test_falscher_geotyp(self): + """Prüft, dass ein Layer mit abweichendem Geometrietyp (Punkt statt Polygon) als 'falscher_geotyp' abgelehnt wird.""" layer = MockLayer(geometry_type="Point") pruefer = Layerpruefer(layer, erwarteter_geotyp="Polygon") ergebnis = pruefer.pruefe() @@ -125,6 +129,7 @@ class TestLayerpruefer(unittest.TestCase): self.assertEqual(ergebnis.aktion, "falscher_geotyp") def test_layer_leer(self): + """Prüft, dass ein Layer ohne Features als 'layer_leer' abgelehnt wird.""" layer = MockLayer(feature_count=0) pruefer = Layerpruefer(layer) ergebnis = pruefer.pruefe() @@ -132,6 +137,7 @@ class TestLayerpruefer(unittest.TestCase): self.assertEqual(ergebnis.aktion, "layer_leer") def test_falsches_crs(self): + """Prüft, dass ein Layer mit abweichendem Koordinatenbezugssystem als 'falsches_crs' abgelehnt wird.""" layer = MockLayer(crs="EPSG:4326") pruefer = Layerpruefer(layer, erwartetes_crs="EPSG:25833") ergebnis = pruefer.pruefe() @@ -139,6 +145,7 @@ class TestLayerpruefer(unittest.TestCase): self.assertEqual(ergebnis.aktion, "falsches_crs") def test_felder_fehlen(self): + """Prüft, dass ein Layer mit fehlenden Pflichtfeldern als 'felder_fehlen' abgelehnt wird.""" layer = MockLayer(fields=["id"]) pruefer = Layerpruefer(layer, erforderliche_felder=["id", "name"]) ergebnis = pruefer.pruefe() @@ -146,6 +153,7 @@ class TestLayerpruefer(unittest.TestCase): self.assertEqual(ergebnis.aktion, "felder_fehlen") def test_datenquelle_unerwartet(self): + """Prüft, dass eine Datenquelle außerhalb der erlaubten Liste als 'datenquelle_unerwartet' abgelehnt wird.""" layer = MockLayer(source="/tmp/test.shp") pruefer = Layerpruefer(layer, erlaubte_datenquellen=["/tmp/allowed.shp"]) ergebnis = pruefer.pruefe() @@ -153,6 +161,7 @@ class TestLayerpruefer(unittest.TestCase): self.assertEqual(ergebnis.aktion, "datenquelle_unerwartet") def test_layer_nicht_editierbar(self): + """Prüft, dass ein nicht editierbarer Layer bei geforderter Editierbarkeit als 'layer_nicht_editierbar' abgelehnt wird.""" layer = MockLayer(editable=False) pruefer = Layerpruefer(layer, muss_editierbar_sein=True) ergebnis = pruefer.pruefe() @@ -160,6 +169,7 @@ class TestLayerpruefer(unittest.TestCase): self.assertEqual(ergebnis.aktion, "layer_nicht_editierbar") def test_layer_ok(self): + """Prüft, dass ein Layer, der alle Anforderungen erfüllt, als 'ok' bestätigt wird.""" layer = MockLayer() pruefer = Layerpruefer(layer) ergebnis = pruefer.pruefe() diff --git a/tests/test_linkpruefer.py b/tests/test_linkpruefer.py index 07c0fff..42072a3 100644 --- a/tests/test_linkpruefer.py +++ b/tests/test_linkpruefer.py @@ -15,6 +15,7 @@ class TestLinkpruefer(unittest.TestCase): # ----------------------------------------------------- @patch("sn_basis.modules.linkpruefer.network_head") def test_remote_link_ok(self, mock_head): + """Prüft, dass eine erreichbare Remote-URL (HTTP HEAD ohne Fehler) als 'ok' bestätigt wird.""" mock_head.return_value = NetworkReply(error=0) lp = Linkpruefer() @@ -29,6 +30,7 @@ class TestLinkpruefer(unittest.TestCase): # ----------------------------------------------------- @patch("sn_basis.modules.linkpruefer.network_head") def test_remote_link_error(self, mock_head): + """Prüft, dass eine Remote-URL mit Fehlerantwort als 'url_nicht_erreichbar' abgelehnt wird.""" mock_head.return_value = NetworkReply(error=1) lp = Linkpruefer() @@ -43,6 +45,7 @@ class TestLinkpruefer(unittest.TestCase): # ----------------------------------------------------- @patch("sn_basis.modules.linkpruefer.network_head", return_value=None) def test_remote_link_network_error(self, mock_head): + """Prüft, dass eine ausbleibende Netzwerkantwort (None) als 'netzwerkfehler' gemeldet wird.""" lp = Linkpruefer() result = lp.pruefe("http://example.com") @@ -55,6 +58,7 @@ class TestLinkpruefer(unittest.TestCase): # ----------------------------------------------------- @patch("sn_basis.modules.linkpruefer.file_exists", return_value=False) def test_local_link_not_found(self, mock_exists): + """Prüft, dass ein nicht existierender lokaler Pfad als 'pfad_nicht_gefunden' abgelehnt wird.""" lp = Linkpruefer() result = lp.pruefe("/path/to/missing/file.shp") @@ -67,6 +71,7 @@ class TestLinkpruefer(unittest.TestCase): # ----------------------------------------------------- @patch("sn_basis.modules.linkpruefer.file_exists", return_value=True) def test_local_link_ok(self, mock_exists): + """Prüft, dass ein existierender lokaler Pfad als 'ok' bestätigt wird.""" lp = Linkpruefer() result = lp.pruefe("/path/to/file.shp") diff --git a/tests/test_print_layout.py b/tests/test_print_layout.py index 608468e..6ccc505 100644 --- a/tests/test_print_layout.py +++ b/tests/test_print_layout.py @@ -54,6 +54,7 @@ class _FakeLegendForResize: class TestPrintLayout(unittest.TestCase): def test_create_legend_item_links_map_and_enables_map_filtering(self): + """Prüft, dass eine erzeugte Legende mit der übergebenen Karte verknüpft ist und automatisch nach deren Sichtbarkeit gefiltert wird.""" project = QgsProject.instance() print_layout = PrintLayout(project=project) layout = QgsPrintLayout(project) @@ -74,6 +75,7 @@ class TestPrintLayout(unittest.TestCase): self.assertTrue(legend.legend_filter_by_map_enabled) def test_create_legend_item_does_not_copy_project_layers_into_legend_model(self): + """Prüft, dass eine neu erzeugte Legende keine Projekt-Layer in ihr Legendenmodell übernimmt (leere Root-Gruppe).""" project = QgsProject.instance() print_layout = PrintLayout(project=project) layout = QgsPrintLayout(project) @@ -91,6 +93,7 @@ class TestPrintLayout(unittest.TestCase): self.assertEqual(root_group.layers, []) def test_configure_legend_size_uses_content_adaptive_size(self): + """Prüft, dass die Legendengröße inhaltsadaptiv bestimmt wird (kein manuelles Resize) und die ermittelte Höhe zurückgegeben wird.""" project = QgsProject.instance() print_layout = PrintLayout(project=project) legend = _FakeLegendForResize() @@ -107,6 +110,7 @@ class TestPrintLayout(unittest.TestCase): self.assertEqual(height, 33.0) def test_configure_hauptkarte_grids_uses_wrapper_constants(self): + """Prüft, dass das Gitternetz der Hauptkarte mit den erwarteten Stil-, Rahmen- und Beschriftungskonstanten (nur rechts/unten beschriftet, Schriftgröße und Hintergrund) konfiguriert wird.""" project = QgsProject.instance() print_layout = PrintLayout(project=project) layout = QgsPrintLayout(project) @@ -153,6 +157,7 @@ class TestPrintLayout(unittest.TestCase): @patch("sn_basis.modules.print_layout.open_layout_designer") def test_create_single_page_layout_keeps_legend_linked_to_hauptkarte_and_theme(self, _mock_open_designer): + """Prüft, dass ein einseitiges Layout die Hauptkarte auf das übergebene Kartenthema festlegt und die Legende mit dieser Karte verknüpft bleibt.""" project = QgsProject.instance() print_layout = PrintLayout(project=project) diff --git a/tests/test_print_logic.py b/tests/test_print_logic.py index a6c787a..29feb3c 100644 --- a/tests/test_print_logic.py +++ b/tests/test_print_logic.py @@ -38,6 +38,7 @@ class TestPrintLogic(unittest.TestCase): self.logic = PrintLogic(pruefmanager=MagicMock()) def test_get_baufreigabe_page_dimensions_prefers_a4_for_small_extent(self): + """Prüft, dass für einen kleinen Kartenausschnitt (Baufreigabe) das Format DIN A4 ohne Fallback gewählt wird.""" din_format, page_w, page_h, map_w, map_h, fallback = self.logic._get_baufreigabe_page_dimensions(80.0, 120.0) self.assertEqual(din_format, "DIN A4") @@ -46,6 +47,7 @@ class TestPrintLogic(unittest.TestCase): self.assertFalse(fallback) def test_get_baufreigabe_page_dimensions_escalates_to_a3(self): + """Prüft, dass ein größerer Kartenausschnitt (Baufreigabe) auf DIN A3 eskaliert wird.""" din_format, page_w, page_h, map_w, map_h, fallback = self.logic._get_baufreigabe_page_dimensions(200.0, 180.0) self.assertEqual(din_format, "DIN A3") @@ -54,6 +56,7 @@ class TestPrintLogic(unittest.TestCase): self.assertFalse(fallback) def test_get_baufreigabe_page_dimensions_respects_a4_as_maximum_with_fallback(self): + """Prüft, dass bei auf DIN A4 begrenztem Höchstformat ein eigentlich A3-großer Ausschnitt mit Fallback-Kennzeichnung auf A4 reduziert wird.""" din_format, page_w, page_h, map_w, map_h, fallback = self.logic._get_baufreigabe_page_dimensions( 200.0, 180.0, @@ -66,6 +69,7 @@ class TestPrintLogic(unittest.TestCase): self.assertTrue(fallback) def test_get_baufreigabe_page_dimensions_falls_back_to_a3_for_oversize_extent(self): + """Prüft, dass ein Ausschnitt, der auch DIN A3 übersteigt, mit Fallback-Kennzeichnung auf DIN A3 begrenzt wird.""" din_format, page_w, page_h, map_w, map_h, fallback = self.logic._get_baufreigabe_page_dimensions(400.0, 300.0) self.assertEqual(din_format, "DIN A3") @@ -74,21 +78,25 @@ class TestPrintLogic(unittest.TestCase): self.assertTrue(fallback) def test_select_standard_page_layout_uses_a4_as_minimum_sheet(self): + """Prüft, dass für einen kleinen Ausschnitt trotz Höchstgrenze DIN A3 mindestens DIN A4 als Blattgröße gewählt wird.""" selected = self.logic._select_standard_page_layout(60.0, 100.0, max_format="DIN A3") self.assertEqual(selected, (297.0, 210.0, 87.0, 190.0)) def test_select_standard_page_layout_limits_hauptkarte_to_a3(self): + """Prüft, dass ein die Fläche voll ausnutzender Ausschnitt auf DIN A3 als größtes zulässiges Format begrenzt wird.""" selected = self.logic._select_standard_page_layout(120.0, 240.0, max_format="DIN A3") self.assertEqual(selected, (420.0, 297.0, 210.0, 277.0)) def test_select_standard_page_layout_returns_none_if_a3_is_too_small(self): + """Prüft, dass kein Layout gewählt wird (None), wenn der Ausschnitt selbst DIN A3 als Höchstformat übersteigt.""" selected = self.logic._select_standard_page_layout(260.0, 280.0, max_format="DIN A3") self.assertIsNone(selected) def test_get_standard_layout_dimensions_uses_a4_and_forces_fit_for_small_extent(self): + """Prüft, dass für einen kleinen Ausschnitt DIN A4 gewählt und das Einpassen (force_fit) erzwungen wird.""" page_w, page_h, map_w, map_h, force_fit = self.logic._get_standard_layout_dimensions( 60.0, 100.0, @@ -101,6 +109,7 @@ class TestPrintLogic(unittest.TestCase): self.assertTrue(force_fit) def test_get_standard_layout_dimensions_caps_endlosrolle_width_at_2000_mm(self): + """Prüft, dass bei aktiviertem Formfaktor (Endlosrolle) die Seitenbreite auf die maximale Rollenbreite (2000 mm) begrenzt wird.""" page_w, page_h, map_w, map_h, force_fit = self.logic._get_standard_layout_dimensions( 2500.0, 100.0, @@ -114,6 +123,7 @@ class TestPrintLogic(unittest.TestCase): self.assertTrue(force_fit) def test_apply_standard_minimum_a4_fallback_for_small_page(self): + """Prüft, dass eine zu kleine Seite auf die A4-Mindestgröße angehoben und als erzwungen (forced) markiert wird.""" page_w, page_h, map_w, map_h, forced = self.logic._apply_standard_minimum_a4_fallback( 250.0, 180.0, @@ -126,6 +136,7 @@ class TestPrintLogic(unittest.TestCase): self.assertEqual((map_w, map_h), (87.0, 190.0)) def test_apply_standard_minimum_a4_fallback_keeps_large_page(self): + """Prüft, dass eine bereits ausreichend große Seite (A3) unverändert bleibt und nicht als erzwungen markiert wird.""" page_w, page_h, map_w, map_h, forced = self.logic._apply_standard_minimum_a4_fallback( 420.0, 297.0, @@ -138,23 +149,27 @@ class TestPrintLogic(unittest.TestCase): self.assertEqual((map_w, map_h), (210.0, 277.0)) def test_does_plot_fit_page_true_for_standard_a4(self): + """Prüft, dass ein Kartenobjekt, das in eine DIN A4-Seite passt, als passend erkannt wird.""" fits = self.logic._does_plot_fit_page(297.0, 210.0, 87.0, 190.0, 210.0, 20.0) self.assertTrue(fits) def test_does_plot_fit_page_false_if_objects_exceed_page(self): + """Prüft, dass ein Kartenobjekt, das die Seitenbreite überschreitet, als nicht passend erkannt wird.""" fits = self.logic._does_plot_fit_page(297.0, 210.0, 120.0, 190.0, 210.0, 20.0) self.assertFalse(fits) @patch("sn_basis.modules.print_logic.set_variable") def test_set_druckbereich_accepts_wie_kartenfenster(self, mock_set_variable): + """Prüft, dass die Auswahl 'wie Kartenfenster' als Projektvariable 'druckbereich' gespeichert wird.""" self.logic.set_druckbereich_for_auswahl(DRUCKBEREICH_WIE_KARTENFENSTER) mock_set_variable.assert_called_once_with("druckbereich", DRUCKBEREICH_WIE_KARTENFENSTER, scope="project") @patch("sn_basis.modules.print_logic.iface") def test_get_canvas_extent_returns_valid_extent(self, mock_iface): + """Prüft, dass der aktuelle Kartenausschnitt des Kartenfensters unverändert zurückgegeben wird.""" extent = _FakeExtent(120.0, 90.0) mock_iface.mapCanvas.return_value = _FakeCanvas(extent) @@ -165,6 +180,7 @@ class TestPrintLogic(unittest.TestCase): @patch.object(PrintLogic, "_buffer_extent") @patch.object(PrintLogic, "_get_canvas_extent") def test_resolve_extent_uses_canvas_extent_without_buffer(self, mock_get_canvas_extent, mock_buffer_extent): + """Prüft, dass bei Druckbereich 'wie Kartenfenster' der Kartenausschnitt ohne Puffer und ohne verknüpften Layer übernommen wird.""" extent = _FakeExtent(120.0, 90.0) mock_get_canvas_extent.return_value = extent @@ -177,6 +193,7 @@ class TestPrintLogic(unittest.TestCase): @patch.object(PrintLogic, "_buffer_extent") @patch.object(PrintLogic, "_get_druckrechteck_extent") def test_resolve_extent_uses_rectangle_extent_without_buffer(self, mock_get_rect_extent, mock_buffer_extent): + """Prüft, dass bei Druckbereich 'Rechteck' der gezeichnete Ausschnitt ohne Puffer und ohne verknüpften Layer übernommen wird.""" extent = _FakeExtent(120.0, 90.0) mock_get_rect_extent.return_value = extent diff --git a/tests/test_pruefmanager.py b/tests/test_pruefmanager.py index 7ef8433..3e542fc 100644 --- a/tests/test_pruefmanager.py +++ b/tests/test_pruefmanager.py @@ -16,6 +16,7 @@ class TestPruefmanager(unittest.TestCase): # 1. OK-Ergebnis → keine Interaktion # ----------------------------------------------------- def test_ok(self): + """Prüft, dass ein bereits erfolgreiches Prüfergebnis ohne Nutzerinteraktion als 'ok' durchgereicht wird.""" ergebnis = pruef_ergebnis(True, "Alles gut", "ok", None) entscheidung = self.manager.verarbeite(ergebnis) @@ -27,6 +28,7 @@ class TestPruefmanager(unittest.TestCase): # ----------------------------------------------------- @patch("sn_basis.modules.Pruefmanager.ask_yes_no", return_value=True) def test_leereingabe_erlaubt_ja(self, mock_ask): + """Prüft, dass bei erlaubter leerer Eingabe eine Ja-Antwort des Nutzers die Entscheidung 'ok' liefert.""" ergebnis = pruef_ergebnis(False, "Leer?", "leereingabe_erlaubt", None) entscheidung = self.manager.verarbeite(ergebnis) @@ -38,6 +40,7 @@ class TestPruefmanager(unittest.TestCase): # ----------------------------------------------------- @patch("sn_basis.modules.Pruefmanager.ask_yes_no", return_value=False) def test_leereingabe_erlaubt_nein(self, mock_ask): + """Prüft, dass bei erlaubter leerer Eingabe eine Nein-Antwort die Aktion 'leereingabe_erlaubt' als abgelehnt bestehen lässt.""" ergebnis = pruef_ergebnis(False, "Leer?", "leereingabe_erlaubt", None) entscheidung = self.manager.verarbeite(ergebnis) @@ -49,6 +52,7 @@ class TestPruefmanager(unittest.TestCase): # ----------------------------------------------------- @patch("sn_basis.modules.Pruefmanager.ask_yes_no", return_value=True) def test_standarddatei_vorschlagen_ja(self, mock_ask): + """Prüft, dass eine Ja-Antwort auf den Vorschlag der Standarddatei die Entscheidung 'ok' mit dem Standardpfad als Kontext liefert.""" ergebnis = pruef_ergebnis( False, "Standarddatei verwenden?", @@ -67,6 +71,7 @@ class TestPruefmanager(unittest.TestCase): # ----------------------------------------------------- @patch("sn_basis.modules.Pruefmanager.ask_yes_no", return_value=False) def test_standarddatei_vorschlagen_nein(self, mock_ask): + """Prüft, dass eine Nein-Antwort auf den Vorschlag der Standarddatei die Aktion 'standarddatei_vorschlagen' als abgelehnt bestehen lässt.""" ergebnis = pruef_ergebnis( False, "Standarddatei verwenden?", @@ -84,6 +89,7 @@ class TestPruefmanager(unittest.TestCase): # ----------------------------------------------------- @patch("sn_basis.modules.Pruefmanager.ask_yes_no", return_value=True) def test_temporaer_erlaubt_ja(self, mock_ask): + """Prüft, dass eine Ja-Antwort auf die Rückfrage nach einer temporären Datei die Aktion 'temporaer_erzeugen' auslöst.""" ergebnis = pruef_ergebnis(False, "Temporär?", "temporaer_erlaubt", None) entscheidung = self.manager.verarbeite(ergebnis) @@ -95,6 +101,7 @@ class TestPruefmanager(unittest.TestCase): # ----------------------------------------------------- @patch("sn_basis.modules.Pruefmanager.ask_yes_no", return_value=False) def test_temporaer_erlaubt_nein(self, mock_ask): + """Prüft, dass eine Nein-Antwort auf die Rückfrage nach einer temporären Datei die Aktion 'temporaer_erlaubt' als abgelehnt bestehen lässt.""" ergebnis = pruef_ergebnis(False, "Temporär?", "temporaer_erlaubt", None) entscheidung = self.manager.verarbeite(ergebnis) @@ -107,6 +114,7 @@ class TestPruefmanager(unittest.TestCase): @patch("sn_basis.modules.Pruefmanager.ask_yes_no", return_value=True) @patch("sn_basis.modules.Pruefmanager.set_layer_visible") def test_layer_unsichtbar_ja(self, mock_set, mock_ask): + """Prüft, dass eine Ja-Antwort bei unsichtbarem Layer den Layer sichtbar schaltet und die Entscheidung 'ok' liefert.""" fake_layer = object() ergebnis = pruef_ergebnis(False, "Layer unsichtbar", "layer_unsichtbar", fake_layer) @@ -121,6 +129,7 @@ class TestPruefmanager(unittest.TestCase): # ----------------------------------------------------- @patch("sn_basis.modules.Pruefmanager.ask_yes_no", return_value=False) def test_layer_unsichtbar_nein(self, mock_ask): + """Prüft, dass eine Nein-Antwort bei unsichtbarem Layer die Aktion 'layer_unsichtbar' als abgelehnt bestehen lässt.""" fake_layer = object() ergebnis = pruef_ergebnis(False, "Layer unsichtbar", "layer_unsichtbar", fake_layer) @@ -134,6 +143,7 @@ class TestPruefmanager(unittest.TestCase): # ----------------------------------------------------- @patch("sn_basis.modules.Pruefmanager.warning") def test_unbekannte_aktion(self, mock_warn): + """Prüft, dass eine unbekannte Aktion eine Warnung auslöst und unverarbeitet als Fehlschlag zurückgegeben wird.""" ergebnis = pruef_ergebnis(False, "???", "unbekannt", None) entscheidung = self.manager.verarbeite(ergebnis) @@ -143,6 +153,7 @@ class TestPruefmanager(unittest.TestCase): @patch("sn_basis.modules.Pruefmanager.ask_overwrite_append_cancel_custom", return_value="overwrite") def test_datei_existiert_overwrite(self, _mock_choice): + """Prüft, dass die Nutzerwahl 'überschreiben' bei bestehender Datei zur Aktion 'datei_existiert_ueberschreiben' führt.""" ergebnis = pruef_ergebnis(False, "Datei existiert", "datei_existiert", "C:/tmp/v.gpkg") entscheidung = self.manager.verarbeite(ergebnis) @@ -152,6 +163,7 @@ class TestPruefmanager(unittest.TestCase): @patch("sn_basis.modules.Pruefmanager.ask_overwrite_append_cancel_custom", return_value="append") def test_datei_existiert_append(self, _mock_choice): + """Prüft, dass die Nutzerwahl 'anhängen' bei bestehender Datei zur Aktion 'datei_existiert_anhaengen' führt.""" ergebnis = pruef_ergebnis(False, "Datei existiert", "datei_existiert", "C:/tmp/v.gpkg") entscheidung = self.manager.verarbeite(ergebnis) @@ -160,6 +172,7 @@ class TestPruefmanager(unittest.TestCase): @patch("sn_basis.modules.Pruefmanager.ask_overwrite_append_cancel_custom", return_value="cancel") def test_datei_existiert_cancel(self, _mock_choice): + """Prüft, dass die Nutzerwahl 'abbrechen' bei bestehender Datei zur Aktion 'datei_existiert_ueberspringen' führt.""" ergebnis = pruef_ergebnis(False, "Datei existiert", "datei_existiert", "C:/tmp/v.gpkg") entscheidung = self.manager.verarbeite(ergebnis) @@ -167,6 +180,7 @@ class TestPruefmanager(unittest.TestCase): self.assertEqual(entscheidung.aktion, "datei_existiert_ueberspringen") def test_datei_existiert_in_non_qgis_mode_returns_input(self): + """Prüft, dass außerhalb des QGIS-Modus bei bestehender Datei keine Rückfrage erfolgt, sondern die ursprüngliche Aktion unentschieden zurückgegeben wird.""" manager = Pruefmanager(ui_modus="test") ergebnis = pruef_ergebnis(False, "Datei existiert", "datei_existiert", "C:/tmp/v.gpkg") diff --git a/tests/test_settings_logic.py b/tests/test_settings_logic.py index 6a8fd64..a7392e8 100644 --- a/tests/test_settings_logic.py +++ b/tests/test_settings_logic.py @@ -13,6 +13,7 @@ class TestSettingsLogic(unittest.TestCase): # ----------------------------------------------------- @patch("sn_basis.functions.settings_logic.get_variable") def test_load(self, mock_get): + """Prüft, dass load() jede bekannte Projektvariable genau einmal über get_variable() liest.""" # Mock-Rückgabe für jede Variable mock_get.side_effect = lambda key, scope="project": f"wert_{key}" @@ -32,6 +33,7 @@ class TestSettingsLogic(unittest.TestCase): # ----------------------------------------------------- @patch("sn_basis.functions.settings_logic.set_variable") def test_save(self, mock_set): + """Prüft, dass save() nur bekannte Variablen-Keys speichert und unbekannte Keys ignoriert.""" logic = SettingsLogic() # Eingabedaten enthalten gültige und ungültige Keys @@ -57,6 +59,7 @@ class TestSettingsLogic(unittest.TestCase): @patch("sn_basis.functions.settings_logic.get_variable") def test_load_handles_partial_values_with_empty_fallback(self, mock_get): + """Prüft, dass load() bei fehlenden Werten auf einen leeren String zurückfällt statt einen Fehler zu werfen.""" values = { "amt": "A1", "behoerde": "", @@ -74,6 +77,7 @@ class TestSettingsLogic(unittest.TestCase): @patch("sn_basis.functions.settings_logic.set_variable") def test_save_empty_string_value_is_persisted(self, mock_set): + """Prüft, dass save() einen leeren String als gültigen Wert speichert, statt ihn wie einen fehlenden Key zu behandeln.""" logic = SettingsLogic() logic.save({"amt": "", "behoerde": "B2"}) diff --git a/tests/test_stilpruefer.py b/tests/test_stilpruefer.py index 06c2fca..ed11b22 100644 --- a/tests/test_stilpruefer.py +++ b/tests/test_stilpruefer.py @@ -18,6 +18,7 @@ class TestStilpruefer(unittest.TestCase): # 1. Keine Datei angegeben # ----------------------------------------------------- def test_keine_datei_angegeben(self): + """Prüft, dass eine leere Pfadangabe als 'ok' ohne Kontext akzeptiert wird (Stil ist optional).""" result = self.pruefer.pruefe("") self.assertTrue(result.ok) @@ -30,6 +31,7 @@ class TestStilpruefer(unittest.TestCase): # ----------------------------------------------------- @patch("sn_basis.modules.stilpruefer.file_exists", return_value=True) def test_datei_existiert_mit_qml(self, mock_exists): + """Prüft, dass eine existierende .qml-Datei als 'stil_anwendbar' bestätigt wird.""" with tempfile.NamedTemporaryFile(suffix=".qml", delete=False) as tmp: tmp_path = tmp.name @@ -48,6 +50,7 @@ class TestStilpruefer(unittest.TestCase): # ----------------------------------------------------- @patch("sn_basis.modules.stilpruefer.file_exists", return_value=True) def test_datei_existiert_falsche_endung(self, mock_exists): + """Prüft, dass eine existierende Datei ohne .qml-Endung als 'falsche_endung' abgelehnt wird.""" with tempfile.NamedTemporaryFile(suffix=".txt", delete=False) as tmp: tmp_path = tmp.name @@ -67,6 +70,7 @@ class TestStilpruefer(unittest.TestCase): # ----------------------------------------------------- @patch("sn_basis.modules.stilpruefer.file_exists", return_value=False) def test_datei_existiert_nicht(self, mock_exists): + """Prüft, dass ein nicht existierender .qml-Pfad als 'datei_nicht_gefunden' abgelehnt wird.""" fake_path = "/tmp/nichtvorhanden.qml" result = self.pruefer.pruefe(fake_path) diff --git a/tests/test_variable_wrapper.py b/tests/test_variable_wrapper.py index e9a1379..5da00e2 100644 --- a/tests/test_variable_wrapper.py +++ b/tests/test_variable_wrapper.py @@ -23,6 +23,7 @@ class TestVariableWrapper(unittest.TestCase): mock_set_project_variable, mock_project_instance, ): + """Prüft, dass set_variable() im Projekt-Scope nicht schreibt, wenn der neue Wert dem bestehenden entspricht.""" mock_project_instance.return_value = object() mock_project_scope.return_value = _Scope("layer_1") @@ -39,6 +40,7 @@ class TestVariableWrapper(unittest.TestCase): mock_set_project_variable, mock_project_instance, ): + """Prüft, dass set_variable() im Projekt-Scope bei geändertem Wert mit dem Präfix 'sn_' geschrieben wird.""" fake_project = object() mock_project_instance.return_value = fake_project mock_project_scope.return_value = _Scope("old_value") @@ -53,12 +55,14 @@ class TestVariableWrapper(unittest.TestCase): @patch("sn_basis.functions.variable_wrapper.QgsExpressionContextUtils.setGlobalVariable") def test_set_variable_global_writes_prefixed_name(self, mock_set_global): + """Prüft, dass set_variable() im globalen Scope den Variablennamen mit 'sn_' vorangestellt schreibt.""" variable_wrapper.set_variable("verfahrensnummer", "123", scope="global") mock_set_global.assert_called_once_with("sn_verfahrensnummer", "123") @patch("sn_basis.functions.variable_wrapper.QgsExpressionContextUtils.globalScope") def test_get_variable_global_returns_empty_string_fallback(self, mock_global_scope): + """Prüft, dass get_variable() im globalen Scope für eine nicht gesetzte Variable einen leeren String liefert.""" mock_global_scope.return_value = _Scope("") value = variable_wrapper.get_variable("nicht_vorhanden", scope="global") @@ -66,10 +70,12 @@ class TestVariableWrapper(unittest.TestCase): self.assertEqual(value, "") def test_get_variable_invalid_scope_raises(self): + """Prüft, dass get_variable() bei einem unbekannten Scope-Namen einen ValueError auslöst.""" with self.assertRaises(ValueError): variable_wrapper.get_variable("foo", scope="invalid") def test_set_variable_invalid_scope_raises(self): + """Prüft, dass set_variable() bei einem unbekannten Scope-Namen einen ValueError auslöst.""" with self.assertRaises(ValueError): variable_wrapper.set_variable("foo", "bar", scope="invalid") diff --git a/tests/test_verfahrensgebiet_manager.py b/tests/test_verfahrensgebiet_manager.py index ebb43fb..44b4dec 100644 --- a/tests/test_verfahrensgebiet_manager.py +++ b/tests/test_verfahrensgebiet_manager.py @@ -16,18 +16,21 @@ class TestVerfahrensgebietManager(unittest.TestCase): @patch("sn_basis.functions.verfahrensgebiet_manager.get_variable", return_value="layer_123") def test_get_verfahrensgebiet_layer_id_returns_value(self, _mock_get_variable): + """Prüft, dass get_verfahrensgebiet_layer_id() die in der Projektvariable gespeicherte Layer-ID liefert.""" result = verfahrensgebiet_manager.get_verfahrensgebiet_layer_id() self.assertEqual(result, "layer_123") @patch("sn_basis.functions.verfahrensgebiet_manager.get_variable", return_value="") def test_get_verfahrensgebiet_layer_id_returns_none_for_empty_value(self, _mock_get_variable): + """Prüft, dass get_verfahrensgebiet_layer_id() bei leerer Projektvariable None statt eines leeren Strings liefert.""" result = verfahrensgebiet_manager.get_verfahrensgebiet_layer_id() self.assertIsNone(result) @patch("sn_basis.functions.verfahrensgebiet_manager.set_variable") def test_set_verfahrensgebiet_layer_id_writes_project_variable(self, mock_set_variable): + """Prüft, dass set_verfahrensgebiet_layer_id() die Layer-ID als Projektvariable 'verfahrensgebiet_layer' speichert.""" verfahrensgebiet_manager.set_verfahrensgebiet_layer_id("layer_abc") mock_set_variable.assert_called_once_with("verfahrensgebiet_layer", "layer_abc", scope="project") @@ -43,6 +46,7 @@ class TestVerfahrensgebietManager(unittest.TestCase): mock_project_instance, mock_find_layer, ): + """Prüft, dass ohne gefundenen Verfahrensgebiet-Layer keine Schreibaktion erfolgt, wenn die Variable bereits leer ist.""" mock_find_layer.return_value = (None, None) mock_project_instance.return_value = object() mock_project_scope.return_value = _Scope("") @@ -55,6 +59,7 @@ class TestVerfahrensgebietManager(unittest.TestCase): @patch("sn_basis.functions.verfahrensgebiet_manager._find_verfahrensgebiet_layer") @patch("sn_basis.functions.verfahrensgebiet_manager.set_variable") def test_update_with_layer_writes_variable(self, mock_set_variable, mock_find_layer): + """Prüft, dass ein gefundener Verfahrensgebiet-Layer seine ID als Projektvariable speichert.""" mock_layer = object() mock_find_layer.return_value = (mock_layer, "layer_99")