From 3f985ce2096b060e62483836ba3d426ca79c3929 Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 18 Sep 2026 11:20:37 +0200 Subject: [PATCH] =?UTF-8?q?Testkatalog=20neu=20erzeugt,=20Wissensbasis=20f?= =?UTF-8?q?=C3=BCr=20Basis=20#65=20nachgezogen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sn_basis: 244 -> 249 Testfälle. fallstricke.md: _MockQDockWidget ohne closeEvent(), zwei bestätigte Testkatalog-Fehlalarme (toter Code in Pruefmanager._ask_use_or_replace_pufferlayer, Issue #60) sowie das Muster Klasse.__new__(Klasse) für UI-Klassen, die im Mock nicht konstruierbar sind. modulkarte.md an aktuelle Testdateizahl angepasst. Co-Authored-By: Claude Sonnet 5 --- docs/architektur/modulkarte.md | 2 +- docs/tests/testkatalog.html | 371 +++++++++++++++++++++++++++------ docs/tests/testkatalog.md | 312 +++++++++++++++++++-------- docs/wissen/fallstricke.md | 13 ++ 4 files changed, 542 insertions(+), 156 deletions(-) diff --git a/docs/architektur/modulkarte.md b/docs/architektur/modulkarte.md index ec64b16..58f69d4 100644 --- a/docs/architektur/modulkarte.md +++ b/docs/architektur/modulkarte.md @@ -63,7 +63,7 @@ Legende: ⚠ = über 600 Zeilen, nie komplett laden, per `grep -n "def "` navigi | Pfad | Zweck | |---|---| -| `tests/` | 19 Testdateien, `unittest`, Mock-Modus; `run_tests.py` (farbiger Runner), `test_qgis.bat` (Coverage in OSGeo4W) | +| `tests/` | 29 Testdateien, `unittest`, Mock-Modus; `run_tests.py` (farbiger Runner), `test_qgis.bat` (Coverage in OSGeo4W) | | `styles/` | QML-Stile (Verfahrensgebiet, LSG, Denkmalschutz, Flurstücksbeschriftung) | | `data/landkreise.json` | Landkreise mit Kennzahl | | `assets/plan-qgis340ExitCrashFix.prompt.md` | KI-Planungsnotiz zum Exit-Crash (historisch) | diff --git a/docs/tests/testkatalog.html b/docs/tests/testkatalog.html index f802bdf..6c22c40 100644 --- a/docs/tests/testkatalog.html +++ b/docs/tests/testkatalog.html @@ -121,22 +121,22 @@ Testkatalog der sn_*-Plugins — was die Suite heute prüft, auf einen Blick.
Quelle: docs/tests/testkatalog.md
Baseline: docs/status/testbaseline.json (SHA-256 aeabc946a7f3)
Prüf-Audit: docs/status/testpruefungen.json (SHA-256 68b590c8feef)
-
418Testfälle
-
375grün
+
501Testfälle
+
458grün
35rot (Baseline)
-
65%mit Docstring
-
13%aktuell geprüft
-
36Testdateien
-
55%ohne Testbezug
+
71%mit Docstring
+
11%aktuell geprüft
+
46Testdateien
+
46%ohne Testbezug
Verteilung je Paket
-
sn_basis19 Dateien · 166 Testfälle
+
sn_basis29 Dateien · 249 Testfälle
sn_verfahrensgebiet12 Dateien · 208 Testfälle
sn_plan415 Dateien · 44 Testfälle
@@ -153,13 +153,32 @@

sn_basis

-

Plattform-Plugin · Ordner Plugin_SN_Basis · 19 Testdateien · 166 Testfälle

+

Plattform-Plugin · Ordner Plugin_SN_Basis · 29 Testdateien · 249 Testfälle

- -

— (Docstring fehlt)

Keine Testfälle: Die Datei enthält keine unittest.TestCase-Klasse – sie ist eine reine Hilfsdatei, die beim Testlauf nur importiert wird.

— (Docstring fehlt)

TestDataGrabber 6
flowchart TD
+  

Tests für sn_basis/ui/base_dockwidget.py::closeEvent (Issue #65).

CloseEventTests 5
flowchart TD
+  root(["test_base_dockwidget.py"])
+  class root rootnode
+  root --> g1["CloseEventTests (5)"]
+  class g1 groupnode
+  g1 --> t1("ruft_cleanup_aller_tabs_auf")
+  g1 --> t2("ignoriert_tabs_ohne_cleanup")
+  g1 --> t3("fehler_in_cleanup_wird_abgefangen_und_andere_tabs_laufen_weiter")
+  g1 --> t4("setzt_toolbar_action_zurueck")
+  g1 --> t5("ohne_action_wird_nichts_zurueckgesetzt")
+  class t1 ok
+  class t2 ok
+  class t3 ok
+  class t4 ok
+  class t5 ok
+  classDef rootnode fill:#1f4038,stroke:#16302a,stroke-width:1px,color:#f4f1e8,font-weight:600;
+  classDef groupnode fill:#cfe0da,stroke:#5c8a7d,stroke-width:1px,color:#152420;
+  classDef ok fill:#dcefdc,stroke:#3f7d4a,stroke-width:1px,color:#1c3a20;
+  classDef warn fill:#f6ead9,stroke:#b5722a,stroke-width:1px,color:#4a2c08;
+  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
CloseEventTests
test_ruft_cleanup_aller_tabs_auf
Prüft, dass closeEvent cleanup() auf allen Tabs des Dock-Widgets aufruft.grünnie geprüft
CloseEventTests
test_ignoriert_tabs_ohne_cleanup
Prüft, dass ein Tab ohne cleanup()-Methode nicht zu einem Fehler führt.grünnie geprüft
CloseEventTests
test_fehler_in_cleanup_wird_abgefangen_und_andere_tabs_laufen_weiter
Prüft, dass ein Fehler in cleanup() eines Tabs nicht die übrigen Tabs verhindert.grünnie geprüft
CloseEventTests
test_setzt_toolbar_action_zurueck
Prüft, dass closeEvent die verknüpfte Toolbar-Action auf 'nicht gedrückt' zurücksetzt.grünnie geprüft
CloseEventTests
test_ohne_action_wird_nichts_zurueckgesetzt
Prüft, dass closeEvent ohne verknüpfte Toolbar-Action keine Ausnahme wirft.grünnie geprüft

— (Docstring fehlt)

Keine Testfälle: Die Datei enthält keine unittest.TestCase-Klasse – sie ist eine reine Hilfsdatei, die beim Testlauf nur importiert wird.

— (Docstring fehlt)

TestDataGrabber 6
flowchart TD
   root(["test_datagrabber.py"])
   class root rootnode
   root --> g1["TestDataGrabber (6)"]
@@ -180,10 +199,10 @@
   classDef groupnode fill:#cfe0da,stroke:#5c8a7d,stroke-width:1px,color:#152420;
   classDef ok fill:#dcefdc,stroke:#3f7d4a,stroke-width:1px,color:#1c3a20;
   classDef warn fill:#f6ead9,stroke:#b5722a,stroke-width:1px,color:#4a2c08;
-  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
TestDataGrabber
test_analyze_source_type_detects_excel
Prüft, dass eine erreichbare .xlsx-Datei als Quelltyp 'excel' erkannt wird.grüngeprüft am 2026-09-16
TestDataGrabber
test_analyze_source_type_returns_unknown_filetype
Prüft, dass eine erreichbare Datei mit unbekannter Endung als 'unbekannter_dateityp' eingestuft wird.grüngeprüft am 2026-09-16
TestDataGrabber
test_analyze_source_type_detects_service_when_file_check_fails
Prüft, dass eine Quelle als 'dienst' erkannt wird, wenn die Dateiprüfung fehlschlägt, die URL aber erreichbar ist.grüngeprüft am 2026-09-16
TestDataGrabber
test_analyze_source_type_returns_unbekannte_quelle_on_full_failure
Prüft, dass eine Quelle als 'unbekannte_quelle' eingestuft wird, wenn weder Datei- noch Linkprüfung erfolgreich sind.grüngeprüft am 2026-09-16
TestDataGrabber
test_run_returns_success_summary_with_valid_rows
Prüft, dass run() bei erfolgreichem Excel-Import eine Erfolgsmeldung mit den geladenen Zeilen liefert.grüngeprüft am 2026-09-16
TestDataGrabber
test_run_returns_failure_summary_without_rows
Prüft, dass run() bei nicht erkennbarer Quelle eine Fehlermeldung ohne Zeilen liefert.grüngeprüft am 2026-09-16

— (Docstring fehlt)

TestDateipruefer 6
flowchart TD
+  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
TestDataGrabber
test_analyze_source_type_detects_excel
Prüft, dass eine erreichbare .xlsx-Datei als Quelltyp 'excel' erkannt wird.grüngeprüft am 2026-09-16
TestDataGrabber
test_analyze_source_type_returns_unknown_filetype
Prüft, dass eine erreichbare Datei mit unbekannter Endung als 'unbekannter_dateityp' eingestuft wird.grüngeprüft am 2026-09-16
TestDataGrabber
test_analyze_source_type_detects_service_when_file_check_fails
Prüft, dass eine Quelle als 'dienst' erkannt wird, wenn die Dateiprüfung fehlschlägt, die URL aber erreichbar ist.grüngeprüft am 2026-09-16
TestDataGrabber
test_analyze_source_type_returns_unbekannte_quelle_on_full_failure
Prüft, dass eine Quelle als 'unbekannte_quelle' eingestuft wird, wenn weder Datei- noch Linkprüfung erfolgreich sind.grüngeprüft am 2026-09-16
TestDataGrabber
test_run_returns_success_summary_with_valid_rows
Prüft, dass run() bei erfolgreichem Excel-Import eine Erfolgsmeldung mit den geladenen Zeilen liefert.grüngeprüft am 2026-09-16
TestDataGrabber
test_run_returns_failure_summary_without_rows
Prüft, dass run() bei nicht erkennbarer Quelle eine Fehlermeldung ohne Zeilen liefert.grüngeprüft am 2026-09-16

— (Docstring fehlt)

TestDateipruefer 12
flowchart TD
   root(["test_dateipruefer.py"])
   class root rootnode
-  root --> g1["TestDateipruefer (6)"]
+  root --> g1["TestDateipruefer (12)"]
   class g1 groupnode
   g1 --> t1("leereingabe_erlaubt")
   g1 --> t2("leereingabe_nicht_erlaubt")
@@ -191,17 +210,29 @@
   g1 --> t4("temporaer_erlaubt")
   g1 --> t5("datei_nicht_gefunden")
   g1 --> t6("datei_ok")
+  g1 --> t7("erkenne_dateityp_unterscheidet_excel_datenbank_und_unbekannt")
+  g1 --> t8("pfad_verbindet_relativen_pfad_mit_basispfad")
+  g1 --> t9("pfad_laesst_absoluten_pfad_unveraendert")
+  g1 --> t10("ist_gueltiger_gpkg_pfad_akzeptiert_vorhandenes_verzeichnis")
+  g1 --> t11("ist_gueltiger_gpkg_pfad_lehnt_falsche_endung_ab")
+  g1 --> t12("ist_gueltiger_gpkg_pfad_lehnt_fehlendes_verzeichnis_ab")
   class t1 ok
   class t2 ok
   class t3 ok
   class t4 ok
   class t5 ok
   class t6 ok
+  class t7 ok
+  class t8 ok
+  class t9 ok
+  class t10 ok
+  class t11 ok
+  class t12 ok
   classDef rootnode fill:#1f4038,stroke:#16302a,stroke-width:1px,color:#f4f1e8,font-weight:600;
   classDef groupnode fill:#cfe0da,stroke:#5c8a7d,stroke-width:1px,color:#152420;
   classDef ok fill:#dcefdc,stroke:#3f7d4a,stroke-width:1px,color:#1c3a20;
   classDef warn fill:#f6ead9,stroke:#b5722a,stroke-width:1px,color:#4a2c08;
-  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
TestDateipruefer
test_leereingabe_erlaubt
Prüft, dass eine leere Pfadangabe bei leereingabe_erlaubt=True als 'leereingabe_erlaubt' ohne Kontext gemeldet wird.grüngeprüft am 2026-09-17
TestDateipruefer
test_leereingabe_nicht_erlaubt
Prüft, dass eine leere Pfadangabe ohne leereingabe_erlaubt als 'leereingabe_nicht_erlaubt' abgelehnt wird.grüngeprüft am 2026-09-17
TestDateipruefer
test_standarddatei_vorschlagen
Prüft, dass bei leerer Pfadangabe mit gesetzter Standarddatei 'standarddatei_vorschlagen' mit dem Standardpfad als Kontext geliefert wird.grünnie geprüft
TestDateipruefer
test_temporaer_erlaubt
Prüft, dass eine leere Pfadangabe bei temporaer_erlaubt=True als 'temporaer_erlaubt' ohne Kontext gemeldet wird.grüngeprüft am 2026-09-17
TestDateipruefer
test_datei_nicht_gefunden
Prüft, dass ein nicht existierender Dateipfad als 'datei_nicht_gefunden' mit dem Pfad als Kontext abgelehnt wird.grüngeprüft am 2026-09-17
TestDateipruefer
test_datei_ok
Prüft, dass ein existierender Dateipfad als 'ok' mit dem Pfad als Kontext bestätigt wird.grüngeprüft am 2026-09-17

Tests für sn_basis/modules/Datenabruf.py (Datenabruf-Kernpipeline, Issue #63).

DetermineSpatialFilterTests 7BuildProviderUrlTests 9FetchFeaturesTests 5DatenabrufOrchestrierungTests 3
flowchart TD
+  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
TestDateipruefer
test_leereingabe_erlaubt
Prüft, dass eine leere Pfadangabe bei leereingabe_erlaubt=True als 'leereingabe_erlaubt' ohne Kontext gemeldet wird.grüngeprüft am 2026-09-17
TestDateipruefer
test_leereingabe_nicht_erlaubt
Prüft, dass eine leere Pfadangabe ohne leereingabe_erlaubt als 'leereingabe_nicht_erlaubt' abgelehnt wird.grüngeprüft am 2026-09-17
TestDateipruefer
test_standarddatei_vorschlagen
Prüft, dass bei leerer Pfadangabe mit gesetzter Standarddatei 'standarddatei_vorschlagen' mit dem Standardpfad als Kontext geliefert wird.grünnie geprüft
TestDateipruefer
test_temporaer_erlaubt
Prüft, dass eine leere Pfadangabe bei temporaer_erlaubt=True als 'temporaer_erlaubt' ohne Kontext gemeldet wird.grüngeprüft am 2026-09-17
TestDateipruefer
test_datei_nicht_gefunden
Prüft, dass ein nicht existierender Dateipfad als 'datei_nicht_gefunden' mit dem Pfad als Kontext abgelehnt wird.grüngeprüft am 2026-09-17
TestDateipruefer
test_datei_ok
Prüft, dass ein existierender Dateipfad als 'ok' mit dem Pfad als Kontext bestätigt wird.grüngeprüft am 2026-09-17
TestDateipruefer
test_erkenne_dateityp_unterscheidet_excel_datenbank_und_unbekannt
Prüft, dass erkenne_dateityp .xlsx als 'excel', .gpkg/.sqlite als 'datenbank' und Rest als 'unbekannt' erkennt.grünnie geprüft
TestDateipruefer
test_pfad_verbindet_relativen_pfad_mit_basispfad
Prüft, dass _pfad einen relativen Pfad mit dem Basisverzeichnis verbindet.grünnie geprüft
TestDateipruefer
test_pfad_laesst_absoluten_pfad_unveraendert
Prüft, dass _pfad einen bereits absoluten Pfad nicht mit dem Basisverzeichnis verbindet.grünnie geprüft
TestDateipruefer
test_ist_gueltiger_gpkg_pfad_akzeptiert_vorhandenes_verzeichnis
Prüft, dass ein .gpkg-Pfad mit vorhandenem Zielverzeichnis als gültig gilt.grünnie geprüft
TestDateipruefer
test_ist_gueltiger_gpkg_pfad_lehnt_falsche_endung_ab
Prüft, dass ein Pfad ohne .gpkg-Endung als ungültig gilt, auch bei vorhandenem Verzeichnis.grünnie geprüft
TestDateipruefer
test_ist_gueltiger_gpkg_pfad_lehnt_fehlendes_verzeichnis_ab
Prüft, dass ein .gpkg-Pfad in einem nicht vorhandenen Verzeichnis als ungültig gilt.grünnie geprüft

Tests für sn_basis/modules/Datenabruf.py (Datenabruf-Kernpipeline, Issue #63).

DetermineSpatialFilterTests 7BuildProviderUrlTests 9FetchFeaturesTests 5DatenabrufOrchestrierungTests 3
flowchart TD
   root(["test_datenabruf.py"])
   class root rootnode
   root --> g1["DetermineSpatialFilterTests (7)"]
@@ -309,7 +340,28 @@
   classDef groupnode fill:#cfe0da,stroke:#5c8a7d,stroke-width:1px,color:#152420;
   classDef ok fill:#dcefdc,stroke:#3f7d4a,stroke-width:1px,color:#1c3a20;
   classDef warn fill:#f6ead9,stroke:#b5722a,stroke-width:1px,color:#4a2c08;
-  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
WriteLayerToGpkgTests
test_ungueltiger_layer_liefert_fehlermeldung
Prüft, dass ein ungültiger Layer eine Fehlermeldung statt eines Absturzes liefert.grünnie geprüft
WriteLayerToGpkgTests
test_gueltiger_layer_wird_ohne_fehler_geschrieben
Prüft, dass ein gültiger Layer im Mock-Modus ohne Fehlermeldung geschrieben wird.grünnie geprüft
ResolveStylePathTests
test_leerer_stilpfad_liefert_none
Prüft, dass ein leerer oder fehlender Stilpfad None liefert.grünnie geprüft
ResolveStylePathTests
test_absoluter_vorhandener_stilpfad_wird_aufgeloest
Prüft, dass ein absoluter, vorhandener Stilpfad normalisiert und unverändert erkannt wird.grünnie geprüft
ResolveStylePathTests
test_nicht_vorhandener_stilpfad_liefert_none
Prüft, dass ein nicht vorhandener Stilpfad None liefert, statt einen ungültigen Pfad zurückzugeben.grünnie geprüft
SchreibeDatenTests
test_ohne_speicherort_wirft_valueerror
Prüft, dass schreibe_Daten ohne Speicherort einen ValueError wirft.grünnie geprüft
SchreibeDatenTests
test_eintrag_ohne_gueltigen_layer_wird_uebersprungen
Prüft, dass ein Eintrag ohne gültigen Layer übersprungen wird und ein Fehlerergebnis meldet.grünnie geprüft
SchreibeDatenTests
test_erfolgreicher_eintrag_liefert_layer_path_und_thema
Prüft, dass ein gültiger Layer einen Layer-Path mit GPKG-Pfad und Layername liefert.grünnie geprüft
SchreibeDatenTests
test_ohne_thema_wird_ident_als_layername_verwendet
Prüft, dass ohne passendes Thema in processed_results der ident als Layername verwendet wird.grünnie geprüft
LadeLayerTests
test_ohne_layer_path_wird_uebersprungen
Prüft, dass ein Eintrag ohne layer_path übersprungen wird, ohne einen Fehler zu melden.grünnie geprüft
LadeLayerTests
test_gueltiger_layer_wird_dem_projekt_hinzugefuegt
Prüft, dass ein gültig ladbarer Layer ohne Fehlermeldung verarbeitet wird.grünnie geprüft
LadeLayerTests
test_ungueltiger_layer_meldet_layer_nicht_gefunden
Prüft, dass ein ungültig ladbarer Layer als 'layer_nicht_gefunden' gemeldet wird.grünnie geprüft
SchreibeLogTests
test_ohne_speicherort_wirft_valueerror
Prüft, dass schreibe_log ohne Speicherort einen ValueError wirft.grünnie geprüft
SchreibeLogTests
test_schreibt_json_datei_mit_ergebnissen_und_gibt_pfad_zurueck
Prüft, dass schreibe_log eine lesbare JSON-Log-Datei erzeugt und deren Pfad zurückgibt.grünnie geprüft

Tests für sn_basis/modules/excel_importer.py (Excel-Import für Linklisten, Issue #63).

ImportXlsxTests 5ExcelImporterKonstruktorTests 2
flowchart TD
+  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
WriteLayerToGpkgTests
test_ungueltiger_layer_liefert_fehlermeldung
Prüft, dass ein ungültiger Layer eine Fehlermeldung statt eines Absturzes liefert.grünnie geprüft
WriteLayerToGpkgTests
test_gueltiger_layer_wird_ohne_fehler_geschrieben
Prüft, dass ein gültiger Layer im Mock-Modus ohne Fehlermeldung geschrieben wird.grünnie geprüft
ResolveStylePathTests
test_leerer_stilpfad_liefert_none
Prüft, dass ein leerer oder fehlender Stilpfad None liefert.grünnie geprüft
ResolveStylePathTests
test_absoluter_vorhandener_stilpfad_wird_aufgeloest
Prüft, dass ein absoluter, vorhandener Stilpfad normalisiert und unverändert erkannt wird.grünnie geprüft
ResolveStylePathTests
test_nicht_vorhandener_stilpfad_liefert_none
Prüft, dass ein nicht vorhandener Stilpfad None liefert, statt einen ungültigen Pfad zurückzugeben.grünnie geprüft
SchreibeDatenTests
test_ohne_speicherort_wirft_valueerror
Prüft, dass schreibe_Daten ohne Speicherort einen ValueError wirft.grünnie geprüft
SchreibeDatenTests
test_eintrag_ohne_gueltigen_layer_wird_uebersprungen
Prüft, dass ein Eintrag ohne gültigen Layer übersprungen wird und ein Fehlerergebnis meldet.grünnie geprüft
SchreibeDatenTests
test_erfolgreicher_eintrag_liefert_layer_path_und_thema
Prüft, dass ein gültiger Layer einen Layer-Path mit GPKG-Pfad und Layername liefert.grünnie geprüft
SchreibeDatenTests
test_ohne_thema_wird_ident_als_layername_verwendet
Prüft, dass ohne passendes Thema in processed_results der ident als Layername verwendet wird.grünnie geprüft
LadeLayerTests
test_ohne_layer_path_wird_uebersprungen
Prüft, dass ein Eintrag ohne layer_path übersprungen wird, ohne einen Fehler zu melden.grünnie geprüft
LadeLayerTests
test_gueltiger_layer_wird_dem_projekt_hinzugefuegt
Prüft, dass ein gültig ladbarer Layer ohne Fehlermeldung verarbeitet wird.grünnie geprüft
LadeLayerTests
test_ungueltiger_layer_meldet_layer_nicht_gefunden
Prüft, dass ein ungültig ladbarer Layer als 'layer_nicht_gefunden' gemeldet wird.grünnie geprüft
SchreibeLogTests
test_ohne_speicherort_wirft_valueerror
Prüft, dass schreibe_log ohne Speicherort einen ValueError wirft.grünnie geprüft
SchreibeLogTests
test_schreibt_json_datei_mit_ergebnissen_und_gibt_pfad_zurueck
Prüft, dass schreibe_log eine lesbare JSON-Log-Datei erzeugt und deren Pfad zurückgibt.grünnie geprüft

Tests für sn_basis/ui/dockmanager.py (nur ein Dock gleichzeitig sichtbar, Issue #65).

DockManagerShowTests 6
flowchart TD
+  root(["test_dockmanager.py"])
+  class root rootnode
+  root --> g1["DockManagerShowTests (6)"]
+  class g1 groupnode
+  g1 --> t1("none_dock_meldet_fehler_und_zeigt_nichts_an")
+  g1 --> t2("setzt_objectname_wenn_leer")
+  g1 --> t3("entfernt_andere_sn_docks_aber_nicht_sich_selbst")
+  g1 --> t4("zeigt_neues_dock_mit_default_area_an")
+  g1 --> t5("fehler_beim_entfernen_wird_als_warnung_gemeldet")
+  g1 --> t6("fehler_beim_anzeigen_wird_gemeldet")
+  class t1 ok
+  class t2 ok
+  class t3 ok
+  class t4 ok
+  class t5 ok
+  class t6 ok
+  classDef rootnode fill:#1f4038,stroke:#16302a,stroke-width:1px,color:#f4f1e8,font-weight:600;
+  classDef groupnode fill:#cfe0da,stroke:#5c8a7d,stroke-width:1px,color:#152420;
+  classDef ok fill:#dcefdc,stroke:#3f7d4a,stroke-width:1px,color:#1c3a20;
+  classDef warn fill:#f6ead9,stroke:#b5722a,stroke-width:1px,color:#4a2c08;
+  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
DockManagerShowTests
test_none_dock_meldet_fehler_und_zeigt_nichts_an
Prüft, dass ein fehlendes Dock-Widget (None) einen Fehler meldet und nichts anzeigt.grünnie geprüft
DockManagerShowTests
test_setzt_objectname_wenn_leer
Prüft, dass ein Dock ohne Namen einen technischen Namen mit dem Präfix 'sn_dock_' erhält.grünnie geprüft
DockManagerShowTests
test_entfernt_andere_sn_docks_aber_nicht_sich_selbst
Prüft, dass andere sn_basis-Docks entfernt werden, das neue Dock und fremde Widgets aber unangetastet bleiben.grünnie geprüft
DockManagerShowTests
test_zeigt_neues_dock_mit_default_area_an
Prüft, dass ein neues Dock mit der Standard-Area (DockAreaRight) angezeigt wird.grünnie geprüft
DockManagerShowTests
test_fehler_beim_entfernen_wird_als_warnung_gemeldet
Prüft, dass ein Fehler beim Entfernen alter Docks nur gewarnt und das neue Dock trotzdem angezeigt wird.grünnie geprüft
DockManagerShowTests
test_fehler_beim_anzeigen_wird_gemeldet
Prüft, dass ein Fehler beim Anzeigen des Docks als Fehler gemeldet wird.grünnie geprüft

Tests für sn_basis/modules/excel_importer.py (Excel-Import für Linklisten, Issue #63).

ImportXlsxTests 5ExcelImporterKonstruktorTests 2
flowchart TD
   root(["test_excel_importer.py"])
   class root rootnode
   root --> g1["ImportXlsxTests (5)"]
@@ -353,7 +405,20 @@
   classDef groupnode fill:#cfe0da,stroke:#5c8a7d,stroke-width:1px,color:#152420;
   classDef ok fill:#dcefdc,stroke:#3f7d4a,stroke-width:1px,color:#1c3a20;
   classDef warn fill:#f6ead9,stroke:#b5722a,stroke-width:1px,color:#4a2c08;
-  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
TestGetLaenderkennung
test_bekannter_praefix_gibt_kennung_zurueck
Prüft, dass der Präfix 'sn' die ALKIS-Länderkennung '14' für Sachsen liefert.grüngeprüft am 2026-09-17
TestGetLaenderkennung
test_praefix_gross_klein_unabhaengig
Prüft, dass die Präfixsuche groß-/kleinschreibungsunabhängig ist.grüngeprüft am 2026-09-17
TestGetLaenderkennung
test_unbekannter_praefix_wirft_keyerror
Prüft, dass ein unbekannter Präfix einen KeyError auslöst.grüngeprüft am 2026-09-17
TestGetLaenderkennung
test_ohne_argument_wird_aus_aufrufendem_modul_abgeleitet
Prüft, dass ohne Argument der Präfix aus dem Modulnamen des Aufrufers abgeleitet wird.grüngeprüft am 2026-09-17
TestGetLaenderkennung
test_mapping_enthaelt_sachsen
Prüft, dass die Mapping-Tabelle LAENDERKENNUNGEN einen Eintrag für Sachsen ('sn' -> '14') enthält.grüngeprüft am 2026-09-17

Tests für sn_basis/modules/LayerLoader.py (Layer erzeugen/filtern/laden, Issue #63).

CreateLayerTests 7TransformGeometryTests 3TransformExtentTests 2FilterByExtentTests 6FilterByLayerTests 4AddToProjectTests 3
flowchart TD
+  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
TestGetLaenderkennung
test_bekannter_praefix_gibt_kennung_zurueck
Prüft, dass der Präfix 'sn' die ALKIS-Länderkennung '14' für Sachsen liefert.grüngeprüft am 2026-09-17
TestGetLaenderkennung
test_praefix_gross_klein_unabhaengig
Prüft, dass die Präfixsuche groß-/kleinschreibungsunabhängig ist.grüngeprüft am 2026-09-17
TestGetLaenderkennung
test_unbekannter_praefix_wirft_keyerror
Prüft, dass ein unbekannter Präfix einen KeyError auslöst.grüngeprüft am 2026-09-17
TestGetLaenderkennung
test_ohne_argument_wird_aus_aufrufendem_modul_abgeleitet
Prüft, dass ohne Argument der Präfix aus dem Modulnamen des Aufrufers abgeleitet wird.grüngeprüft am 2026-09-17
TestGetLaenderkennung
test_mapping_enthaelt_sachsen
Prüft, dass die Mapping-Tabelle LAENDERKENNUNGEN einen Eintrag für Sachsen ('sn' -> '14') enthält.grüngeprüft am 2026-09-17

Tests für sn_basis/functions/landkreise.py::_lade_landkreise (Issue #65).

LadeLandkreiseTests 2
flowchart TD
+  root(["test_landkreise.py"])
+  class root rootnode
+  root --> g1["LadeLandkreiseTests (2)"]
+  class g1 groupnode
+  g1 --> t1("laedt_die_echte_landkreisliste_nicht_leer")
+  g1 --> t2("fehlende_datei_liefert_leere_liste")
+  class t1 ok
+  class t2 ok
+  classDef rootnode fill:#1f4038,stroke:#16302a,stroke-width:1px,color:#f4f1e8,font-weight:600;
+  classDef groupnode fill:#cfe0da,stroke:#5c8a7d,stroke-width:1px,color:#152420;
+  classDef ok fill:#dcefdc,stroke:#3f7d4a,stroke-width:1px,color:#1c3a20;
+  classDef warn fill:#f6ead9,stroke:#b5722a,stroke-width:1px,color:#4a2c08;
+  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
LadeLandkreiseTests
test_laedt_die_echte_landkreisliste_nicht_leer
Prüft, dass _lade_landkreise die echte landkreise.json als nicht-leere Liste von (Kennzahl, Name)-Tupeln liefert.grünnie geprüft
LadeLandkreiseTests
test_fehlende_datei_liefert_leere_liste
Prüft, dass eine nicht lesbare Datenquelle eine leere Liste liefert, statt eine Ausnahme zu werfen.grünnie geprüft

Tests für sn_basis/modules/LayerLoader.py (Layer erzeugen/filtern/laden, Issue #63).

CreateLayerTests 7TransformGeometryTests 3TransformExtentTests 2FilterByExtentTests 6FilterByLayerTests 4AddToProjectTests 3
flowchart TD
   root(["test_layerloader.py"])
   class root rootnode
   root --> g1["CreateLayerTests (7)"]
@@ -472,7 +537,70 @@
   classDef groupnode fill:#cfe0da,stroke:#5c8a7d,stroke-width:1px,color:#152420;
   classDef ok fill:#dcefdc,stroke:#3f7d4a,stroke-width:1px,color:#1c3a20;
   classDef warn fill:#f6ead9,stroke:#b5722a,stroke-width:1px,color:#4a2c08;
-  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
TestLinkpruefer
test_leere_eingabe
Prüft, dass eine leere Eingabe ohne Netzwerk-/Dateizugriff als 'leer' abgelehnt wird.grüngeprüft am 2026-09-17
TestLinkpruefer
test_remote_link_ok
Prüft, dass eine erreichbare Remote-URL (HTTP HEAD ohne Fehler) als 'ok' bestätigt wird.grüngeprüft am 2026-09-17
TestLinkpruefer
test_remote_link_error
Prüft, dass eine Remote-URL mit Fehlerantwort als 'url_nicht_erreichbar' abgelehnt wird.grüngeprüft am 2026-09-17
TestLinkpruefer
test_remote_link_network_error
Prüft, dass eine ausbleibende Netzwerkantwort (None) als 'netzwerkfehler' gemeldet wird.grüngeprüft am 2026-09-17
TestLinkpruefer
test_local_link_not_found
Prüft, dass ein nicht existierender lokaler Pfad als 'pfad_nicht_gefunden' abgelehnt wird.grüngeprüft am 2026-09-17
TestLinkpruefer
test_local_link_ok
Prüft, dass ein existierender lokaler Pfad als 'ok' bestätigt wird.grüngeprüft am 2026-09-17

— (Docstring fehlt)

TestPrintLayout 5
flowchart TD
+  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
TestLinkpruefer
test_leere_eingabe
Prüft, dass eine leere Eingabe ohne Netzwerk-/Dateizugriff als 'leer' abgelehnt wird.grüngeprüft am 2026-09-17
TestLinkpruefer
test_remote_link_ok
Prüft, dass eine erreichbare Remote-URL (HTTP HEAD ohne Fehler) als 'ok' bestätigt wird.grüngeprüft am 2026-09-17
TestLinkpruefer
test_remote_link_error
Prüft, dass eine Remote-URL mit Fehlerantwort als 'url_nicht_erreichbar' abgelehnt wird.grüngeprüft am 2026-09-17
TestLinkpruefer
test_remote_link_network_error
Prüft, dass eine ausbleibende Netzwerkantwort (None) als 'netzwerkfehler' gemeldet wird.grüngeprüft am 2026-09-17
TestLinkpruefer
test_local_link_not_found
Prüft, dass ein nicht existierender lokaler Pfad als 'pfad_nicht_gefunden' abgelehnt wird.grüngeprüft am 2026-09-17
TestLinkpruefer
test_local_link_ok
Prüft, dass ein existierender lokaler Pfad als 'ok' bestätigt wird.grüngeprüft am 2026-09-17

Tests für sn_basis/functions/ly_existence_wrapper.py::layer_is_valid/layer_is_usable (Issue #65).

LayerIsValidTests 5LayerIsUsableTests 3
flowchart TD
+  root(["test_ly_existence_wrapper.py"])
+  class root rootnode
+  root --> g1["LayerIsValidTests (5)"]
+  class g1 groupnode
+  g1 --> t1("none_ist_nicht_gueltig")
+  g1 --> t2("objekt_ohne_isvalid_ist_nicht_gueltig")
+  g1 --> t3("gueltiger_layer_liefert_true")
+  g1 --> t4("ungueltiger_layer_liefert_false")
+  g1 --> t5("ausnahme_bei_isvalid_liefert_false")
+  root --> g2["LayerIsUsableTests (3)"]
+  class g2 groupnode
+  g2 --> t6("none_ist_nicht_nutzbar")
+  g2 --> t7("gueltiger_layer_ist_nutzbar")
+  g2 --> t8("ungueltiger_layer_ist_nicht_nutzbar")
+  class t1 ok
+  class t2 ok
+  class t3 ok
+  class t4 ok
+  class t5 ok
+  class t6 ok
+  class t7 ok
+  class t8 ok
+  classDef rootnode fill:#1f4038,stroke:#16302a,stroke-width:1px,color:#f4f1e8,font-weight:600;
+  classDef groupnode fill:#cfe0da,stroke:#5c8a7d,stroke-width:1px,color:#152420;
+  classDef ok fill:#dcefdc,stroke:#3f7d4a,stroke-width:1px,color:#1c3a20;
+  classDef warn fill:#f6ead9,stroke:#b5722a,stroke-width:1px,color:#4a2c08;
+  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
LayerIsValidTests
test_none_ist_nicht_gueltig
Prüft, dass layer_is_valid für None False liefert.grünnie geprüft
LayerIsValidTests
test_objekt_ohne_isvalid_ist_nicht_gueltig
Prüft, dass ein Objekt ohne isValid()-Methode als ungültig gilt.grünnie geprüft
LayerIsValidTests
test_gueltiger_layer_liefert_true
Prüft, dass ein Layer mit isValid()==True als gültig erkannt wird.grünnie geprüft
LayerIsValidTests
test_ungueltiger_layer_liefert_false
Prüft, dass ein Layer mit isValid()==False als ungültig erkannt wird.grünnie geprüft
LayerIsValidTests
test_ausnahme_bei_isvalid_liefert_false
Prüft, dass eine Ausnahme in isValid() abgefangen wird und False liefert.grünnie geprüft
LayerIsUsableTests
test_none_ist_nicht_nutzbar
Prüft, dass layer_is_usable für None False liefert.grünnie geprüft
LayerIsUsableTests
test_gueltiger_layer_ist_nutzbar
Prüft, dass ein vorhandener, gültiger Layer als nutzbar gilt.grünnie geprüft
LayerIsUsableTests
test_ungueltiger_layer_ist_nicht_nutzbar
Prüft, dass ein vorhandener, aber ungültiger Layer als nicht nutzbar gilt.grünnie geprüft

Tests für sn_basis/functions/ly_style_wrapper.py::apply_style_from_path (Issue #65).

ApplyStyleFromPathTests 4
flowchart TD
+  root(["test_ly_style_wrapper.py"])
+  class root rootnode
+  root --> g1["ApplyStyleFromPathTests (4)"]
+  class g1 groupnode
+  g1 --> t1("fehlender_layer_liefert_false")
+  g1 --> t2("erfolgreiches_laden_liefert_true_und_triggert_repaint")
+  g1 --> t3("fehlgeschlagenes_laden_liefert_false_ohne_repaint")
+  g1 --> t4("ausnahme_beim_laden_wird_abgefangen")
+  class t1 ok
+  class t2 ok
+  class t3 ok
+  class t4 ok
+  classDef rootnode fill:#1f4038,stroke:#16302a,stroke-width:1px,color:#f4f1e8,font-weight:600;
+  classDef groupnode fill:#cfe0da,stroke:#5c8a7d,stroke-width:1px,color:#152420;
+  classDef ok fill:#dcefdc,stroke:#3f7d4a,stroke-width:1px,color:#1c3a20;
+  classDef warn fill:#f6ead9,stroke:#b5722a,stroke-width:1px,color:#4a2c08;
+  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
ApplyStyleFromPathTests
test_fehlender_layer_liefert_false
Prüft, dass ein fehlender Layer (None) False liefert, ohne einen Stil zu laden.grünnie geprüft
ApplyStyleFromPathTests
test_erfolgreiches_laden_liefert_true_und_triggert_repaint
Prüft, dass ein erfolgreich geladener Stil True liefert und den Layer neu zeichnet.grünnie geprüft
ApplyStyleFromPathTests
test_fehlgeschlagenes_laden_liefert_false_ohne_repaint
Prüft, dass ein fehlgeschlagenes Laden False liefert, ohne den Layer neu zu zeichnen.grünnie geprüft
ApplyStyleFromPathTests
test_ausnahme_beim_laden_wird_abgefangen
Prüft, dass eine Ausnahme beim Laden des Stils abgefangen wird und False liefert.grünnie geprüft

Tests für sn_basis/functions/message_wrapper.py (Issue #65).

GetMessageBarTests 2PushMessageTests 2
flowchart TD
+  root(["test_message_wrapper.py"])
+  class root rootnode
+  root --> g1["GetMessageBarTests (2)"]
+  class g1 groupnode
+  g1 --> t1("liefert_objekt_mit_pushmessage_methode")
+  g1 --> t2("faellt_bei_fehlerhaftem_iface_auf_mock_bar_zurueck")
+  root --> g2["PushMessageTests (2)"]
+  class g2 groupnode
+  g2 --> t3("liefert_dict_mit_titel_text_level_und_dauer")
+  g2 --> t4("fehler_in_der_message_bar_wird_abgefangen")
+  class t1 ok
+  class t2 ok
+  class t3 ok
+  class t4 ok
+  classDef rootnode fill:#1f4038,stroke:#16302a,stroke-width:1px,color:#f4f1e8,font-weight:600;
+  classDef groupnode fill:#cfe0da,stroke:#5c8a7d,stroke-width:1px,color:#152420;
+  classDef ok fill:#dcefdc,stroke:#3f7d4a,stroke-width:1px,color:#1c3a20;
+  classDef warn fill:#f6ead9,stroke:#b5722a,stroke-width:1px,color:#4a2c08;
+  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
GetMessageBarTests
test_liefert_objekt_mit_pushmessage_methode
Prüft, dass _get_message_bar ein Objekt mit aufrufbarer pushMessage()-Methode liefert.grünnie geprüft
GetMessageBarTests
test_faellt_bei_fehlerhaftem_iface_auf_mock_bar_zurueck
Prüft, dass ein Fehler beim Zugriff auf iface.messageBar() auf eine funktionierende Mock-MessageBar zurückfällt.grünnie geprüft
PushMessageTests
test_liefert_dict_mit_titel_text_level_und_dauer
Prüft, dass push_message im Mock-Modus ein Dict mit den übergebenen Werten liefert.grünnie geprüft
PushMessageTests
test_fehler_in_der_message_bar_wird_abgefangen
Prüft, dass eine fehlschlagende MessageBar push_message nicht zum Absturz bringt, sondern None liefert.grünnie geprüft

— (Docstring fehlt)

TestPrintLayout 5
flowchart TD
   root(["test_print_layout.py"])
   class root rootnode
   root --> g1["TestPrintLayout (5)"]
@@ -534,10 +662,29 @@
   classDef groupnode fill:#cfe0da,stroke:#5c8a7d,stroke-width:1px,color:#152420;
   classDef ok fill:#dcefdc,stroke:#3f7d4a,stroke-width:1px,color:#1c3a20;
   classDef warn fill:#f6ead9,stroke:#b5722a,stroke-width:1px,color:#4a2c08;
-  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
TestPrintLogic
test_get_baufreigabe_page_dimensions_prefers_a4_for_small_extent
Prüft, dass für einen kleinen Kartenausschnitt (Baufreigabe) das Format DIN A4 ohne Fallback gewählt wird.grünnie geprüft
TestPrintLogic
test_get_baufreigabe_page_dimensions_escalates_to_a3
Prüft, dass ein größerer Kartenausschnitt (Baufreigabe) auf DIN A3 eskaliert wird.grünnie geprüft
TestPrintLogic
test_get_baufreigabe_page_dimensions_respects_a4_as_maximum_with_fallback
Prüft, dass bei auf DIN A4 begrenztem Höchstformat ein eigentlich A3-großer Ausschnitt mit Fallback-Kennzeichnung auf A4 reduziert wird.grünnie geprüft
TestPrintLogic
test_get_baufreigabe_page_dimensions_falls_back_to_a3_for_oversize_extent
Prüft, dass ein Ausschnitt, der auch DIN A3 übersteigt, mit Fallback-Kennzeichnung auf DIN A3 begrenzt wird.grünnie geprüft
TestPrintLogic
test_select_standard_page_layout_uses_a4_as_minimum_sheet
Prüft, dass für einen kleinen Ausschnitt trotz Höchstgrenze DIN A3 mindestens DIN A4 als Blattgröße gewählt wird.grünnie geprüft
TestPrintLogic
test_select_standard_page_layout_limits_hauptkarte_to_a3
Prüft, dass ein die Fläche voll ausnutzender Ausschnitt auf DIN A3 als größtes zulässiges Format begrenzt wird.grünnie geprüft
TestPrintLogic
test_select_standard_page_layout_returns_none_if_a3_is_too_small
Prüft, dass kein Layout gewählt wird (None), wenn der Ausschnitt selbst DIN A3 als Höchstformat übersteigt.grünnie geprüft
TestPrintLogic
test_get_standard_layout_dimensions_uses_a4_and_forces_fit_for_small_extent
Prüft, dass für einen kleinen Ausschnitt DIN A4 gewählt und das Einpassen (force_fit) erzwungen wird.grünnie geprüft
TestPrintLogic
test_get_standard_layout_dimensions_caps_endlosrolle_width_at_2000_mm
Prüft, dass bei aktiviertem Formfaktor (Endlosrolle) die Seitenbreite auf die maximale Rollenbreite (2000 mm) begrenzt wird.grünnie geprüft
TestPrintLogic
test_apply_standard_minimum_a4_fallback_for_small_page
Prüft, dass eine zu kleine Seite auf die A4-Mindestgröße angehoben und als erzwungen (forced) markiert wird.grünnie geprüft
TestPrintLogic
test_apply_standard_minimum_a4_fallback_keeps_large_page
Prüft, dass eine bereits ausreichend große Seite (A3) unverändert bleibt und nicht als erzwungen markiert wird.grünnie geprüft
TestPrintLogic
test_does_plot_fit_page_true_for_standard_a4
Prüft, dass ein Kartenobjekt, das in eine DIN A4-Seite passt, als passend erkannt wird.grünnie geprüft
TestPrintLogic
test_does_plot_fit_page_false_if_objects_exceed_page
Prüft, dass ein Kartenobjekt, das die Seitenbreite überschreitet, als nicht passend erkannt wird.grünnie geprüft
TestPrintLogic
test_set_druckbereich_accepts_wie_kartenfenster
Prüft, dass die Auswahl 'wie Kartenfenster' als Projektvariable 'druckbereich' gespeichert wird.grünnie geprüft
TestPrintLogic
test_get_canvas_extent_returns_valid_extent
Prüft, dass der aktuelle Kartenausschnitt des Kartenfensters unverändert zurückgegeben wird.grünnie geprüft
TestPrintLogic
test_resolve_extent_uses_canvas_extent_without_buffer
Prüft, dass bei Druckbereich 'wie Kartenfenster' der Kartenausschnitt ohne Puffer und ohne verknüpften Layer übernommen wird.grünnie geprüft
TestPrintLogic
test_resolve_extent_uses_rectangle_extent_without_buffer
Prüft, dass bei Druckbereich 'Rechteck' der gezeichnete Ausschnitt ohne Puffer und ohne verknüpften Layer übernommen wird.grünnie geprüft

— (Docstring fehlt)

TestPruefmanager 14
flowchart TD
+  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
TestPrintLogic
test_get_baufreigabe_page_dimensions_prefers_a4_for_small_extent
Prüft, dass für einen kleinen Kartenausschnitt (Baufreigabe) das Format DIN A4 ohne Fallback gewählt wird.grünnie geprüft
TestPrintLogic
test_get_baufreigabe_page_dimensions_escalates_to_a3
Prüft, dass ein größerer Kartenausschnitt (Baufreigabe) auf DIN A3 eskaliert wird.grünnie geprüft
TestPrintLogic
test_get_baufreigabe_page_dimensions_respects_a4_as_maximum_with_fallback
Prüft, dass bei auf DIN A4 begrenztem Höchstformat ein eigentlich A3-großer Ausschnitt mit Fallback-Kennzeichnung auf A4 reduziert wird.grünnie geprüft
TestPrintLogic
test_get_baufreigabe_page_dimensions_falls_back_to_a3_for_oversize_extent
Prüft, dass ein Ausschnitt, der auch DIN A3 übersteigt, mit Fallback-Kennzeichnung auf DIN A3 begrenzt wird.grünnie geprüft
TestPrintLogic
test_select_standard_page_layout_uses_a4_as_minimum_sheet
Prüft, dass für einen kleinen Ausschnitt trotz Höchstgrenze DIN A3 mindestens DIN A4 als Blattgröße gewählt wird.grünnie geprüft
TestPrintLogic
test_select_standard_page_layout_limits_hauptkarte_to_a3
Prüft, dass ein die Fläche voll ausnutzender Ausschnitt auf DIN A3 als größtes zulässiges Format begrenzt wird.grünnie geprüft
TestPrintLogic
test_select_standard_page_layout_returns_none_if_a3_is_too_small
Prüft, dass kein Layout gewählt wird (None), wenn der Ausschnitt selbst DIN A3 als Höchstformat übersteigt.grünnie geprüft
TestPrintLogic
test_get_standard_layout_dimensions_uses_a4_and_forces_fit_for_small_extent
Prüft, dass für einen kleinen Ausschnitt DIN A4 gewählt und das Einpassen (force_fit) erzwungen wird.grünnie geprüft
TestPrintLogic
test_get_standard_layout_dimensions_caps_endlosrolle_width_at_2000_mm
Prüft, dass bei aktiviertem Formfaktor (Endlosrolle) die Seitenbreite auf die maximale Rollenbreite (2000 mm) begrenzt wird.grünnie geprüft
TestPrintLogic
test_apply_standard_minimum_a4_fallback_for_small_page
Prüft, dass eine zu kleine Seite auf die A4-Mindestgröße angehoben und als erzwungen (forced) markiert wird.grünnie geprüft
TestPrintLogic
test_apply_standard_minimum_a4_fallback_keeps_large_page
Prüft, dass eine bereits ausreichend große Seite (A3) unverändert bleibt und nicht als erzwungen markiert wird.grünnie geprüft
TestPrintLogic
test_does_plot_fit_page_true_for_standard_a4
Prüft, dass ein Kartenobjekt, das in eine DIN A4-Seite passt, als passend erkannt wird.grünnie geprüft
TestPrintLogic
test_does_plot_fit_page_false_if_objects_exceed_page
Prüft, dass ein Kartenobjekt, das die Seitenbreite überschreitet, als nicht passend erkannt wird.grünnie geprüft
TestPrintLogic
test_set_druckbereich_accepts_wie_kartenfenster
Prüft, dass die Auswahl 'wie Kartenfenster' als Projektvariable 'druckbereich' gespeichert wird.grünnie geprüft
TestPrintLogic
test_get_canvas_extent_returns_valid_extent
Prüft, dass der aktuelle Kartenausschnitt des Kartenfensters unverändert zurückgegeben wird.grünnie geprüft
TestPrintLogic
test_resolve_extent_uses_canvas_extent_without_buffer
Prüft, dass bei Druckbereich 'wie Kartenfenster' der Kartenausschnitt ohne Puffer und ohne verknüpften Layer übernommen wird.grünnie geprüft
TestPrintLogic
test_resolve_extent_uses_rectangle_extent_without_buffer
Prüft, dass bei Druckbereich 'Rechteck' der gezeichnete Ausschnitt ohne Puffer und ohne verknüpften Layer übernommen wird.grünnie geprüft

Tests für sn_basis/modules/pruef_ergebnis.py::ist_verfahrens_db_aktion/erlaubte_persistierung (Issue #65).

IstVerfahrensDbAktionTests 2ErlaubtePersistierungTests 2
flowchart TD
+  root(["test_pruef_ergebnis.py"])
+  class root rootnode
+  root --> g1["IstVerfahrensDbAktionTests (2)"]
+  class g1 groupnode
+  g1 --> t1("liefert_true_fuer_alle_verfahrens_db_aktionen")
+  g1 --> t2("liefert_false_fuer_andere_aktionen")
+  root --> g2["ErlaubtePersistierungTests (2)"]
+  class g2 groupnode
+  g2 --> t3("liefert_true_fuer_erzeugen_ueberschreiben_anhaengen")
+  g2 --> t4("liefert_false_fuer_ueberspringen_und_reines_existieren")
+  class t1 ok
+  class t2 ok
+  class t3 ok
+  class t4 ok
+  classDef rootnode fill:#1f4038,stroke:#16302a,stroke-width:1px,color:#f4f1e8,font-weight:600;
+  classDef groupnode fill:#cfe0da,stroke:#5c8a7d,stroke-width:1px,color:#152420;
+  classDef ok fill:#dcefdc,stroke:#3f7d4a,stroke-width:1px,color:#1c3a20;
+  classDef warn fill:#f6ead9,stroke:#b5722a,stroke-width:1px,color:#4a2c08;
+  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
IstVerfahrensDbAktionTests
test_liefert_true_fuer_alle_verfahrens_db_aktionen
Prüft, dass ist_verfahrens_db_aktion für alle vier Verfahrens-DB-Aktionscodes True liefert.grünnie geprüft
IstVerfahrensDbAktionTests
test_liefert_false_fuer_andere_aktionen
Prüft, dass ist_verfahrens_db_aktion für Nicht-Verfahrens-DB-Aktionen und ohne Aktion False liefert.grünnie geprüft
ErlaubtePersistierungTests
test_liefert_true_fuer_erzeugen_ueberschreiben_anhaengen
Prüft, dass erlaubte_persistierung für Erzeugen/Überschreiben/Anhängen True liefert.grünnie geprüft
ErlaubtePersistierungTests
test_liefert_false_fuer_ueberspringen_und_reines_existieren
Prüft, dass erlaubte_persistierung bei Überspringen und reinem 'datei_existiert' False liefert.grünnie geprüft

— (Docstring fehlt)

TestPruefmanager 24
flowchart TD
   root(["test_pruefmanager.py"])
   class root rootnode
-  root --> g1["TestPruefmanager (14)"]
+  root --> g1["TestPruefmanager (24)"]
   class g1 groupnode
   g1 --> t1("ok")
   g1 --> t2("leereingabe_erlaubt_ja")
@@ -553,6 +700,16 @@
   g1 --> t12("datei_existiert_append")
   g1 --> t13("datei_existiert_cancel")
   g1 --> t14("datei_existiert_in_non_qgis_mode_returns_input")
+  g1 --> t15("verfahrensgebiet_layer_existiert_ergaenzen")
+  g1 --> t16("verfahrensgebiet_layer_existiert_abbrechen")
+  g1 --> t17("verfahrensgebiet_layer_existiert_in_non_qgis_mode_returns_input")
+  g1 --> t18("report_error_kritische_aktion_ruft_error_auf")
+  g1 --> t19("report_error_warn_aktion_ruft_warning_auf")
+  g1 --> t20("report_error_unbekannte_aktion_faellt_auf_warning_zurueck")
+  g1 --> t21("frage_ja_nein_im_qgis_modus_fragt_nutzer")
+  g1 --> t22("frage_ja_nein_ausserhalb_qgis_liefert_default_ohne_rueckfrage")
+  g1 --> t23("frage_text_im_qgis_modus_fragt_nutzer")
+  g1 --> t24("frage_text_ausserhalb_qgis_liefert_default_ohne_rueckfrage")
   class t1 ok
   class t2 ok
   class t3 ok
@@ -567,11 +724,71 @@
   class t12 ok
   class t13 ok
   class t14 ok
+  class t15 ok
+  class t16 ok
+  class t17 ok
+  class t18 ok
+  class t19 ok
+  class t20 ok
+  class t21 ok
+  class t22 ok
+  class t23 ok
+  class t24 ok
   classDef rootnode fill:#1f4038,stroke:#16302a,stroke-width:1px,color:#f4f1e8,font-weight:600;
   classDef groupnode fill:#cfe0da,stroke:#5c8a7d,stroke-width:1px,color:#152420;
   classDef ok fill:#dcefdc,stroke:#3f7d4a,stroke-width:1px,color:#1c3a20;
   classDef warn fill:#f6ead9,stroke:#b5722a,stroke-width:1px,color:#4a2c08;
-  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
TestPruefmanager
test_ok
Prüft, dass ein bereits erfolgreiches Prüfergebnis ohne Nutzerinteraktion als 'ok' durchgereicht wird.grüngeprüft am 2026-09-17
TestPruefmanager
test_leereingabe_erlaubt_ja
Prüft, dass bei erlaubter leerer Eingabe eine Ja-Antwort des Nutzers die Entscheidung 'ok' liefert.grüngeprüft am 2026-09-17
TestPruefmanager
test_leereingabe_erlaubt_nein
Prüft, dass bei erlaubter leerer Eingabe eine Nein-Antwort die Aktion 'leereingabe_erlaubt' als abgelehnt bestehen lässt.grüngeprüft am 2026-09-17
TestPruefmanager
test_standarddatei_vorschlagen_ja
Prüft, dass eine Ja-Antwort auf den Vorschlag der Standarddatei die Entscheidung 'ok' mit dem Standardpfad als Kontext liefert.grüngeprüft am 2026-09-17
TestPruefmanager
test_standarddatei_vorschlagen_nein
Prüft, dass eine Nein-Antwort auf den Vorschlag der Standarddatei die Aktion 'standarddatei_vorschlagen' als abgelehnt bestehen lässt.grüngeprüft am 2026-09-17
TestPruefmanager
test_temporaer_erlaubt_ja
Prüft, dass eine Ja-Antwort auf die Rückfrage nach einer temporären Datei die Aktion 'temporaer_erzeugen' auslöst.grüngeprüft am 2026-09-17
TestPruefmanager
test_temporaer_erlaubt_nein
Prüft, dass eine Nein-Antwort auf die Rückfrage nach einer temporären Datei die Aktion 'temporaer_erlaubt' als abgelehnt bestehen lässt.grüngeprüft am 2026-09-17
TestPruefmanager
test_layer_unsichtbar_ja
Prüft, dass eine Ja-Antwort bei unsichtbarem Layer den Layer sichtbar schaltet und die Entscheidung 'ok' liefert.grüngeprüft am 2026-09-17
TestPruefmanager
test_layer_unsichtbar_nein
Prüft, dass eine Nein-Antwort bei unsichtbarem Layer die Aktion 'layer_unsichtbar' als abgelehnt bestehen lässt.grüngeprüft am 2026-09-17
TestPruefmanager
test_unbekannte_aktion
Prüft, dass eine unbekannte Aktion eine Warnung auslöst und unverarbeitet als Fehlschlag zurückgegeben wird.grüngeprüft am 2026-09-17
TestPruefmanager
test_datei_existiert_overwrite
Prüft, dass die Nutzerwahl 'überschreiben' bei bestehender Datei zur Aktion 'datei_existiert_ueberschreiben' führt.grüngeprüft am 2026-09-17
TestPruefmanager
test_datei_existiert_append
Prüft, dass die Nutzerwahl 'anhängen' bei bestehender Datei zur Aktion 'datei_existiert_anhaengen' führt.grüngeprüft am 2026-09-17
TestPruefmanager
test_datei_existiert_cancel
Prüft, dass die Nutzerwahl 'abbrechen' bei bestehender Datei zur Aktion 'datei_existiert_ueberspringen' führt.grüngeprüft am 2026-09-17
TestPruefmanager
test_datei_existiert_in_non_qgis_mode_returns_input
Prüft, dass außerhalb des QGIS-Modus bei bestehender Datei keine Rückfrage erfolgt, sondern die ursprüngliche Aktion unentschieden zurückgegeben wird.grüngeprüft am 2026-09-17

— (Docstring fehlt)

TestSettingsLogic 4
flowchart TD
+  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
TestPruefmanager
test_ok
Prüft, dass ein bereits erfolgreiches Prüfergebnis ohne Nutzerinteraktion als 'ok' durchgereicht wird.grüngeprüft am 2026-09-17
TestPruefmanager
test_leereingabe_erlaubt_ja
Prüft, dass bei erlaubter leerer Eingabe eine Ja-Antwort des Nutzers die Entscheidung 'ok' liefert.grüngeprüft am 2026-09-17
TestPruefmanager
test_leereingabe_erlaubt_nein
Prüft, dass bei erlaubter leerer Eingabe eine Nein-Antwort die Aktion 'leereingabe_erlaubt' als abgelehnt bestehen lässt.grüngeprüft am 2026-09-17
TestPruefmanager
test_standarddatei_vorschlagen_ja
Prüft, dass eine Ja-Antwort auf den Vorschlag der Standarddatei die Entscheidung 'ok' mit dem Standardpfad als Kontext liefert.grüngeprüft am 2026-09-17
TestPruefmanager
test_standarddatei_vorschlagen_nein
Prüft, dass eine Nein-Antwort auf den Vorschlag der Standarddatei die Aktion 'standarddatei_vorschlagen' als abgelehnt bestehen lässt.grüngeprüft am 2026-09-17
TestPruefmanager
test_temporaer_erlaubt_ja
Prüft, dass eine Ja-Antwort auf die Rückfrage nach einer temporären Datei die Aktion 'temporaer_erzeugen' auslöst.grüngeprüft am 2026-09-17
TestPruefmanager
test_temporaer_erlaubt_nein
Prüft, dass eine Nein-Antwort auf die Rückfrage nach einer temporären Datei die Aktion 'temporaer_erlaubt' als abgelehnt bestehen lässt.grüngeprüft am 2026-09-17
TestPruefmanager
test_layer_unsichtbar_ja
Prüft, dass eine Ja-Antwort bei unsichtbarem Layer den Layer sichtbar schaltet und die Entscheidung 'ok' liefert.grüngeprüft am 2026-09-17
TestPruefmanager
test_layer_unsichtbar_nein
Prüft, dass eine Nein-Antwort bei unsichtbarem Layer die Aktion 'layer_unsichtbar' als abgelehnt bestehen lässt.grüngeprüft am 2026-09-17
TestPruefmanager
test_unbekannte_aktion
Prüft, dass eine unbekannte Aktion eine Warnung auslöst und unverarbeitet als Fehlschlag zurückgegeben wird.grüngeprüft am 2026-09-17
TestPruefmanager
test_datei_existiert_overwrite
Prüft, dass die Nutzerwahl 'überschreiben' bei bestehender Datei zur Aktion 'datei_existiert_ueberschreiben' führt.grüngeprüft am 2026-09-17
TestPruefmanager
test_datei_existiert_append
Prüft, dass die Nutzerwahl 'anhängen' bei bestehender Datei zur Aktion 'datei_existiert_anhaengen' führt.grüngeprüft am 2026-09-17
TestPruefmanager
test_datei_existiert_cancel
Prüft, dass die Nutzerwahl 'abbrechen' bei bestehender Datei zur Aktion 'datei_existiert_ueberspringen' führt.grüngeprüft am 2026-09-17
TestPruefmanager
test_datei_existiert_in_non_qgis_mode_returns_input
Prüft, dass außerhalb des QGIS-Modus bei bestehender Datei keine Rückfrage erfolgt, sondern die ursprüngliche Aktion unentschieden zurückgegeben wird.grüngeprüft am 2026-09-17
TestPruefmanager
test_verfahrensgebiet_layer_existiert_ergaenzen
Prüft, dass die Nutzerwahl 'ergänzen' bei bestehendem Verfahrensgebiet zur Aktion 'verfahrensgebiet_ergaenzen' führt.grünnie geprüft
TestPruefmanager
test_verfahrensgebiet_layer_existiert_abbrechen
Prüft, dass die Nutzerwahl 'abbrechen' bei bestehendem Verfahrensgebiet ok=False mit Aktion 'verfahrensgebiet_abbrechen' liefert.grünnie geprüft
TestPruefmanager
test_verfahrensgebiet_layer_existiert_in_non_qgis_mode_returns_input
Prüft, dass außerhalb des QGIS-Modus bei bestehendem Verfahrensgebiet keine Rückfrage erfolgt.grünnie geprüft
TestPruefmanager
test_report_error_kritische_aktion_ruft_error_auf
Prüft, dass eine kritische Aktion (z. B. 'netzwerkfehler') über error() gemeldet wird, nicht über warning().grünnie geprüft
TestPruefmanager
test_report_error_warn_aktion_ruft_warning_auf
Prüft, dass eine Warn-Aktion (z. B. 'datei_nicht_gefunden') über warning() gemeldet wird, nicht über error().grünnie geprüft
TestPruefmanager
test_report_error_unbekannte_aktion_faellt_auf_warning_zurueck
Prüft, dass eine nicht eingestufte Aktion als Fallback über warning() gemeldet wird.grünnie geprüft
TestPruefmanager
test_frage_ja_nein_im_qgis_modus_fragt_nutzer
Prüft, dass frage_ja_nein im QGIS-Modus den Nutzer fragt und dessen Antwort liefert.grünnie geprüft
TestPruefmanager
test_frage_ja_nein_ausserhalb_qgis_liefert_default_ohne_rueckfrage
Prüft, dass frage_ja_nein außerhalb des QGIS-Modus den Default-Wert liefert, ohne den Nutzer zu fragen.grünnie geprüft
TestPruefmanager
test_frage_text_im_qgis_modus_fragt_nutzer
Prüft, dass frage_text im QGIS-Modus den Nutzer fragt und Text plus OK-Status liefert.grünnie geprüft
TestPruefmanager
test_frage_text_ausserhalb_qgis_liefert_default_ohne_rueckfrage
Prüft, dass frage_text außerhalb des QGIS-Modus den Standardtext mit OK=True liefert, ohne den Nutzer zu fragen.grünnie geprüft

Tests für sn_basis/functions/qgiscore_wrapper.py::polygon_zu_linie/layer_exists_in_gpkg (Issue #65).

PolygonZuLinieTests 7LayerExistsInGpkgTests 4
flowchart TD
+  root(["test_qgiscore_wrapper_helpers.py"])
+  class root rootnode
+  root --> g1["PolygonZuLinieTests (7)"]
+  class g1 groupnode
+  g1 --> t1("none_liefert_none")
+  g1 --> t2("leere_geometrie_liefert_none")
+  g1 --> t3("stufe1_nutzt_boundary_wenn_vorhanden")
+  g1 --> t4("stufe2_extrahiert_ringe_bei_einfachem_polygon")
+  g1 --> t5("stufe2_extrahiert_alle_ringe_bei_multipolygon")
+  g1 --> t6("stufe3_fallback_wenn_keine_ringe_extrahierbar")
+  g1 --> t7("alle_stufen_scheitern_liefert_none")
+  root --> g2["LayerExistsInGpkgTests (4)"]
+  class g2 groupnode
+  g2 --> t8("fehlende_datei_liefert_false")
+  g2 --> t9("leerer_pfad_oder_layername_liefert_false")
+  g2 --> t10("vorhandener_layer_liefert_true")
+  g2 --> t11("fehlender_layer_liefert_false")
+  class t1 ok
+  class t2 ok
+  class t3 ok
+  class t4 ok
+  class t5 ok
+  class t6 ok
+  class t7 ok
+  class t8 ok
+  class t9 ok
+  class t10 ok
+  class t11 ok
+  classDef rootnode fill:#1f4038,stroke:#16302a,stroke-width:1px,color:#f4f1e8,font-weight:600;
+  classDef groupnode fill:#cfe0da,stroke:#5c8a7d,stroke-width:1px,color:#152420;
+  classDef ok fill:#dcefdc,stroke:#3f7d4a,stroke-width:1px,color:#1c3a20;
+  classDef warn fill:#f6ead9,stroke:#b5722a,stroke-width:1px,color:#4a2c08;
+  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
PolygonZuLinieTests
test_none_liefert_none
Prüft, dass polygon_zu_linie für None-Eingabe None liefert.grünnie geprüft
PolygonZuLinieTests
test_leere_geometrie_liefert_none
Prüft, dass eine leere Geometrie None liefert.grünnie geprüft
PolygonZuLinieTests
test_stufe1_nutzt_boundary_wenn_vorhanden
Prüft, dass eine Geometrie mit boundary() (QGIS 3.x-Pfad) deren Ergebnis direkt liefert.grünnie geprüft
PolygonZuLinieTests
test_stufe2_extrahiert_ringe_bei_einfachem_polygon
Prüft, dass ohne boundary() die Ringe eines einfachen Polygons manuell extrahiert werden.grünnie geprüft
PolygonZuLinieTests
test_stufe2_extrahiert_alle_ringe_bei_multipolygon
Prüft, dass bei einem MultiPolygon die Ringe aller Teilpolygone extrahiert werden.grünnie geprüft
PolygonZuLinieTests
test_stufe3_fallback_wenn_keine_ringe_extrahierbar
Prüft, dass bei fehlgeschlagener Ringextraktion auf convertToType zurückgefallen wird.grünnie geprüft
PolygonZuLinieTests
test_alle_stufen_scheitern_liefert_none
Prüft, dass polygon_zu_linie None liefert, wenn Ringextraktion und convertToType beide scheitern.grünnie geprüft
LayerExistsInGpkgTests
test_fehlende_datei_liefert_false
Prüft, dass eine nicht vorhandene GPKG-Datei False liefert.grünnie geprüft
LayerExistsInGpkgTests
test_leerer_pfad_oder_layername_liefert_false
Prüft, dass ein leerer Pfad oder Layername False liefert.grünnie geprüft
LayerExistsInGpkgTests
test_vorhandener_layer_liefert_true
Prüft, dass ein in gpkg_contents eingetragener Layername als vorhanden erkannt wird.grünnie geprüft
LayerExistsInGpkgTests
test_fehlender_layer_liefert_false
Prüft, dass ein nicht in gpkg_contents eingetragener Layername als nicht vorhanden gilt.grünnie geprüft

Tests für sn_basis/functions/qgisui_wrapper.py::add_layer_to_project (Issue #65).

AddLayerToProjectTests 4
flowchart TD
+  root(["test_qgisui_wrapper_helpers.py"])
+  class root rootnode
+  root --> g1["AddLayerToProjectTests (4)"]
+  class g1 groupnode
+  g1 --> t1("none_layer_liefert_false")
+  g1 --> t2("mock_modus_liefert_true_ohne_projektzugriff")
+  g1 --> t3("mit_qgis_fuegt_layer_dem_projekt_hinzu")
+  g1 --> t4("mit_qgis_fehler_liefert_false")
+  class t1 ok
+  class t2 ok
+  class t3 ok
+  class t4 ok
+  classDef rootnode fill:#1f4038,stroke:#16302a,stroke-width:1px,color:#f4f1e8,font-weight:600;
+  classDef groupnode fill:#cfe0da,stroke:#5c8a7d,stroke-width:1px,color:#152420;
+  classDef ok fill:#dcefdc,stroke:#3f7d4a,stroke-width:1px,color:#1c3a20;
+  classDef warn fill:#f6ead9,stroke:#b5722a,stroke-width:1px,color:#4a2c08;
+  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
AddLayerToProjectTests
test_none_layer_liefert_false
Prüft, dass add_layer_to_project für einen fehlenden Layer (None) False liefert.grünnie geprüft
AddLayerToProjectTests
test_mock_modus_liefert_true_ohne_projektzugriff
Prüft, dass im Mock-Modus (ohne QGIS) ein gültiger Layer True liefert, ohne das Projekt anzufassen.grünnie geprüft
AddLayerToProjectTests
test_mit_qgis_fuegt_layer_dem_projekt_hinzu
Prüft, dass bei verfügbarem QGIS der Layer über QgsProject.instance().addMapLayer hinzugefügt wird.grünnie geprüft
AddLayerToProjectTests
test_mit_qgis_fehler_liefert_false
Prüft, dass ein Fehler beim Hinzufügen zum Projekt abgefangen wird und False liefert.grünnie geprüft

— (Docstring fehlt)

TestSettingsLogic 4
flowchart TD
   root(["test_settings_logic.py"])
   class root rootnode
   root --> g1["TestSettingsLogic (4)"]
@@ -588,7 +805,30 @@
   classDef groupnode fill:#cfe0da,stroke:#5c8a7d,stroke-width:1px,color:#152420;
   classDef ok fill:#dcefdc,stroke:#3f7d4a,stroke-width:1px,color:#1c3a20;
   classDef warn fill:#f6ead9,stroke:#b5722a,stroke-width:1px,color:#4a2c08;
-  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
TestSettingsLogic
test_load
Prüft, dass load() jede bekannte Projektvariable genau einmal über get_variable() liest.grüngeprüft am 2026-09-17
TestSettingsLogic
test_save
Prüft, dass save() nur bekannte Variablen-Keys speichert und unbekannte Keys ignoriert.grüngeprüft am 2026-09-17
TestSettingsLogic
test_load_handles_partial_values_with_empty_fallback
Prüft, dass load() für jede Variable den (auch leeren) Wert von get_variable() unverändert übernimmt, selbst wenn nicht alle Variablen im Mock konfiguriert sind.grüngeprüft am 2026-09-17
TestSettingsLogic
test_save_empty_string_value_is_persisted
Prüft, dass save() einen leeren String als gültigen Wert speichert, statt ihn wie einen fehlenden Key zu behandeln.grüngeprüft am 2026-09-17

— (Docstring fehlt)

TestStilpruefer 4
flowchart TD
+  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
TestSettingsLogic
test_load
Prüft, dass load() jede bekannte Projektvariable genau einmal über get_variable() liest.grüngeprüft am 2026-09-17
TestSettingsLogic
test_save
Prüft, dass save() nur bekannte Variablen-Keys speichert und unbekannte Keys ignoriert.grüngeprüft am 2026-09-17
TestSettingsLogic
test_load_handles_partial_values_with_empty_fallback
Prüft, dass load() für jede Variable den (auch leeren) Wert von get_variable() unverändert übernimmt, selbst wenn nicht alle Variablen im Mock konfiguriert sind.grüngeprüft am 2026-09-17
TestSettingsLogic
test_save_empty_string_value_is_persisted
Prüft, dass save() einen leeren String als gültigen Wert speichert, statt ihn wie einen fehlenden Key zu behandeln.grüngeprüft am 2026-09-17

Tests für sn_basis/ui/tabs/settings_tab.py::save_data/load_data (Issue #65).

SaveDataTests 2LoadDataTests 4
flowchart TD
+  root(["test_settings_tab.py"])
+  class root rootnode
+  root --> g1["SaveDataTests (2)"]
+  class g1 groupnode
+  g1 --> t1("sammelt_text_und_combobox_werte_inklusive_landkreiskennzahl")
+  g1 --> t2("ohne_landkreis_dropdown_wird_keine_kennzahl_ergaenzt")
+  root --> g2["LoadDataTests (4)"]
+  class g2 groupnode
+  g2 --> t3("befuellt_textfelder_aus_gespeicherten_daten")
+  g2 --> t4("ohne_gespeicherten_wert_bleibt_textfeld_leer")
+  g2 --> t5("waehlt_combobox_eintrag_bei_bekanntem_namen")
+  g2 --> t6("unbekannter_gespeicherter_name_waehlt_ersten_eintrag")
+  class t1 ok
+  class t2 ok
+  class t3 ok
+  class t4 ok
+  class t5 ok
+  class t6 ok
+  classDef rootnode fill:#1f4038,stroke:#16302a,stroke-width:1px,color:#f4f1e8,font-weight:600;
+  classDef groupnode fill:#cfe0da,stroke:#5c8a7d,stroke-width:1px,color:#152420;
+  classDef ok fill:#dcefdc,stroke:#3f7d4a,stroke-width:1px,color:#1c3a20;
+  classDef warn fill:#f6ead9,stroke:#b5722a,stroke-width:1px,color:#4a2c08;
+  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
SaveDataTests
test_sammelt_text_und_combobox_werte_inklusive_landkreiskennzahl
Prüft, dass save_data Text- und Dropdown-Werte sammelt und die Landkreiskennzahl separat ergänzt.grünnie geprüft
SaveDataTests
test_ohne_landkreis_dropdown_wird_keine_kennzahl_ergaenzt
Prüft, dass ohne Landkreis-Dropdown im Formular keine 'landkreis_kennzahl' ergänzt wird.grünnie geprüft
LoadDataTests
test_befuellt_textfelder_aus_gespeicherten_daten
Prüft, dass load_data ein Textfeld mit dem gespeicherten Wert befüllt.grünnie geprüft
LoadDataTests
test_ohne_gespeicherten_wert_bleibt_textfeld_leer
Prüft, dass load_data ohne gespeicherten Wert das Textfeld auf einen leeren Text setzt.grünnie geprüft
LoadDataTests
test_waehlt_combobox_eintrag_bei_bekanntem_namen
Prüft, dass load_data im Landkreis-Dropdown den gespeicherten Landkreisnamen auswählt.grünnie geprüft
LoadDataTests
test_unbekannter_gespeicherter_name_waehlt_ersten_eintrag
Prüft, dass load_data bei einem nicht mehr vorhandenen Landkreisnamen auf den ersten Eintrag zurückfällt.grünnie geprüft

— (Docstring fehlt)

TestStilpruefer 4
flowchart TD
   root(["test_stilpruefer.py"])
   class root rootnode
   root --> g1["TestStilpruefer (4)"]
@@ -605,18 +845,34 @@
   classDef groupnode fill:#cfe0da,stroke:#5c8a7d,stroke-width:1px,color:#152420;
   classDef ok fill:#dcefdc,stroke:#3f7d4a,stroke-width:1px,color:#1c3a20;
   classDef warn fill:#f6ead9,stroke:#b5722a,stroke-width:1px,color:#4a2c08;
-  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
TestStilpruefer
test_keine_datei_angegeben
Prüft, dass eine leere Pfadangabe als 'ok' ohne Kontext akzeptiert wird (Stil ist optional).grüngeprüft am 2026-09-17
TestStilpruefer
test_datei_existiert_mit_qml
Prüft, dass eine existierende .qml-Datei als 'stil_anwendbar' bestätigt wird.grüngeprüft am 2026-09-17
TestStilpruefer
test_datei_existiert_falsche_endung
Prüft, dass eine existierende Datei ohne .qml-Endung als 'falsche_endung' abgelehnt wird.grüngeprüft am 2026-09-17
TestStilpruefer
test_datei_existiert_nicht
Prüft, dass ein nicht existierender .qml-Pfad als 'datei_nicht_gefunden' abgelehnt wird.grüngeprüft am 2026-09-17

Unit-Tests für sn_basis.functions.sys_wrapper.get_plugin_root().

TestGetPluginRoot 1
flowchart TD
+  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
TestStilpruefer
test_keine_datei_angegeben
Prüft, dass eine leere Pfadangabe als 'ok' ohne Kontext akzeptiert wird (Stil ist optional).grüngeprüft am 2026-09-17
TestStilpruefer
test_datei_existiert_mit_qml
Prüft, dass eine existierende .qml-Datei als 'stil_anwendbar' bestätigt wird.grüngeprüft am 2026-09-17
TestStilpruefer
test_datei_existiert_falsche_endung
Prüft, dass eine existierende Datei ohne .qml-Endung als 'falsche_endung' abgelehnt wird.grüngeprüft am 2026-09-17
TestStilpruefer
test_datei_existiert_nicht
Prüft, dass ein nicht existierender .qml-Pfad als 'datei_nicht_gefunden' abgelehnt wird.grüngeprüft am 2026-09-17

Unit-Tests für sn_basis.functions.sys_wrapper.get_plugin_root().

TestGetPluginRoot 1JoinPathTests 1EnsureDirTests 2GetattrSafeTests 2
flowchart TD
   root(["test_sys_wrapper.py"])
   class root rootnode
   root --> g1["TestGetPluginRoot (1)"]
   class g1 groupnode
   g1 --> t1("get_plugin_root_folgt_keiner_verzeichnisverknuepfung")
+  root --> g2["JoinPathTests (1)"]
+  class g2 groupnode
+  g2 --> t2("verbindet_mehrere_pfadbestandteile")
+  root --> g3["EnsureDirTests (2)"]
+  class g3 groupnode
+  g3 --> t3("legt_fehlendes_verzeichnis_inklusive_eltern_an")
+  g3 --> t4("vorhandenes_verzeichnis_wirft_keinen_fehler")
+  root --> g4["GetattrSafeTests (2)"]
+  class g4 groupnode
+  g4 --> t5("liefert_vorhandenes_attribut")
+  g4 --> t6("liefert_default_bei_fehlendem_attribut")
   class t1 ok
+  class t2 ok
+  class t3 ok
+  class t4 ok
+  class t5 ok
+  class t6 ok
   classDef rootnode fill:#1f4038,stroke:#16302a,stroke-width:1px,color:#f4f1e8,font-weight:600;
   classDef groupnode fill:#cfe0da,stroke:#5c8a7d,stroke-width:1px,color:#152420;
   classDef ok fill:#dcefdc,stroke:#3f7d4a,stroke-width:1px,color:#1c3a20;
   classDef warn fill:#f6ead9,stroke:#b5722a,stroke-width:1px,color:#4a2c08;
-  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
TestGetPluginRoot
test_get_plugin_root_folgt_keiner_verzeichnisverknuepfung
Prüft, dass get_plugin_root() bei einem über eine Verzeichnisverknüpfung (wie von link_qgis_profile.py angelegt) erreichten Modul den verlinkten Pfad liefert, statt zum echten Zielverzeichnis aufzulösen (Verfahrensgebiet #50).grüngeprüft am 2026-09-17

Unit-Tests für `sn_basis.functions.text_wrapper`.

TestSanitizeBezeichner 7
flowchart TD
+  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
TestGetPluginRoot
test_get_plugin_root_folgt_keiner_verzeichnisverknuepfung
Prüft, dass get_plugin_root() bei einem über eine Verzeichnisverknüpfung (wie von link_qgis_profile.py angelegt) erreichten Modul den verlinkten Pfad liefert, statt zum echten Zielverzeichnis aufzulösen (Verfahrensgebiet #50).grüngeprüft am 2026-09-17
JoinPathTests
test_verbindet_mehrere_pfadbestandteile
Prüft, dass join_path mehrere Bestandteile OS-sicher zu einem Path zusammenfügt.grünnie geprüft
EnsureDirTests
test_legt_fehlendes_verzeichnis_inklusive_eltern_an
Prüft, dass ensure_dir ein fehlendes Verzeichnis samt Elternverzeichnissen anlegt.grünnie geprüft
EnsureDirTests
test_vorhandenes_verzeichnis_wirft_keinen_fehler
Prüft, dass ensure_dir bei einem bereits vorhandenen Verzeichnis keinen Fehler wirft.grünnie geprüft
GetattrSafeTests
test_liefert_vorhandenes_attribut
Prüft, dass getattr_safe ein vorhandenes Attribut liefert.grünnie geprüft
GetattrSafeTests
test_liefert_default_bei_fehlendem_attribut
Prüft, dass getattr_safe bei fehlendem Attribut den Default-Wert liefert.grünnie geprüft

Unit-Tests für `sn_basis.functions.text_wrapper`.

TestSanitizeBezeichner 7
flowchart TD
   root(["test_text_wrapper.py"])
   class root rootnode
   root --> g1["TestSanitizeBezeichner (7)"]
@@ -660,7 +916,7 @@
   classDef groupnode fill:#cfe0da,stroke:#5c8a7d,stroke-width:1px,color:#152420;
   classDef ok fill:#dcefdc,stroke:#3f7d4a,stroke-width:1px,color:#1c3a20;
   classDef warn fill:#f6ead9,stroke:#b5722a,stroke-width:1px,color:#4a2c08;
-  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
TestVariableWrapper
test_set_variable_project_noop_write_is_skipped
Prüft, dass set_variable() im Projekt-Scope nicht schreibt, wenn der neue Wert dem bestehenden entspricht.grünnie geprüft
TestVariableWrapper
test_set_variable_project_changed_value_is_written
Prüft, dass set_variable() im Projekt-Scope bei geändertem Wert mit dem Präfix 'sn_' geschrieben wird.grünnie geprüft
TestVariableWrapper
test_set_variable_global_writes_prefixed_name
Prüft, dass set_variable() im globalen Scope den Variablennamen mit 'sn_' vorangestellt schreibt.grünnie geprüft
TestVariableWrapper
test_get_variable_global_returns_empty_string_fallback
Prüft, dass get_variable() im globalen Scope für eine nicht gesetzte Variable einen leeren String liefert.grünnie geprüft
TestVariableWrapper
test_get_variable_invalid_scope_raises
Prüft, dass get_variable() bei einem unbekannten Scope-Namen einen ValueError auslöst.grünnie geprüft
TestVariableWrapper
test_set_variable_invalid_scope_raises
Prüft, dass set_variable() bei einem unbekannten Scope-Namen einen ValueError auslöst.grünnie geprüft

— (Docstring fehlt)

TestVerfahrensgebietManager 5
flowchart TD
+  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
TestVariableWrapper
test_set_variable_project_noop_write_is_skipped
Prüft, dass set_variable() im Projekt-Scope nicht schreibt, wenn der neue Wert dem bestehenden entspricht.grünnie geprüft
TestVariableWrapper
test_set_variable_project_changed_value_is_written
Prüft, dass set_variable() im Projekt-Scope bei geändertem Wert mit dem Präfix 'sn_' geschrieben wird.grünnie geprüft
TestVariableWrapper
test_set_variable_global_writes_prefixed_name
Prüft, dass set_variable() im globalen Scope den Variablennamen mit 'sn_' vorangestellt schreibt.grünnie geprüft
TestVariableWrapper
test_get_variable_global_returns_empty_string_fallback
Prüft, dass get_variable() im globalen Scope für eine nicht gesetzte Variable einen leeren String liefert.grünnie geprüft
TestVariableWrapper
test_get_variable_invalid_scope_raises
Prüft, dass get_variable() bei einem unbekannten Scope-Namen einen ValueError auslöst.grünnie geprüft
TestVariableWrapper
test_set_variable_invalid_scope_raises
Prüft, dass set_variable() bei einem unbekannten Scope-Namen einen ValueError auslöst.grünnie geprüft

Tests für sn_basis/functions/verfahrensgebiet_manager.py (zentrale Layer-Verfolgung, Issue #65).

TestVerfahrensgebietManager 5OnHandlerTests 5ListenerSetupTests 3
flowchart TD
   root(["test_verfahrensgebiet_manager.py"])
   class root rootnode
   root --> g1["TestVerfahrensgebietManager (5)"]
@@ -670,41 +926,50 @@
   g1 --> t3("set_verfahrensgebiet_layer_id_writes_project_variable")
   g1 --> t4("update_without_layer_does_not_write_when_already_empty")
   g1 --> t5("update_with_layer_writes_variable")
+  root --> g2["OnHandlerTests (5)"]
+  class g2 groupnode
+  g2 --> t6("on_project_changed_ohne_layer_setzt_variable_leer")
+  g2 --> t7("on_project_changed_mit_layer_setzt_variable")
+  g2 --> t8("on_layers_added_findet_neuen_layer")
+  g2 --> t9("on_layer_removed_bei_aktuellem_layer_sucht_neu")
+  g2 --> t10("on_layer_removed_bei_anderem_layer_aendert_nichts")
+  root --> g3["ListenerSetupTests (3)"]
+  class g3 groupnode
+  g3 --> t11("setup_ohne_qgis_tut_nichts")
+  g3 --> t12("setup_verbindet_signale_und_ist_idempotent")
+  g3 --> t13("teardown_trennt_alle_signale_und_ist_idempotent")
   class t1 ok
   class t2 ok
   class t3 ok
   class t4 ok
   class t5 ok
+  class t6 ok
+  class t7 ok
+  class t8 ok
+  class t9 ok
+  class t10 ok
+  class t11 ok
+  class t12 ok
+  class t13 ok
   classDef rootnode fill:#1f4038,stroke:#16302a,stroke-width:1px,color:#f4f1e8,font-weight:600;
   classDef groupnode fill:#cfe0da,stroke:#5c8a7d,stroke-width:1px,color:#152420;
   classDef ok fill:#dcefdc,stroke:#3f7d4a,stroke-width:1px,color:#1c3a20;
   classDef warn fill:#f6ead9,stroke:#b5722a,stroke-width:1px,color:#4a2c08;
-  classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
TestVerfahrensgebietManager
test_get_verfahrensgebiet_layer_id_returns_value
Prüft, dass get_verfahrensgebiet_layer_id() die in der Projektvariable gespeicherte Layer-ID liefert.grünnie geprüft
TestVerfahrensgebietManager
test_get_verfahrensgebiet_layer_id_returns_none_for_empty_value
Prüft, dass get_verfahrensgebiet_layer_id() bei leerer Projektvariable None statt eines leeren Strings liefert.grünnie geprüft
TestVerfahrensgebietManager
test_set_verfahrensgebiet_layer_id_writes_project_variable
Prüft, dass set_verfahrensgebiet_layer_id() die Layer-ID als Projektvariable 'verfahrensgebiet_layer' speichert.grünnie geprüft
TestVerfahrensgebietManager
test_update_without_layer_does_not_write_when_already_empty
Prüft, dass ohne gefundenen Verfahrensgebiet-Layer keine Schreibaktion erfolgt, wenn die Variable bereits leer ist.grünnie geprüft
TestVerfahrensgebietManager
test_update_with_layer_writes_variable
Prüft, dass ein gefundener Verfahrensgebiet-Layer seine ID als Projektvariable speichert.grünnie geprüft
+ classDef skip fill:#e6e6ee,stroke:#6f7285,stroke-width:1px,color:#2b2d38;
TestfallprüftStatusgeprüft
TestVerfahrensgebietManager
test_get_verfahrensgebiet_layer_id_returns_value
Prüft, dass get_verfahrensgebiet_layer_id() die in der Projektvariable gespeicherte Layer-ID liefert.grünnie geprüft
TestVerfahrensgebietManager
test_get_verfahrensgebiet_layer_id_returns_none_for_empty_value
Prüft, dass get_verfahrensgebiet_layer_id() bei leerer Projektvariable None statt eines leeren Strings liefert.grünnie geprüft
TestVerfahrensgebietManager
test_set_verfahrensgebiet_layer_id_writes_project_variable
Prüft, dass set_verfahrensgebiet_layer_id() die Layer-ID als Projektvariable 'verfahrensgebiet_layer' speichert.grünnie geprüft
TestVerfahrensgebietManager
test_update_without_layer_does_not_write_when_already_empty
Prüft, dass ohne gefundenen Verfahrensgebiet-Layer keine Schreibaktion erfolgt, wenn die Variable bereits leer ist.grünnie geprüft
TestVerfahrensgebietManager
test_update_with_layer_writes_variable
Prüft, dass ein gefundener Verfahrensgebiet-Layer seine ID als Projektvariable speichert.grünnie geprüft
OnHandlerTests
test_on_project_changed_ohne_layer_setzt_variable_leer
Prüft, dass _on_project_changed die Variable leert, wenn kein Verfahrensgebiet-Layer existiert.grünnie geprüft
OnHandlerTests
test_on_project_changed_mit_layer_setzt_variable
Prüft, dass _on_project_changed die Layer-ID eines gefundenen Verfahrensgebiet-Layers übernimmt.grünnie geprüft
OnHandlerTests
test_on_layers_added_findet_neuen_layer
Prüft, dass _on_layers_added nach neu hinzugefügten Layern sucht und die Variable aktualisiert.grünnie geprüft
OnHandlerTests
test_on_layer_removed_bei_aktuellem_layer_sucht_neu
Prüft, dass das Entfernen des aktuell aktiven Verfahrensgebiet-Layers eine Neusuche auslöst.grünnie geprüft
OnHandlerTests
test_on_layer_removed_bei_anderem_layer_aendert_nichts
Prüft, dass das Entfernen eines anderen Layers keine Neusuche auslöst.grünnie geprüft
ListenerSetupTests
test_setup_ohne_qgis_tut_nichts
Prüft, dass setup_verfahrensgebiet_listener ohne QGIS keine Signale registriert.grünnie geprüft
ListenerSetupTests
test_setup_verbindet_signale_und_ist_idempotent
Prüft, dass setup_verfahrensgebiet_listener die Projektsignale verbindet und ein zweiter Aufruf nichts doppelt registriert.grünnie geprüft
ListenerSetupTests
test_teardown_trennt_alle_signale_und_ist_idempotent
Prüft, dass teardown_verfahrensgebiet_listener alle Signale trennt und mehrfacher Aufruf nicht fehlschlägt.grünnie geprüft
-

Ungetestete Funktionen (strukturell) – 156 von 229

+

Ungetestete Funktionen (strukturell) – 115 von 229

Heuristik: Name kommt in keiner Testdatei des Pakets vor. Details siehe docs/tests/testkatalog.md.

- - - - - - - - - - - @@ -712,41 +977,22 @@ - - - - - - - - - - - - - - - - - - - @@ -791,19 +1037,12 @@ - - - - - - - @@ -824,9 +1063,7 @@ - - @@ -837,9 +1074,7 @@ - - -
DateiFunktion/MethodeZeile
functions/dialog_wrapper.pyshow_info_dialog42
functions/dialog_wrapper.pyask_text56
functions/dialog_wrapper.pyask_ergaenzen_entfernen_ersetzen_abbrechen131
functions/dialog_wrapper.pyask_detailpruefung_oder_vg_laden185
functions/dialog_wrapper.pyask_detailpruefung_oder_abbrechen235
functions/dialog_wrapper.pyProgressDialog.set_total328
functions/dialog_wrapper.pyProgressDialog.set_value336
functions/dialog_wrapper.pyProgressDialog.set_label348
functions/dialog_wrapper.pyProgressDialog.is_canceled357
functions/dialog_wrapper.pyProgressDialog.close366
functions/dialog_wrapper.pyProgressDialog.raise_to_front373
functions/dialog_wrapper.pycreate_progress_dialog390
functions/landkreise.py_lade_landkreise20
functions/ly_existence_wrapper.pylayer_is_valid10
functions/ly_existence_wrapper.pylayer_is_usable27
functions/ly_style_wrapper.pyapply_style_from_path8
functions/ly_style_wrapper.pyapply_style27
functions/message_wrapper.py_get_message_bar15
functions/message_wrapper.pypush_message42
functions/message_wrapper.pyinfo67
functions/message_wrapper.pyerror77
functions/message_wrapper.pysuccess82
functions/os_wrapper.pynormalize_path43
functions/os_wrapper.pyget_home_dir53
functions/os_wrapper.pybasename68
functions/os_wrapper.pyis_case_sensitive_fs80
functions/os_wrapper.pypath_suffix96
functions/qgiscore_wrapper.pylayer_exists_in_gpkg1019
functions/qgiscore_wrapper.pypolygon_zu_linie1058
functions/qgisui_wrapper.pyget_main_window131
functions/qgisui_wrapper.pyadd_dock_widget149
functions/qgisui_wrapper.pyremove_dock_widget156
functions/qgisui_wrapper.pyfind_dock_widgets163
functions/qgisui_wrapper.pyadd_menu178
functions/qgisui_wrapper.pyremove_menu188
functions/qgisui_wrapper.pyadd_toolbar201
functions/qgisui_wrapper.pyremove_toolbar208
functions/qgisui_wrapper.pyadd_layer_to_project217
functions/qt_wrapper.pyexec_dialog60
functions/qt_wrapper.pydebug_qt_status64
functions/sys_wrapper.pyjoin_path36
functions/sys_wrapper.pyensure_dir56
functions/sys_wrapper.pygetattr_safe102
functions/verfahrensgebiet_manager.py_on_layers_added109
functions/verfahrensgebiet_manager.py_on_layer_removed114
functions/verfahrensgebiet_manager.py_on_project_changed123
functions/verfahrensgebiet_manager.pysetup_verfahrensgebiet_listener132
functions/verfahrensgebiet_manager.pyteardown_verfahrensgebiet_listener176
modules/DataGrabber.pyDataGrabber.set_source68
modules/DataGrabber.pyDataGrabber._process_database_source309
modules/DataGrabber.pyDataGrabber._process_service_source320
modules/DataGrabber.pyDataGrabber._aggregate_results330
modules/Dateipruefer.pyDateipruefer.erkenne_dateityp77
modules/Dateipruefer.pyDateipruefer._pfad91
modules/Dateipruefer.pyDateipruefer._ist_leer98
modules/Dateipruefer.pyDateipruefer._ist_gueltiger_gpkg_pfad113
modules/Dateipruefer.pyDateipruefer._handle_leere_eingabe227
modules/Datenschreiber.pyDatenschreiber._store_style_in_gpkg77
modules/LayerLoader.pyLayerLoader._was_canceled42
modules/LayerLoader.pyLayerLoader._process_events50
modules/LayerLoader.pyLayerLoader.apply_style190
modules/linkpruefer.pyLinkpruefer._pfad33
modules/linkpruefer.pyLinkpruefer._ist_url41
modules/linkpruefer.pyLinkpruefer._pruefe_url81
modules/linkpruefer.pyLinkpruefer._pruefe_dateipfad115
modules/print_logic.pyPrintLogic._get_plot_dimensions_mm1052
modules/print_logic.pyPrintLogic._get_required_map_dimensions_mm1061
modules/print_logic.pyPrintLogic.druckvorlage_anlegen1161
modules/pruef_ergebnis.pypruef_ergebnis.ist_verfahrens_db_aktion149
modules/pruef_ergebnis.pypruef_ergebnis.dateipfad167
modules/pruef_ergebnis.pypruef_ergebnis.erlaubte_persistierung181
modules/Pruefmanager.pyPruefmanager.report_error20
modules/Pruefmanager.pyPruefmanager.report_summary45
modules/Pruefmanager.pyPruefmanager.zeige_hinweis62
modules/Pruefmanager.pyPruefmanager.frage_ja_nein67
modules/Pruefmanager.pyPruefmanager.frage_text73
modules/Pruefmanager.pyPruefmanager._handle_datei_existiert83
modules/Pruefmanager.pyPruefmanager._handle_verfahrensgebiet_layer_existiert230
modules/Pruefmanager.pyPruefmanager._ask_use_or_replace_pufferlayer273
ui/base_dockwidget.pyBaseDockWidget.closeEvent97
ui/dockmanager.pyDockManager.show30
ui/navigation.pyNavigation.init_ui33
ui/navigation.pyNavigation.add_action68
ui/navigation.pyNavigation.finalize_menu_and_toolbar81
ui/tabs/print_tab.pyPrintTab._format_druckpuffer_label425
ui/tabs/print_tab.pyPrintTab._on_vorlage_erstellen428
ui/tabs/print_tab.pyPrintTab._disconnect_project_signals441
ui/tabs/print_tab.pyPrintTab.cleanup459
ui/tabs/print_tab.pyPrintTab._connect_project_signals464
ui/tabs/print_tab.pyPrintTab._on_project_changed482
ui/tabs/print_tab.pyPrintTab._toggle_atlas489
ui/tabs/print_tab.pyPrintTab._restore_atlas_layer_selection495
ui/tabs/print_tab.pyPrintTab._disconnect_theme_collection_signals519
ui/tabs/print_tab.pyPrintTab._on_atlas_layer_changed612
ui/tabs/print_tab.pyPrintTab._on_auswahl_as_atlas_clicked641
ui/tabs/print_tab.pyPrintTab._populate_atlas_layer_combo679
ui/tabs/settings_tab.pySettingsTab._build_input118
ui/tabs/settings_tab.pySettingsTab.save_data130
ui/tabs/settings_tab.pySettingsTab.load_data149
+ui/tabs/settings_tab.pySettingsTab._build_input118
diff --git a/docs/tests/testkatalog.md b/docs/tests/testkatalog.md index 06d44c2..b38db6b 100644 --- a/docs/tests/testkatalog.md +++ b/docs/tests/testkatalog.md @@ -10,19 +10,19 @@ selbst (Docstrings) und aus der Testbaseline. Stand der Baseline: `docs/status/testbaseline.json` (SHA-256 `aeabc946a7f3`) Stand des Prüf-Audits: `docs/status/testpruefungen.json` (SHA-256 `68b590c8feef`) -Gesamt: 3 Pakete, 36 Testdateien, 418 Testfälle – 375 grün, 35 rot (Baseline), 8 übersprungen. -Mit Beschreibung (Docstring): 273 von 418 (65 %). -Fachlich geprüft: 55 von 418 (13 %) aktuell, 0 veraltet seit Codeänderung, 363 nie geprüft. -Strukturelle Lücken (heuristisch, Namensabgleich): 229 von 413 (55 %) Funktionen/Methoden ohne erkennbaren Testbezug – Abschnitt „Ungetestete Funktionen“. +Gesamt: 3 Pakete, 46 Testdateien, 501 Testfälle – 458 grün, 35 rot (Baseline), 8 übersprungen. +Mit Beschreibung (Docstring): 356 von 501 (71 %). +Fachlich geprüft: 55 von 501 (11 %) aktuell, 0 veraltet seit Codeänderung, 446 nie geprüft. +Strukturelle Lücken (heuristisch, Namensabgleich): 188 von 413 (46 %) Funktionen/Methoden ohne erkennbaren Testbezug – Abschnitt „Ungetestete Funktionen“. ## Zusammenfassung | Paket | Testdateien | Testfälle | grün | rot (Baseline) | übersprungen | mit Beschreibung | fachlich geprüft | ohne Testbezug | | --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | -| `sn_basis` | 19 | 166 | 166 | 0 | 0 | 166 von 166 (100 %) | 55 von 166 (33 %) | 156 von 229 (68 %) | +| `sn_basis` | 29 | 249 | 249 | 0 | 0 | 249 von 249 (100 %) | 55 von 249 (22 %) | 115 von 229 (50 %) | | `sn_verfahrensgebiet` | 12 | 208 | 166 | 34 | 8 | 106 von 208 (51 %) | 0 von 208 (0 %) | 34 von 104 (33 %) | | `sn_plan41` | 5 | 44 | 43 | 1 | 0 | 1 von 44 (2 %) | 0 von 44 (0 %) | 39 von 80 (49 %) | -| **Summe** | **36** | **418** | **375** | **35** | **8** | **273 von 418 (65 %)** | **55 von 418 (13 %)** | **229 von 413 (55 %)** | +| **Summe** | **46** | **501** | **458** | **35** | **8** | **356 von 501 (71 %)** | **55 von 501 (11 %)** | **188 von 413 (46 %)** | ### Legende @@ -36,7 +36,23 @@ Strukturelle Lücken (heuristisch, Namensabgleich): 229 von 413 (55 %) Funktione ## Paket `sn_basis` -Plattform-Plugin, Ordner `Plugin_SN_Basis` – 19 Testdateien mit 166 Testfällen (166 grün, 0 rot, 0 übersprungen). +Plattform-Plugin, Ordner `Plugin_SN_Basis` – 29 Testdateien mit 249 Testfällen (249 grün, 0 rot, 0 übersprungen). + +### `Plugin_SN_Basis/tests/test_base_dockwidget.py` + +Worum es in der Datei geht: Tests für sn_basis/ui/base_dockwidget.py::closeEvent (Issue #65). + +Testgruppen: + +- `CloseEventTests` (5 Testfälle): — (Docstring fehlt) + +| Testfall | prüft | Status | geprüft | +| --- | --- | --- | --- | +| `CloseEventTests.test_ruft_cleanup_aller_tabs_auf` | Prüft, dass closeEvent cleanup() auf allen Tabs des Dock-Widgets aufruft. | grün | nie geprüft | +| `CloseEventTests.test_ignoriert_tabs_ohne_cleanup` | Prüft, dass ein Tab ohne cleanup()-Methode nicht zu einem Fehler führt. | grün | nie geprüft | +| `CloseEventTests.test_fehler_in_cleanup_wird_abgefangen_und_andere_tabs_laufen_weiter` | Prüft, dass ein Fehler in cleanup() eines Tabs nicht die übrigen Tabs verhindert. | grün | nie geprüft | +| `CloseEventTests.test_setzt_toolbar_action_zurueck` | Prüft, dass closeEvent die verknüpfte Toolbar-Action auf 'nicht gedrückt' zurücksetzt. | grün | nie geprüft | +| `CloseEventTests.test_ohne_action_wird_nichts_zurueckgesetzt` | Prüft, dass closeEvent ohne verknüpfte Toolbar-Action keine Ausnahme wirft. | grün | nie geprüft | ### `Plugin_SN_Basis/tests/test_bootstrap.py` @@ -67,7 +83,7 @@ Worum es in der Datei geht: — (Docstring fehlt) Testgruppen: -- `TestDateipruefer` (6 Testfälle): — (Docstring fehlt) +- `TestDateipruefer` (12 Testfälle): — (Docstring fehlt) | Testfall | prüft | Status | geprüft | | --- | --- | --- | --- | @@ -77,6 +93,12 @@ Testgruppen: | `TestDateipruefer.test_temporaer_erlaubt` | Prüft, dass eine leere Pfadangabe bei temporaer_erlaubt=True als 'temporaer_erlaubt' ohne Kontext gemeldet wird. | grün | geprüft am 2026-09-17 | | `TestDateipruefer.test_datei_nicht_gefunden` | Prüft, dass ein nicht existierender Dateipfad als 'datei_nicht_gefunden' mit dem Pfad als Kontext abgelehnt wird. | grün | geprüft am 2026-09-17 | | `TestDateipruefer.test_datei_ok` | Prüft, dass ein existierender Dateipfad als 'ok' mit dem Pfad als Kontext bestätigt wird. | grün | geprüft am 2026-09-17 | +| `TestDateipruefer.test_erkenne_dateityp_unterscheidet_excel_datenbank_und_unbekannt` | Prüft, dass erkenne_dateityp .xlsx als 'excel', .gpkg/.sqlite als 'datenbank' und Rest als 'unbekannt' erkennt. | grün | nie geprüft | +| `TestDateipruefer.test_pfad_verbindet_relativen_pfad_mit_basispfad` | Prüft, dass _pfad einen relativen Pfad mit dem Basisverzeichnis verbindet. | grün | nie geprüft | +| `TestDateipruefer.test_pfad_laesst_absoluten_pfad_unveraendert` | Prüft, dass _pfad einen bereits absoluten Pfad nicht mit dem Basisverzeichnis verbindet. | grün | nie geprüft | +| `TestDateipruefer.test_ist_gueltiger_gpkg_pfad_akzeptiert_vorhandenes_verzeichnis` | Prüft, dass ein .gpkg-Pfad mit vorhandenem Zielverzeichnis als gültig gilt. | grün | nie geprüft | +| `TestDateipruefer.test_ist_gueltiger_gpkg_pfad_lehnt_falsche_endung_ab` | Prüft, dass ein Pfad ohne .gpkg-Endung als ungültig gilt, auch bei vorhandenem Verzeichnis. | grün | nie geprüft | +| `TestDateipruefer.test_ist_gueltiger_gpkg_pfad_lehnt_fehlendes_verzeichnis_ab` | Prüft, dass ein .gpkg-Pfad in einem nicht vorhandenen Verzeichnis als ungültig gilt. | grün | nie geprüft | ### `Plugin_SN_Basis/tests/test_datenabruf.py` @@ -145,6 +167,23 @@ Testgruppen: | `SchreibeLogTests.test_ohne_speicherort_wirft_valueerror` | Prüft, dass schreibe_log ohne Speicherort einen ValueError wirft. | grün | nie geprüft | | `SchreibeLogTests.test_schreibt_json_datei_mit_ergebnissen_und_gibt_pfad_zurueck` | Prüft, dass schreibe_log eine lesbare JSON-Log-Datei erzeugt und deren Pfad zurückgibt. | grün | nie geprüft | +### `Plugin_SN_Basis/tests/test_dockmanager.py` + +Worum es in der Datei geht: Tests für sn_basis/ui/dockmanager.py (nur ein Dock gleichzeitig sichtbar, Issue #65). + +Testgruppen: + +- `DockManagerShowTests` (6 Testfälle): — (Docstring fehlt) + +| Testfall | prüft | Status | geprüft | +| --- | --- | --- | --- | +| `DockManagerShowTests.test_none_dock_meldet_fehler_und_zeigt_nichts_an` | Prüft, dass ein fehlendes Dock-Widget (None) einen Fehler meldet und nichts anzeigt. | grün | nie geprüft | +| `DockManagerShowTests.test_setzt_objectname_wenn_leer` | Prüft, dass ein Dock ohne Namen einen technischen Namen mit dem Präfix 'sn_dock_' erhält. | grün | nie geprüft | +| `DockManagerShowTests.test_entfernt_andere_sn_docks_aber_nicht_sich_selbst` | Prüft, dass andere sn_basis-Docks entfernt werden, das neue Dock und fremde Widgets aber unangetastet bleiben. | grün | nie geprüft | +| `DockManagerShowTests.test_zeigt_neues_dock_mit_default_area_an` | Prüft, dass ein neues Dock mit der Standard-Area (DockAreaRight) angezeigt wird. | grün | nie geprüft | +| `DockManagerShowTests.test_fehler_beim_entfernen_wird_als_warnung_gemeldet` | Prüft, dass ein Fehler beim Entfernen alter Docks nur gewarnt und das neue Dock trotzdem angezeigt wird. | grün | nie geprüft | +| `DockManagerShowTests.test_fehler_beim_anzeigen_wird_gemeldet` | Prüft, dass ein Fehler beim Anzeigen des Docks als Fehler gemeldet wird. | grün | nie geprüft | + ### `Plugin_SN_Basis/tests/test_excel_importer.py` Worum es in der Datei geht: Tests für sn_basis/modules/excel_importer.py (Excel-Import für Linklisten, Issue #63). @@ -180,6 +219,19 @@ Testgruppen: | `TestGetLaenderkennung.test_ohne_argument_wird_aus_aufrufendem_modul_abgeleitet` | Prüft, dass ohne Argument der Präfix aus dem Modulnamen des Aufrufers abgeleitet wird. | grün | geprüft am 2026-09-17 | | `TestGetLaenderkennung.test_mapping_enthaelt_sachsen` | Prüft, dass die Mapping-Tabelle LAENDERKENNUNGEN einen Eintrag für Sachsen ('sn' -> '14') enthält. | grün | geprüft am 2026-09-17 | +### `Plugin_SN_Basis/tests/test_landkreise.py` + +Worum es in der Datei geht: Tests für sn_basis/functions/landkreise.py::_lade_landkreise (Issue #65). + +Testgruppen: + +- `LadeLandkreiseTests` (2 Testfälle): — (Docstring fehlt) + +| Testfall | prüft | Status | geprüft | +| --- | --- | --- | --- | +| `LadeLandkreiseTests.test_laedt_die_echte_landkreisliste_nicht_leer` | Prüft, dass _lade_landkreise die echte landkreise.json als nicht-leere Liste von (Kennzahl, Name)-Tupeln liefert. | grün | nie geprüft | +| `LadeLandkreiseTests.test_fehlende_datei_liefert_leere_liste` | Prüft, dass eine nicht lesbare Datenquelle eine leere Liste liefert, statt eine Ausnahme zu werfen. | grün | nie geprüft | + ### `Plugin_SN_Basis/tests/test_layerloader.py` Worum es in der Datei geht: Tests für sn_basis/modules/LayerLoader.py (Layer erzeugen/filtern/laden, Issue #63). @@ -259,6 +311,57 @@ Testgruppen: | `TestLinkpruefer.test_local_link_not_found` | Prüft, dass ein nicht existierender lokaler Pfad als 'pfad_nicht_gefunden' abgelehnt wird. | grün | geprüft am 2026-09-17 | | `TestLinkpruefer.test_local_link_ok` | Prüft, dass ein existierender lokaler Pfad als 'ok' bestätigt wird. | grün | geprüft am 2026-09-17 | +### `Plugin_SN_Basis/tests/test_ly_existence_wrapper.py` + +Worum es in der Datei geht: Tests für sn_basis/functions/ly_existence_wrapper.py::layer_is_valid/layer_is_usable (Issue #65). + +Testgruppen: + +- `LayerIsValidTests` (5 Testfälle): — (Docstring fehlt) +- `LayerIsUsableTests` (3 Testfälle): — (Docstring fehlt) + +| Testfall | prüft | Status | geprüft | +| --- | --- | --- | --- | +| `LayerIsValidTests.test_none_ist_nicht_gueltig` | Prüft, dass layer_is_valid für None False liefert. | grün | nie geprüft | +| `LayerIsValidTests.test_objekt_ohne_isvalid_ist_nicht_gueltig` | Prüft, dass ein Objekt ohne isValid()-Methode als ungültig gilt. | grün | nie geprüft | +| `LayerIsValidTests.test_gueltiger_layer_liefert_true` | Prüft, dass ein Layer mit isValid()==True als gültig erkannt wird. | grün | nie geprüft | +| `LayerIsValidTests.test_ungueltiger_layer_liefert_false` | Prüft, dass ein Layer mit isValid()==False als ungültig erkannt wird. | grün | nie geprüft | +| `LayerIsValidTests.test_ausnahme_bei_isvalid_liefert_false` | Prüft, dass eine Ausnahme in isValid() abgefangen wird und False liefert. | grün | nie geprüft | +| `LayerIsUsableTests.test_none_ist_nicht_nutzbar` | Prüft, dass layer_is_usable für None False liefert. | grün | nie geprüft | +| `LayerIsUsableTests.test_gueltiger_layer_ist_nutzbar` | Prüft, dass ein vorhandener, gültiger Layer als nutzbar gilt. | grün | nie geprüft | +| `LayerIsUsableTests.test_ungueltiger_layer_ist_nicht_nutzbar` | Prüft, dass ein vorhandener, aber ungültiger Layer als nicht nutzbar gilt. | grün | nie geprüft | + +### `Plugin_SN_Basis/tests/test_ly_style_wrapper.py` + +Worum es in der Datei geht: Tests für sn_basis/functions/ly_style_wrapper.py::apply_style_from_path (Issue #65). + +Testgruppen: + +- `ApplyStyleFromPathTests` (4 Testfälle): — (Docstring fehlt) + +| Testfall | prüft | Status | geprüft | +| --- | --- | --- | --- | +| `ApplyStyleFromPathTests.test_fehlender_layer_liefert_false` | Prüft, dass ein fehlender Layer (None) False liefert, ohne einen Stil zu laden. | grün | nie geprüft | +| `ApplyStyleFromPathTests.test_erfolgreiches_laden_liefert_true_und_triggert_repaint` | Prüft, dass ein erfolgreich geladener Stil True liefert und den Layer neu zeichnet. | grün | nie geprüft | +| `ApplyStyleFromPathTests.test_fehlgeschlagenes_laden_liefert_false_ohne_repaint` | Prüft, dass ein fehlgeschlagenes Laden False liefert, ohne den Layer neu zu zeichnen. | grün | nie geprüft | +| `ApplyStyleFromPathTests.test_ausnahme_beim_laden_wird_abgefangen` | Prüft, dass eine Ausnahme beim Laden des Stils abgefangen wird und False liefert. | grün | nie geprüft | + +### `Plugin_SN_Basis/tests/test_message_wrapper.py` + +Worum es in der Datei geht: Tests für sn_basis/functions/message_wrapper.py (Issue #65). + +Testgruppen: + +- `GetMessageBarTests` (2 Testfälle): — (Docstring fehlt) +- `PushMessageTests` (2 Testfälle): — (Docstring fehlt) + +| Testfall | prüft | Status | geprüft | +| --- | --- | --- | --- | +| `GetMessageBarTests.test_liefert_objekt_mit_pushmessage_methode` | Prüft, dass _get_message_bar ein Objekt mit aufrufbarer pushMessage()-Methode liefert. | grün | nie geprüft | +| `GetMessageBarTests.test_faellt_bei_fehlerhaftem_iface_auf_mock_bar_zurueck` | Prüft, dass ein Fehler beim Zugriff auf iface.messageBar() auf eine funktionierende Mock-MessageBar zurückfällt. | grün | nie geprüft | +| `PushMessageTests.test_liefert_dict_mit_titel_text_level_und_dauer` | Prüft, dass push_message im Mock-Modus ein Dict mit den übergebenen Werten liefert. | grün | nie geprüft | +| `PushMessageTests.test_fehler_in_der_message_bar_wird_abgefangen` | Prüft, dass eine fehlschlagende MessageBar push_message nicht zum Absturz bringt, sondern None liefert. | grün | nie geprüft | + ### `Plugin_SN_Basis/tests/test_print_layout.py` Worum es in der Datei geht: — (Docstring fehlt) @@ -303,13 +406,29 @@ Testgruppen: | `TestPrintLogic.test_resolve_extent_uses_canvas_extent_without_buffer` | Prüft, dass bei Druckbereich 'wie Kartenfenster' der Kartenausschnitt ohne Puffer und ohne verknüpften Layer übernommen wird. | grün | nie geprüft | | `TestPrintLogic.test_resolve_extent_uses_rectangle_extent_without_buffer` | Prüft, dass bei Druckbereich 'Rechteck' der gezeichnete Ausschnitt ohne Puffer und ohne verknüpften Layer übernommen wird. | grün | nie geprüft | +### `Plugin_SN_Basis/tests/test_pruef_ergebnis.py` + +Worum es in der Datei geht: Tests für sn_basis/modules/pruef_ergebnis.py::ist_verfahrens_db_aktion/erlaubte_persistierung (Issue #65). + +Testgruppen: + +- `IstVerfahrensDbAktionTests` (2 Testfälle): — (Docstring fehlt) +- `ErlaubtePersistierungTests` (2 Testfälle): — (Docstring fehlt) + +| Testfall | prüft | Status | geprüft | +| --- | --- | --- | --- | +| `IstVerfahrensDbAktionTests.test_liefert_true_fuer_alle_verfahrens_db_aktionen` | Prüft, dass ist_verfahrens_db_aktion für alle vier Verfahrens-DB-Aktionscodes True liefert. | grün | nie geprüft | +| `IstVerfahrensDbAktionTests.test_liefert_false_fuer_andere_aktionen` | Prüft, dass ist_verfahrens_db_aktion für Nicht-Verfahrens-DB-Aktionen und ohne Aktion False liefert. | grün | nie geprüft | +| `ErlaubtePersistierungTests.test_liefert_true_fuer_erzeugen_ueberschreiben_anhaengen` | Prüft, dass erlaubte_persistierung für Erzeugen/Überschreiben/Anhängen True liefert. | grün | nie geprüft | +| `ErlaubtePersistierungTests.test_liefert_false_fuer_ueberspringen_und_reines_existieren` | Prüft, dass erlaubte_persistierung bei Überspringen und reinem 'datei_existiert' False liefert. | grün | nie geprüft | + ### `Plugin_SN_Basis/tests/test_pruefmanager.py` Worum es in der Datei geht: — (Docstring fehlt) Testgruppen: -- `TestPruefmanager` (14 Testfälle): — (Docstring fehlt) +- `TestPruefmanager` (24 Testfälle): — (Docstring fehlt) | Testfall | prüft | Status | geprüft | | --- | --- | --- | --- | @@ -327,6 +446,54 @@ Testgruppen: | `TestPruefmanager.test_datei_existiert_append` | Prüft, dass die Nutzerwahl 'anhängen' bei bestehender Datei zur Aktion 'datei_existiert_anhaengen' führt. | grün | geprüft am 2026-09-17 | | `TestPruefmanager.test_datei_existiert_cancel` | Prüft, dass die Nutzerwahl 'abbrechen' bei bestehender Datei zur Aktion 'datei_existiert_ueberspringen' führt. | grün | geprüft am 2026-09-17 | | `TestPruefmanager.test_datei_existiert_in_non_qgis_mode_returns_input` | Prüft, dass außerhalb des QGIS-Modus bei bestehender Datei keine Rückfrage erfolgt, sondern die ursprüngliche Aktion unentschieden zurückgegeben wird. | grün | geprüft am 2026-09-17 | +| `TestPruefmanager.test_verfahrensgebiet_layer_existiert_ergaenzen` | Prüft, dass die Nutzerwahl 'ergänzen' bei bestehendem Verfahrensgebiet zur Aktion 'verfahrensgebiet_ergaenzen' führt. | grün | nie geprüft | +| `TestPruefmanager.test_verfahrensgebiet_layer_existiert_abbrechen` | Prüft, dass die Nutzerwahl 'abbrechen' bei bestehendem Verfahrensgebiet ok=False mit Aktion 'verfahrensgebiet_abbrechen' liefert. | grün | nie geprüft | +| `TestPruefmanager.test_verfahrensgebiet_layer_existiert_in_non_qgis_mode_returns_input` | Prüft, dass außerhalb des QGIS-Modus bei bestehendem Verfahrensgebiet keine Rückfrage erfolgt. | grün | nie geprüft | +| `TestPruefmanager.test_report_error_kritische_aktion_ruft_error_auf` | Prüft, dass eine kritische Aktion (z. B. 'netzwerkfehler') über error() gemeldet wird, nicht über warning(). | grün | nie geprüft | +| `TestPruefmanager.test_report_error_warn_aktion_ruft_warning_auf` | Prüft, dass eine Warn-Aktion (z. B. 'datei_nicht_gefunden') über warning() gemeldet wird, nicht über error(). | grün | nie geprüft | +| `TestPruefmanager.test_report_error_unbekannte_aktion_faellt_auf_warning_zurueck` | Prüft, dass eine nicht eingestufte Aktion als Fallback über warning() gemeldet wird. | grün | nie geprüft | +| `TestPruefmanager.test_frage_ja_nein_im_qgis_modus_fragt_nutzer` | Prüft, dass frage_ja_nein im QGIS-Modus den Nutzer fragt und dessen Antwort liefert. | grün | nie geprüft | +| `TestPruefmanager.test_frage_ja_nein_ausserhalb_qgis_liefert_default_ohne_rueckfrage` | Prüft, dass frage_ja_nein außerhalb des QGIS-Modus den Default-Wert liefert, ohne den Nutzer zu fragen. | grün | nie geprüft | +| `TestPruefmanager.test_frage_text_im_qgis_modus_fragt_nutzer` | Prüft, dass frage_text im QGIS-Modus den Nutzer fragt und Text plus OK-Status liefert. | grün | nie geprüft | +| `TestPruefmanager.test_frage_text_ausserhalb_qgis_liefert_default_ohne_rueckfrage` | Prüft, dass frage_text außerhalb des QGIS-Modus den Standardtext mit OK=True liefert, ohne den Nutzer zu fragen. | grün | nie geprüft | + +### `Plugin_SN_Basis/tests/test_qgiscore_wrapper_helpers.py` + +Worum es in der Datei geht: Tests für sn_basis/functions/qgiscore_wrapper.py::polygon_zu_linie/layer_exists_in_gpkg (Issue #65). + +Testgruppen: + +- `PolygonZuLinieTests` (7 Testfälle): — (Docstring fehlt) +- `LayerExistsInGpkgTests` (4 Testfälle): — (Docstring fehlt) + +| Testfall | prüft | Status | geprüft | +| --- | --- | --- | --- | +| `PolygonZuLinieTests.test_none_liefert_none` | Prüft, dass polygon_zu_linie für None-Eingabe None liefert. | grün | nie geprüft | +| `PolygonZuLinieTests.test_leere_geometrie_liefert_none` | Prüft, dass eine leere Geometrie None liefert. | grün | nie geprüft | +| `PolygonZuLinieTests.test_stufe1_nutzt_boundary_wenn_vorhanden` | Prüft, dass eine Geometrie mit boundary() (QGIS 3.x-Pfad) deren Ergebnis direkt liefert. | grün | nie geprüft | +| `PolygonZuLinieTests.test_stufe2_extrahiert_ringe_bei_einfachem_polygon` | Prüft, dass ohne boundary() die Ringe eines einfachen Polygons manuell extrahiert werden. | grün | nie geprüft | +| `PolygonZuLinieTests.test_stufe2_extrahiert_alle_ringe_bei_multipolygon` | Prüft, dass bei einem MultiPolygon die Ringe aller Teilpolygone extrahiert werden. | grün | nie geprüft | +| `PolygonZuLinieTests.test_stufe3_fallback_wenn_keine_ringe_extrahierbar` | Prüft, dass bei fehlgeschlagener Ringextraktion auf convertToType zurückgefallen wird. | grün | nie geprüft | +| `PolygonZuLinieTests.test_alle_stufen_scheitern_liefert_none` | Prüft, dass polygon_zu_linie None liefert, wenn Ringextraktion und convertToType beide scheitern. | grün | nie geprüft | +| `LayerExistsInGpkgTests.test_fehlende_datei_liefert_false` | Prüft, dass eine nicht vorhandene GPKG-Datei False liefert. | grün | nie geprüft | +| `LayerExistsInGpkgTests.test_leerer_pfad_oder_layername_liefert_false` | Prüft, dass ein leerer Pfad oder Layername False liefert. | grün | nie geprüft | +| `LayerExistsInGpkgTests.test_vorhandener_layer_liefert_true` | Prüft, dass ein in gpkg_contents eingetragener Layername als vorhanden erkannt wird. | grün | nie geprüft | +| `LayerExistsInGpkgTests.test_fehlender_layer_liefert_false` | Prüft, dass ein nicht in gpkg_contents eingetragener Layername als nicht vorhanden gilt. | grün | nie geprüft | + +### `Plugin_SN_Basis/tests/test_qgisui_wrapper_helpers.py` + +Worum es in der Datei geht: Tests für sn_basis/functions/qgisui_wrapper.py::add_layer_to_project (Issue #65). + +Testgruppen: + +- `AddLayerToProjectTests` (4 Testfälle): — (Docstring fehlt) + +| Testfall | prüft | Status | geprüft | +| --- | --- | --- | --- | +| `AddLayerToProjectTests.test_none_layer_liefert_false` | Prüft, dass add_layer_to_project für einen fehlenden Layer (None) False liefert. | grün | nie geprüft | +| `AddLayerToProjectTests.test_mock_modus_liefert_true_ohne_projektzugriff` | Prüft, dass im Mock-Modus (ohne QGIS) ein gültiger Layer True liefert, ohne das Projekt anzufassen. | grün | nie geprüft | +| `AddLayerToProjectTests.test_mit_qgis_fuegt_layer_dem_projekt_hinzu` | Prüft, dass bei verfügbarem QGIS der Layer über QgsProject.instance().addMapLayer hinzugefügt wird. | grün | nie geprüft | +| `AddLayerToProjectTests.test_mit_qgis_fehler_liefert_false` | Prüft, dass ein Fehler beim Hinzufügen zum Projekt abgefangen wird und False liefert. | grün | nie geprüft | ### `Plugin_SN_Basis/tests/test_settings_logic.py` @@ -343,6 +510,24 @@ Testgruppen: | `TestSettingsLogic.test_load_handles_partial_values_with_empty_fallback` | Prüft, dass load() für jede Variable den (auch leeren) Wert von get_variable() unverändert übernimmt, selbst wenn nicht alle Variablen im Mock konfiguriert sind. | grün | geprüft am 2026-09-17 | | `TestSettingsLogic.test_save_empty_string_value_is_persisted` | Prüft, dass save() einen leeren String als gültigen Wert speichert, statt ihn wie einen fehlenden Key zu behandeln. | grün | geprüft am 2026-09-17 | +### `Plugin_SN_Basis/tests/test_settings_tab.py` + +Worum es in der Datei geht: Tests für sn_basis/ui/tabs/settings_tab.py::save_data/load_data (Issue #65). + +Testgruppen: + +- `SaveDataTests` (2 Testfälle): — (Docstring fehlt) +- `LoadDataTests` (4 Testfälle): — (Docstring fehlt) + +| Testfall | prüft | Status | geprüft | +| --- | --- | --- | --- | +| `SaveDataTests.test_sammelt_text_und_combobox_werte_inklusive_landkreiskennzahl` | Prüft, dass save_data Text- und Dropdown-Werte sammelt und die Landkreiskennzahl separat ergänzt. | grün | nie geprüft | +| `SaveDataTests.test_ohne_landkreis_dropdown_wird_keine_kennzahl_ergaenzt` | Prüft, dass ohne Landkreis-Dropdown im Formular keine 'landkreis_kennzahl' ergänzt wird. | grün | nie geprüft | +| `LoadDataTests.test_befuellt_textfelder_aus_gespeicherten_daten` | Prüft, dass load_data ein Textfeld mit dem gespeicherten Wert befüllt. | grün | nie geprüft | +| `LoadDataTests.test_ohne_gespeicherten_wert_bleibt_textfeld_leer` | Prüft, dass load_data ohne gespeicherten Wert das Textfeld auf einen leeren Text setzt. | grün | nie geprüft | +| `LoadDataTests.test_waehlt_combobox_eintrag_bei_bekanntem_namen` | Prüft, dass load_data im Landkreis-Dropdown den gespeicherten Landkreisnamen auswählt. | grün | nie geprüft | +| `LoadDataTests.test_unbekannter_gespeicherter_name_waehlt_ersten_eintrag` | Prüft, dass load_data bei einem nicht mehr vorhandenen Landkreisnamen auf den ersten Eintrag zurückfällt. | grün | nie geprüft | + ### `Plugin_SN_Basis/tests/test_stilpruefer.py` Worum es in der Datei geht: — (Docstring fehlt) @@ -365,10 +550,18 @@ Worum es in der Datei geht: Unit-Tests für sn_basis.functions.sys_wrapper.get_p Testgruppen: - `TestGetPluginRoot` (1 Testfälle): — (Docstring fehlt) +- `JoinPathTests` (1 Testfälle): — (Docstring fehlt) +- `EnsureDirTests` (2 Testfälle): — (Docstring fehlt) +- `GetattrSafeTests` (2 Testfälle): — (Docstring fehlt) | Testfall | prüft | Status | geprüft | | --- | --- | --- | --- | | `TestGetPluginRoot.test_get_plugin_root_folgt_keiner_verzeichnisverknuepfung` | Prüft, dass get_plugin_root() bei einem über eine Verzeichnisverknüpfung (wie von link_qgis_profile.py angelegt) erreichten Modul den verlinkten Pfad liefert, statt zum echten Zielverzeichnis aufzulösen (Verfahrensgebiet #50). | grün | geprüft am 2026-09-17 | +| `JoinPathTests.test_verbindet_mehrere_pfadbestandteile` | Prüft, dass join_path mehrere Bestandteile OS-sicher zu einem Path zusammenfügt. | grün | nie geprüft | +| `EnsureDirTests.test_legt_fehlendes_verzeichnis_inklusive_eltern_an` | Prüft, dass ensure_dir ein fehlendes Verzeichnis samt Elternverzeichnissen anlegt. | grün | nie geprüft | +| `EnsureDirTests.test_vorhandenes_verzeichnis_wirft_keinen_fehler` | Prüft, dass ensure_dir bei einem bereits vorhandenen Verzeichnis keinen Fehler wirft. | grün | nie geprüft | +| `GetattrSafeTests.test_liefert_vorhandenes_attribut` | Prüft, dass getattr_safe ein vorhandenes Attribut liefert. | grün | nie geprüft | +| `GetattrSafeTests.test_liefert_default_bei_fehlendem_attribut` | Prüft, dass getattr_safe bei fehlendem Attribut den Default-Wert liefert. | grün | nie geprüft | ### `Plugin_SN_Basis/tests/test_text_wrapper.py` @@ -407,11 +600,13 @@ Testgruppen: ### `Plugin_SN_Basis/tests/test_verfahrensgebiet_manager.py` -Worum es in der Datei geht: — (Docstring fehlt) +Worum es in der Datei geht: Tests für sn_basis/functions/verfahrensgebiet_manager.py (zentrale Layer-Verfolgung, Issue #65). Testgruppen: - `TestVerfahrensgebietManager` (5 Testfälle): — (Docstring fehlt) +- `OnHandlerTests` (5 Testfälle): — (Docstring fehlt) +- `ListenerSetupTests` (3 Testfälle): — (Docstring fehlt) | Testfall | prüft | Status | geprüft | | --- | --- | --- | --- | @@ -420,6 +615,14 @@ Testgruppen: | `TestVerfahrensgebietManager.test_set_verfahrensgebiet_layer_id_writes_project_variable` | Prüft, dass set_verfahrensgebiet_layer_id() die Layer-ID als Projektvariable 'verfahrensgebiet_layer' speichert. | grün | nie geprüft | | `TestVerfahrensgebietManager.test_update_without_layer_does_not_write_when_already_empty` | Prüft, dass ohne gefundenen Verfahrensgebiet-Layer keine Schreibaktion erfolgt, wenn die Variable bereits leer ist. | grün | nie geprüft | | `TestVerfahrensgebietManager.test_update_with_layer_writes_variable` | Prüft, dass ein gefundener Verfahrensgebiet-Layer seine ID als Projektvariable speichert. | grün | nie geprüft | +| `OnHandlerTests.test_on_project_changed_ohne_layer_setzt_variable_leer` | Prüft, dass _on_project_changed die Variable leert, wenn kein Verfahrensgebiet-Layer existiert. | grün | nie geprüft | +| `OnHandlerTests.test_on_project_changed_mit_layer_setzt_variable` | Prüft, dass _on_project_changed die Layer-ID eines gefundenen Verfahrensgebiet-Layers übernimmt. | grün | nie geprüft | +| `OnHandlerTests.test_on_layers_added_findet_neuen_layer` | Prüft, dass _on_layers_added nach neu hinzugefügten Layern sucht und die Variable aktualisiert. | grün | nie geprüft | +| `OnHandlerTests.test_on_layer_removed_bei_aktuellem_layer_sucht_neu` | Prüft, dass das Entfernen des aktuell aktiven Verfahrensgebiet-Layers eine Neusuche auslöst. | grün | nie geprüft | +| `OnHandlerTests.test_on_layer_removed_bei_anderem_layer_aendert_nichts` | Prüft, dass das Entfernen eines anderen Layers keine Neusuche auslöst. | grün | nie geprüft | +| `ListenerSetupTests.test_setup_ohne_qgis_tut_nichts` | Prüft, dass setup_verfahrensgebiet_listener ohne QGIS keine Signale registriert. | grün | nie geprüft | +| `ListenerSetupTests.test_setup_verbindet_signale_und_ist_idempotent` | Prüft, dass setup_verfahrensgebiet_listener die Projektsignale verbindet und ein zweiter Aufruf nichts doppelt registriert. | grün | nie geprüft | +| `ListenerSetupTests.test_teardown_trennt_alle_signale_und_ist_idempotent` | Prüft, dass teardown_verfahrensgebiet_listener alle Signale trennt und mehrfacher Aufruf nicht fehlschlägt. | grün | nie geprüft | ## Paket `sn_verfahrensgebiet` @@ -908,7 +1111,7 @@ Arbeitsliste: Diese Testfälle haben keinen Docstring; was sie fachlich prüfen, aus dem Quelltext erschließen. Jeder Eintrag braucht eine einzeilige Beschreibung im Testfall, dann verschwindet er hier von selbst. -### `sn_basis` – 0 von 166 Testfällen ohne Beschreibung +### `sn_basis` – 0 von 249 Testfällen ohne Beschreibung Keine Lücken. @@ -1113,43 +1316,23 @@ Keine Lücken. Heuristik, kein Beweis: Diese Funktionen und Methoden kommen unter ihrem Namen in keiner Testdatei des Pakets vor. Das schließt nicht aus, dass sie indirekt über eine andere, getestete Funktion mitlaufen – umgekehrt gilt: Taucht der Name irgendwo in einer Testdatei auf, gilt die Funktion schon als referenziert, auch bei zufälliger Namensgleichheit mit etwas anderem. `main.py`/`__init__.py` (QGIS-Einstiegspunkte wie `classFactory`, `initGui`, `unload`) und Dunder-Methoden sind ausgenommen. Diese Liste ersetzt keine fachliche Prüfung, ob ein Test sinnvoll wäre – dafür braucht es einen Menschen, der die Funktion kennt. -### `sn_basis` – 156 von 229 (68 %) ohne Testbezug +### `sn_basis` – 115 von 229 (50 %) ohne Testbezug -#### `functions/dialog_wrapper.py` (12) +#### `functions/dialog_wrapper.py` (9) - `show_info_dialog` (Zeile 42) -- `ask_text` (Zeile 56) -- `ask_ergaenzen_entfernen_ersetzen_abbrechen` (Zeile 131) - `ask_detailpruefung_oder_vg_laden` (Zeile 185) - `ask_detailpruefung_oder_abbrechen` (Zeile 235) - `ProgressDialog.set_total` (Zeile 328) - `ProgressDialog.set_value` (Zeile 336) - `ProgressDialog.set_label` (Zeile 348) - `ProgressDialog.is_canceled` (Zeile 357) -- `ProgressDialog.close` (Zeile 366) - `ProgressDialog.raise_to_front` (Zeile 373) - `create_progress_dialog` (Zeile 390) -#### `functions/landkreise.py` (1) +#### `functions/message_wrapper.py` (2) -- `_lade_landkreise` (Zeile 20) - -#### `functions/ly_existence_wrapper.py` (2) - -- `layer_is_valid` (Zeile 10) -- `layer_is_usable` (Zeile 27) - -#### `functions/ly_style_wrapper.py` (2) - -- `apply_style_from_path` (Zeile 8) -- `apply_style` (Zeile 27) - -#### `functions/message_wrapper.py` (5) - -- `_get_message_bar` (Zeile 15) -- `push_message` (Zeile 42) - `info` (Zeile 67) -- `error` (Zeile 77) - `success` (Zeile 82) #### `functions/os_wrapper.py` (6) @@ -1161,42 +1344,19 @@ Heuristik, kein Beweis: Diese Funktionen und Methoden kommen unter ihrem Namen i - `is_case_sensitive_fs` (Zeile 80) - `path_suffix` (Zeile 96) -#### `functions/qgiscore_wrapper.py` (2) - -- `layer_exists_in_gpkg` (Zeile 1019) -- `polygon_zu_linie` (Zeile 1058) - -#### `functions/qgisui_wrapper.py` (9) +#### `functions/qgisui_wrapper.py` (5) - `get_main_window` (Zeile 131) -- `add_dock_widget` (Zeile 149) -- `remove_dock_widget` (Zeile 156) -- `find_dock_widgets` (Zeile 163) - `add_menu` (Zeile 178) - `remove_menu` (Zeile 188) - `add_toolbar` (Zeile 201) - `remove_toolbar` (Zeile 208) -- `add_layer_to_project` (Zeile 217) #### `functions/qt_wrapper.py` (2) - `exec_dialog` (Zeile 60) - `debug_qt_status` (Zeile 64) -#### `functions/sys_wrapper.py` (3) - -- `join_path` (Zeile 36) -- `ensure_dir` (Zeile 56) -- `getattr_safe` (Zeile 102) - -#### `functions/verfahrensgebiet_manager.py` (5) - -- `_on_layers_added` (Zeile 109) -- `_on_layer_removed` (Zeile 114) -- `_on_project_changed` (Zeile 123) -- `setup_verfahrensgebiet_listener` (Zeile 132) -- `teardown_verfahrensgebiet_listener` (Zeile 176) - #### `modules/DataGrabber.py` (4) - `DataGrabber.set_source` (Zeile 68) @@ -1204,27 +1364,22 @@ Heuristik, kein Beweis: Diese Funktionen und Methoden kommen unter ihrem Namen i - `DataGrabber._process_service_source` (Zeile 320) - `DataGrabber._aggregate_results` (Zeile 330) -#### `modules/Dateipruefer.py` (5) +#### `modules/Dateipruefer.py` (2) -- `Dateipruefer.erkenne_dateityp` (Zeile 77) -- `Dateipruefer._pfad` (Zeile 91) - `Dateipruefer._ist_leer` (Zeile 98) -- `Dateipruefer._ist_gueltiger_gpkg_pfad` (Zeile 113) - `Dateipruefer._handle_leere_eingabe` (Zeile 227) #### `modules/Datenschreiber.py` (1) - `Datenschreiber._store_style_in_gpkg` (Zeile 77) -#### `modules/LayerLoader.py` (3) +#### `modules/LayerLoader.py` (2) - `LayerLoader._was_canceled` (Zeile 42) - `LayerLoader._process_events` (Zeile 50) -- `LayerLoader.apply_style` (Zeile 190) -#### `modules/linkpruefer.py` (4) +#### `modules/linkpruefer.py` (3) -- `Linkpruefer._pfad` (Zeile 33) - `Linkpruefer._ist_url` (Zeile 41) - `Linkpruefer._pruefe_url` (Zeile 81) - `Linkpruefer._pruefe_dateipfad` (Zeile 115) @@ -1279,31 +1434,18 @@ Heuristik, kein Beweis: Diese Funktionen und Methoden kommen unter ihrem Namen i - `PrintLogic._get_required_map_dimensions_mm` (Zeile 1061) - `PrintLogic.druckvorlage_anlegen` (Zeile 1161) -#### `modules/pruef_ergebnis.py` (3) +#### `modules/pruef_ergebnis.py` (1) -- `pruef_ergebnis.ist_verfahrens_db_aktion` (Zeile 149) - `pruef_ergebnis.dateipfad` (Zeile 167) -- `pruef_ergebnis.erlaubte_persistierung` (Zeile 181) -#### `modules/Pruefmanager.py` (8) +#### `modules/Pruefmanager.py` (5) -- `Pruefmanager.report_error` (Zeile 20) - `Pruefmanager.report_summary` (Zeile 45) - `Pruefmanager.zeige_hinweis` (Zeile 62) -- `Pruefmanager.frage_ja_nein` (Zeile 67) -- `Pruefmanager.frage_text` (Zeile 73) - `Pruefmanager._handle_datei_existiert` (Zeile 83) - `Pruefmanager._handle_verfahrensgebiet_layer_existiert` (Zeile 230) - `Pruefmanager._ask_use_or_replace_pufferlayer` (Zeile 273) -#### `ui/base_dockwidget.py` (1) - -- `BaseDockWidget.closeEvent` (Zeile 97) - -#### `ui/dockmanager.py` (1) - -- `DockManager.show` (Zeile 30) - #### `ui/navigation.py` (6) - `Navigation.init_ui` (Zeile 33) @@ -1313,7 +1455,7 @@ Heuristik, kein Beweis: Diese Funktionen und Methoden kommen unter ihrem Namen i - `Navigation.remove_action` (Zeile 104) - `Navigation.remove_all` (Zeile 115) -#### `ui/tabs/print_tab.py` (27) +#### `ui/tabs/print_tab.py` (25) - `PrintTab.set_services` (Zeile 94) - `PrintTab._build_ui` (Zeile 115) @@ -1329,9 +1471,7 @@ Heuristik, kein Beweis: Diese Funktionen und Methoden kommen unter ihrem Namen i - `PrintTab._format_druckpuffer_label` (Zeile 425) - `PrintTab._on_vorlage_erstellen` (Zeile 428) - `PrintTab._disconnect_project_signals` (Zeile 441) -- `PrintTab.cleanup` (Zeile 459) - `PrintTab._connect_project_signals` (Zeile 464) -- `PrintTab._on_project_changed` (Zeile 482) - `PrintTab._toggle_atlas` (Zeile 489) - `PrintTab._restore_atlas_layer_selection` (Zeile 495) - `PrintTab._disconnect_theme_collection_signals` (Zeile 519) @@ -1343,11 +1483,9 @@ Heuristik, kein Beweis: Diese Funktionen und Methoden kommen unter ihrem Namen i - `PrintTab._on_auswahl_as_atlas_clicked` (Zeile 641) - `PrintTab._populate_atlas_layer_combo` (Zeile 679) -#### `ui/tabs/settings_tab.py` (3) +#### `ui/tabs/settings_tab.py` (1) - `SettingsTab._build_input` (Zeile 118) -- `SettingsTab.save_data` (Zeile 130) -- `SettingsTab.load_data` (Zeile 149) ### `sn_verfahrensgebiet` – 34 von 104 (33 %) ohne Testbezug diff --git a/docs/wissen/fallstricke.md b/docs/wissen/fallstricke.md index a2dde29..6f69896 100644 --- a/docs/wissen/fallstricke.md +++ b/docs/wissen/fallstricke.md @@ -14,6 +14,19 @@ Kurz, konkret, mit Datum und Quelle. Neue Einträge oben in der passenden Rubrik Funktionen, sondern durch den unvollständigen Mock. Beim Schreiben neuer Tests für einen dieser Pfade prüfen, ob `functions/qgiscore_wrapper.py::_MockQgsProject` die benötigte Methode schon hat, statt lange nach dem „Bug" in der eigentlichen Funktion zu suchen. Ergänzt in Issue Basis #63 (18.09.2026). +- **`_MockQDockWidget` hatte kein `closeEvent()`:** `BaseDockWidget.closeEvent()` ruft am Ende + `super().closeEvent(event)` auf – im Mock-Modus stürzte das für **jede** reale `BaseDockWidget`-Instanz mit + `AttributeError` ab. Ergänzt in Issue Basis #65 (18.09.2026); gleiche Kategorie Fund wie oben – erst den + Mock in `qt_wrapper.py`/`qgiscore_wrapper.py` auf Vollständigkeit prüfen, bevor die eigentliche Funktion in + Verdacht gerät. Bei UI-Klassen mit `__init__`, die selbst nicht QGIS-frei konstruierbar sind (fehlende + `setLayout()`/`QGroupBox` im Mock, z. B. `SettingsTab`), Instanz stattdessen über `Klasse.__new__(Klasse)` + ohne `__init__` erzeugen und nur die für den Test nötigen Attribute von Hand setzen (siehe + `tests/test_base_dockwidget.py`, `tests/test_settings_tab.py`). +- **Zwei Testkatalog-Fehlalarme durch die „Ungetestete Funktionen"-Heuristik entdeckt und real bestätigt (Issue + Basis #60):** `Pruefmanager._ask_use_or_replace_pufferlayer()` referenziert `self.pruefmanager`, das auf + `Pruefmanager`-Instanzen nie existiert (`AttributeError` bei jedem Aufruf) – toter Code, im ganzen Workspace + ohne Aufrufer. Vor einem Test für eine als „testen" markierte Funktion kurz prüfen, ob sie überhaupt + syntaktisch fehlerfrei aufrufbar ist. - **`openpyxl` ist eine harte Abhängigkeit** von `sn_basis` (Excel-Import) und unter Linux-QGIS oft nicht installiert (Issue Verfahrensgebiet #21). `requests` ist nur optionaler Fallback. Es gibt keine `requirements.txt`. (09/2026) - **QGIS lädt Plugins in nicht garantierter Reihenfolge.** Fachplugins dürfen in `initGui()` nicht davon ausgehen, dass `sn_basis` fertig ist; `sn_basis` ruft `initGui()` aller `sn_*` nach. (Code `main.py`) - **Exit-Crash unter QGIS 3.40** entstand durch nicht getrennte Projektsignale beim Unload. Regel: jeder Tab/Manager, der Signale verbindet, bietet `cleanup()`/`teardown_...()` und wird beim Schließen aufgerufen. (Basis, `assets/plan-qgis340ExitCrashFix.prompt.md`)