diff --git a/docs/architektur/modulkarte.md b/docs/architektur/modulkarte.md index 82b7f46..ec64b16 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/` | 13 Testdateien, `unittest`, Mock-Modus; `run_tests.py` (farbiger Runner), `test_qgis.bat` (Coverage in OSGeo4W) | +| `tests/` | 19 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/status/STATUS.md b/docs/status/STATUS.md index 4079e17..4e218d2 100644 --- a/docs/status/STATUS.md +++ b/docs/status/STATUS.md @@ -1,7 +1,7 @@ # Status des Projekts Kurz und aktuell. Wird bei jedem Merge und jeder Übergabe gepflegt (Skill `sn-uebergabe`). Älteres wandert nach unten -in „Erledigt" oder wird gelöscht. **Stand: 04.09.2026.** +in „Erledigt" oder wird gelöscht. **Stand: 18.09.2026.** ## Aktuelle Phase @@ -13,7 +13,7 @@ spätere Phase und beginnt erst, wenn die Test-Baseline grün ist und das Projek | Person / Behörde | Schwerpunkt | Stand | |---|---|---| -| Daniel Helbig (LK Meißen) | Fachfunktionen Verfahrensgebiet, Plan41, VLN-API | aktiv | +| Daniel Helbig (LK Meißen) | Fachfunktionen Verfahrensgebiet, Plan41, VLN-API; aktuell Test-Audit und Testabdeckung sn_basis-Kernpipeline (Basis #63) | aktiv | | Michael Otto (LK Mittelsachsen) | Release-Infrastruktur, Linkliste, zuletzt Verfahrensgebiet (Shape-Laden, Beteiligung) | aktiv | | 22munzke | Druck/Layout-Anforderungen (Issues Basis #37–#44) | Issues | | weitere Behörden | Einstieg über dieses Repository | ab 09/2026 | @@ -30,16 +30,18 @@ spätere Phase und beginnt erst, wenn die Test-Baseline grün ist und das Projek Stable 4.2 wird am 25.09.2026 LTR. Produktentscheidung, blockiert die CI-Matrix (`docs/konzept/07_qgis_tests_plan.md` Abschnitt 2). 4. **Test-Baseline grün machen.** Ist-Stand Mock-Modus laut `docs/status/testbaseline.json`: - sn_basis 87/87 grün, sn_plan41 43/44 (1 Fehler in `test_tab_a_ui`), sn_verfahrensgebiet 157/201 + sn_basis 166/166 grün, sn_plan41 43/44 (1 Fehler in `test_tab_a_ui`), sn_verfahrensgebiet 157/201 (36 rot, 8 übersprungen; meist veraltete Tests nach dem Mehrfachauswahl-Umbau). Probelauf am 03.09.2026 mit frischen Klonen: `sn_verfahrensgebiet` 154/201, **drei neue rote Tests** in `test_verfahrensgebiet_alkis_komplett` durch PR #43 („Nur-laden-Option durch Stop-Abfrage ersetzt"). Entscheidung des Maintainers: Tests anpassen oder Baseline mit `--update-baseline` nachziehen. -5. **Testbeschreibungen nachziehen.** Von 332 Testfällen haben nur 100 (30 %) einen Docstring — `sn_basis` - keinen einzigen von 87, `sn_plan41` einen von 44. Ohne Beschreibung ist von außen nicht erkennbar, was ein - Test prüft. Arbeitsliste: Abschnitt „Lücken" in `docs/tests/testkatalog.md`. Pflicht für neue und geänderte - Tests gilt ab sofort (ADR 0009). Seit 15.09.2026 zusätzlich als Dashboard `docs/tests/testkatalog.html` - (lokal im Browser öffnen) – zeigt Testabdeckung und -status auf einen Blick, ohne in den Code zu schauen. +5. **Testbeschreibungen nachziehen.** `sn_basis` und `sn_verfahrensgebiet` (Docstring-Pflicht) sind in Arbeit, + `sn_plan41` weiterhin fast vollständig ohne Docstring (1 von 44). Ohne Beschreibung ist von außen nicht + erkennbar, was ein Test prüft. Arbeitsliste: Abschnitt „Lücken" in `docs/tests/testkatalog.md`. Pflicht für + neue und geänderte Tests gilt ab sofort (ADR 0009). Seit 15.09.2026 zusätzlich als Dashboard + `docs/tests/testkatalog.html` (lokal im Browser öffnen) – zeigt Testabdeckung und -status auf einen Blick, + seit 18.09.2026 auch strukturelle Lücken (Quellcode-Funktionen ohne Testbezug, Abschnitt „Ungetestete + Funktionen"), ohne in den Code zu schauen. 6. **Testlücken beim Shape-Import schließen.** Beim Erstellen von `docs/tests/verfahrensgebiet-shape-import.md` gefunden und gegen `origin/unstable` geprüft: `_ermittle_gebietstyp_aus_fbschl` hat **keinen** Test — obwohl PR #44/#45 genau diese Funktion tolerant gemacht hat. Ebenso ungetestet: mehrere Shapefile-Sätze in einer diff --git a/docs/tests/testkatalog.html b/docs/tests/testkatalog.html index aebb3bf..f802bdf 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)
-
348Testfälle
-
305grün
+
418Testfälle
+
375grün
35rot (Baseline)
-
58%mit Docstring
-
16%aktuell geprüft
-
32Testdateien
-
60%ohne Testbezug
+
65%mit Docstring
+
13%aktuell geprüft
+
36Testdateien
+
55%ohne Testbezug
Verteilung je Paket
-
sn_basis15 Dateien · 96 Testfälle
+
sn_basis19 Dateien · 166 Testfälle
sn_verfahrensgebiet12 Dateien · 208 Testfälle
sn_plan415 Dateien · 44 Testfälle
@@ -153,9 +153,9 @@

sn_basis

-

Plattform-Plugin · Ordner Plugin_SN_Basis · 15 Testdateien · 96 Testfälle

+

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

- @@ -201,7 +201,140 @@ 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

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

TestGetLaenderkennung 5
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

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)"]
+  class g1 groupnode
+  g1 --> t1("raumfilter_ohne_liefert_none")
+  g1 --> t2("fehlender_layer_liefert_none")
+  g1 --> t3("unbekannter_raumfilter_liefert_none")
+  g1 --> t4("verfahrensgebiet_liefert_extent_und_crs")
+  g1 --> t5("verfahrensgebiet_ohne_extent_liefert_none")
+  g1 --> t6("pufferlayer_liefert_extent_des_pufferlayers")
+  g1 --> t7("pufferlayer_ohne_puffer_liefert_none")
+  root --> g2["BuildProviderUrlTests (9)"]
+  class g2 groupnode
+  g2 --> t8("wms_liefert_link_unveraendert")
+  g2 --> t9("url_praefix_wird_entfernt")
+  g2 --> t10("wfs_baut_standardparameter_und_bbox_mit_crs")
+  g2 --> t11("wfs_repariert_doppeltes_fragezeichen")
+  g2 --> t12("wfs_ohne_raumfilter_setzt_keine_bbox")
+  g2 --> t13("rest_provider_haengt_query_endpunkt_an")
+  g2 --> t14("rest_provider_mit_bbox_baut_geometry_envelope_und_srid")
+  g2 --> t15("default_provider_haengt_generischen_bbox_parameter_an")
+  g2 --> t16("default_provider_ohne_raumfilter_laesst_query_unveraendert")
+  root --> g3["FetchFeaturesTests (5)"]
+  class g3 groupnode
+  g3 --> t17("wms_liefert_keine_features_ohne_fehler")
+  g3 --> t18("abbruch_vor_abruf_liefert_fehlermeldung")
+  g3 --> t19("json_featurecollection_wird_geparst")
+  g3 --> t20("netzwerkfehler_wird_als_fehlermeldung_gemeldet")
+  g3 --> t21("wfs_xml_liefert_anzahl_aus_numberofmatched")
+  root --> g4["DatenabrufOrchestrierungTests (3)"]
+  class g4 groupnode
+  g4 --> t22("fehlende_pflichtfelder_werden_als_ungueltig_gemeldet")
+  g4 --> t23("wms_zeile_ohne_features_landet_in_ausserhalb")
+  g4 --> t24("abbruch_ueber_progress_stoppt_weitere_zeilen")
+  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
+  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
DetermineSpatialFilterTests
test_raumfilter_ohne_liefert_none
Prüft, dass Raumfilter 'ohne' unabhängig vom Layer immer None liefert.grünnie geprüft
DetermineSpatialFilterTests
test_fehlender_layer_liefert_none
Prüft, dass ohne Verfahrensgebiet-Layer kein Raumfilter gebaut wird.grünnie geprüft
DetermineSpatialFilterTests
test_unbekannter_raumfilter_liefert_none
Prüft, dass ein unbekannter Raumfilter-Wert None liefert, statt einen Fehler zu werfen.grünnie geprüft
DetermineSpatialFilterTests
test_verfahrensgebiet_liefert_extent_und_crs
Prüft, dass Raumfilter 'Verfahrensgebiet' Extent und CRS des Verfahrensgebiet-Layers liefert.grünnie geprüft
DetermineSpatialFilterTests
test_verfahrensgebiet_ohne_extent_liefert_none
Prüft, dass ein Verfahrensgebiet-Layer ohne ermittelbaren Extent None liefert.grünnie geprüft
DetermineSpatialFilterTests
test_pufferlayer_liefert_extent_des_pufferlayers
Prüft, dass Raumfilter 'Pufferlayer' Extent und CRS des erzeugten Pufferlayers liefert.grünnie geprüft
DetermineSpatialFilterTests
test_pufferlayer_ohne_puffer_liefert_none
Prüft, dass 'Pufferlayer' None liefert, wenn kein Pufferlayer erzeugt werden konnte.grünnie geprüft
BuildProviderUrlTests
test_wms_liefert_link_unveraendert
Prüft, dass bei Provider WMS der Link unverändert durchgereicht wird, auch mit Raumfilter.grünnie geprüft
BuildProviderUrlTests
test_url_praefix_wird_entfernt
Prüft, dass ein vorangestelltes 'url=' aus dem Link entfernt wird.grünnie geprüft
BuildProviderUrlTests
test_wfs_baut_standardparameter_und_bbox_mit_crs
Prüft, dass WFS-Abrufe Standardparameter, umbenanntes TYPENAMES und BBOX mit CRS-URN erhalten.grünnie geprüft
BuildProviderUrlTests
test_wfs_repariert_doppeltes_fragezeichen
Prüft, dass ein zweites '?' im WFS-Link zu '&' korrigiert wird, statt eine ungültige URL zu erzeugen.grünnie geprüft
BuildProviderUrlTests
test_wfs_ohne_raumfilter_setzt_keine_bbox
Prüft, dass WFS ohne Raumfilter (bbox_geom=None) keinen BBOX-Parameter setzt.grünnie geprüft
BuildProviderUrlTests
test_rest_provider_haengt_query_endpunkt_an
Prüft, dass REST/ArcGIS-Links ohne '/query'-Endpunkt automatisch ergänzt werden.grünnie geprüft
BuildProviderUrlTests
test_rest_provider_mit_bbox_baut_geometry_envelope_und_srid
Prüft, dass REST-Abrufe mit Raumfilter eine Geometry-Envelope und inSR/outSR aus dem CRS setzen.grünnie geprüft
BuildProviderUrlTests
test_default_provider_haengt_generischen_bbox_parameter_an
Prüft, dass ein unbekannter Provider mit Raumfilter einen generischen bbox-Parameter erhält.grünnie geprüft
BuildProviderUrlTests
test_default_provider_ohne_raumfilter_laesst_query_unveraendert
Prüft, dass ein unbekannter Provider ohne Raumfilter keinen bbox-Parameter ergänzt.grünnie geprüft
FetchFeaturesTests
test_wms_liefert_keine_features_ohne_fehler
Prüft, dass bei Provider WMS kein Featureabruf stattfindet und kein Fehler gemeldet wird.grünnie geprüft
FetchFeaturesTests
test_abbruch_vor_abruf_liefert_fehlermeldung
Prüft, dass ein bereits gesetzter Abbruch vor dem eigentlichen Abruf erkannt wird.grünnie geprüft
FetchFeaturesTests
test_json_featurecollection_wird_geparst
Prüft, dass eine JSON-FeatureCollection-Antwort in eine Feature-Liste umgewandelt wird.grünnie geprüft
FetchFeaturesTests
test_netzwerkfehler_wird_als_fehlermeldung_gemeldet
Prüft, dass ein fehlgeschlagener HTTP-Abruf eine Fehlermeldung statt einer Ausnahme liefert.grünnie geprüft
FetchFeaturesTests
test_wfs_xml_liefert_anzahl_aus_numberofmatched
Prüft, dass eine WFS-XML-Antwort ohne JSON die Trefferzahl aus numberOfMatched übernimmt.grünnie geprüft
DatenabrufOrchestrierungTests
test_fehlende_pflichtfelder_werden_als_ungueltig_gemeldet
Prüft, dass eine Zeile ohne Link/Provider mit Aktion 'pflichtfelder_fehlen' gemeldet und übersprungen wird.grünnie geprüft
DatenabrufOrchestrierungTests
test_wms_zeile_ohne_features_landet_in_ausserhalb
Prüft, dass eine erfolgreich abgerufene WMS-Zeile mit 0 Features als 'ausserhalb' gezählt wird.grünnie geprüft
DatenabrufOrchestrierungTests
test_abbruch_ueber_progress_stoppt_weitere_zeilen
Prüft, dass ein Abbruch über das Progress-Objekt die Verarbeitung weiterer Zeilen stoppt.grünnie geprüft

Tests für sn_basis/modules/Datenschreiber.py (Schreib-/Ladepipeline, Issue #63).

WriteLayerToGpkgTests 2ResolveStylePathTests 3SchreibeDatenTests 4LadeLayerTests 3SchreibeLogTests 2
flowchart TD
+  root(["test_datenschreiber.py"])
+  class root rootnode
+  root --> g1["WriteLayerToGpkgTests (2)"]
+  class g1 groupnode
+  g1 --> t1("ungueltiger_layer_liefert_fehlermeldung")
+  g1 --> t2("gueltiger_layer_wird_ohne_fehler_geschrieben")
+  root --> g2["ResolveStylePathTests (3)"]
+  class g2 groupnode
+  g2 --> t3("leerer_stilpfad_liefert_none")
+  g2 --> t4("absoluter_vorhandener_stilpfad_wird_aufgeloest")
+  g2 --> t5("nicht_vorhandener_stilpfad_liefert_none")
+  root --> g3["SchreibeDatenTests (4)"]
+  class g3 groupnode
+  g3 --> t6("ohne_speicherort_wirft_valueerror")
+  g3 --> t7("eintrag_ohne_gueltigen_layer_wird_uebersprungen")
+  g3 --> t8("erfolgreicher_eintrag_liefert_layer_path_und_thema")
+  g3 --> t9("ohne_thema_wird_ident_als_layername_verwendet")
+  root --> g4["LadeLayerTests (3)"]
+  class g4 groupnode
+  g4 --> t10("ohne_layer_path_wird_uebersprungen")
+  g4 --> t11("gueltiger_layer_wird_dem_projekt_hinzugefuegt")
+  g4 --> t12("ungueltiger_layer_meldet_layer_nicht_gefunden")
+  root --> g5["SchreibeLogTests (2)"]
+  class g5 groupnode
+  g5 --> t13("ohne_speicherort_wirft_valueerror")
+  g5 --> t14("schreibt_json_datei_mit_ergebnissen_und_gibt_pfad_zurueck")
+  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
+  class t14 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
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
+  root(["test_excel_importer.py"])
+  class root rootnode
+  root --> g1["ImportXlsxTests (5)"]
+  class g1 groupnode
+  g1 --> t1("erfolgreicher_import_liefert_zeilen_als_dicts")
+  g1 --> t2("fehlende_datei_liefert_leere_liste")
+  g1 --> t3("arbeitsblatt_ohne_header_liefert_leere_liste_und_meldet_kein_header")
+  g1 --> t4("header_zeile_nur_leere_werte_liefert_kein_header")
+  g1 --> t5("nicht_lesbare_datei_liefert_leere_liste_und_meldet_read_error")
+  root --> g2["ExcelImporterKonstruktorTests (2)"]
+  class g2 groupnode
+  g2 --> t6("ohne_dateipfad_wirft_valueerror")
+  g2 --> t7("ohne_pruefmanager_wirft_valueerror")
+  class t1 ok
+  class t2 ok
+  class t3 ok
+  class t4 ok
+  class t5 ok
+  class t6 ok
+  class t7 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
ImportXlsxTests
test_erfolgreicher_import_liefert_zeilen_als_dicts
Prüft, dass eine gültige Excel-Datei als Liste von Dicts mit den Header-Spalten geliefert wird.grünnie geprüft
ImportXlsxTests
test_fehlende_datei_liefert_leere_liste
Prüft, dass eine nicht vorhandene Datei eine leere Liste liefert, statt eine Ausnahme zu werfen.grünnie geprüft
ImportXlsxTests
test_arbeitsblatt_ohne_header_liefert_leere_liste_und_meldet_kein_header
Prüft, dass ein leeres Arbeitsblatt ohne Header-Zeile 'kein_header' meldet und eine leere Liste liefert.grünnie geprüft
ImportXlsxTests
test_header_zeile_nur_leere_werte_liefert_kein_header
Prüft, dass eine Header-Zeile aus ausschließlich leeren Zellen ebenfalls als 'kein_header' gilt.grünnie geprüft
ImportXlsxTests
test_nicht_lesbare_datei_liefert_leere_liste_und_meldet_read_error
Prüft, dass eine Datei mit ungültigem Excel-Inhalt 'read_error' meldet und eine leere Liste liefert.grünnie geprüft
ExcelImporterKonstruktorTests
test_ohne_dateipfad_wirft_valueerror
Prüft, dass ExcelImporter ohne Dateipfad einen ValueError wirft.grünnie geprüft
ExcelImporterKonstruktorTests
test_ohne_pruefmanager_wirft_valueerror
Prüft, dass ExcelImporter ohne Pruefmanager einen ValueError wirft.grünnie geprüft

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

TestGetLaenderkennung 5
flowchart TD
   root(["test_laenderkennung.py"])
   class root rootnode
   root --> g1["TestGetLaenderkennung (5)"]
@@ -220,7 +353,76 @@
   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

— (Docstring fehlt)

TestLayerpruefer 10
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/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)"]
+  class g1 groupnode
+  g1 --> t1("wfs_baut_uri_ohne_getfeature_parameter")
+  g1 --> t2("wfs_mit_url_praefix_wird_nicht_doppelt_gesetzt")
+  g1 --> t3("wms_baut_url_praefix_und_nutzt_rasterlayer")
+  g1 --> t4("rest_featureserver_ergaenzt_layer_index")
+  g1 --> t5("ogr_provider_nutzt_link_direkt")
+  g1 --> t6("ungueltiger_layer_meldet_layer_nicht_verfuegbar")
+  g1 --> t7("ausnahme_beim_erstellen_wird_abgefangen")
+  root --> g2["TransformGeometryTests (3)"]
+  class g2 groupnode
+  g2 --> t8("fehlender_layer_liefert_geometrie_unveraendert")
+  g2 --> t9("gleiche_crs_liefert_geometrie_unveraendert")
+  g2 --> t10("unterschiedliche_crs_klont_und_transformiert_geometrie")
+  root --> g3["TransformExtentTests (2)"]
+  class g3 groupnode
+  g3 --> t11("gleiche_crs_liefert_extent_unveraendert")
+  g3 --> t12("unterschiedliche_crs_nutzt_coordinate_transform")
+  root --> g4["FilterByExtentTests (6)"]
+  class g4 groupnode
+  g4 --> t13("ungueltiger_layer_wird_unveraendert_zurueckgegeben")
+  g4 --> t14("ohne_extent_wird_layer_unveraendert_zurueckgegeben")
+  g4 --> t15("falscher_layertyp_wird_unveraendert_zurueckgegeben")
+  g4 --> t16("keine_treffer_liefert_none")
+  g4 --> t17("abbruch_liefert_none_und_meldet_needs_user_action")
+  g4 --> t18("erfolgreicher_filter_liefert_neuen_layer_mit_features")
+  root --> g5["FilterByLayerTests (4)"]
+  class g5 groupnode
+  g5 --> t19("ungueltiger_layer_oder_filterlayer_wird_unveraendert_zurueckgegeben")
+  g5 --> t20("filterlayer_ohne_features_liefert_none")
+  g5 --> t21("erfolgreicher_geometriefilter_liefert_neuen_layer")
+  g5 --> t22("keine_ueberschneidung_liefert_none")
+  root --> g6["AddToProjectTests (3)"]
+  class g6 groupnode
+  g6 --> t23("gueltiger_layer_wird_dem_projekt_hinzugefuegt")
+  g6 --> t24("ungueltiger_layer_wird_nicht_hinzugefuegt")
+  g6 --> t25("none_layer_wird_nicht_hinzugefuegt")
+  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
+  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
+  class t25 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
CreateLayerTests
test_wfs_baut_uri_ohne_getfeature_parameter
Prüft, dass für WFS die GetFeature-spezifischen Parameter aus der URI entfernt werden.grünnie geprüft
CreateLayerTests
test_wfs_mit_url_praefix_wird_nicht_doppelt_gesetzt
Prüft, dass ein bereits vorhandenes 'url='-Präfix im WFS-Link nicht verdoppelt wird.grünnie geprüft
CreateLayerTests
test_wms_baut_url_praefix_und_nutzt_rasterlayer
Prüft, dass WMS-Layer über QgsRasterLayer mit 'url='-Präfix erzeugt werden.grünnie geprüft
CreateLayerTests
test_rest_featureserver_ergaenzt_layer_index
Prüft, dass ein REST-Link auf '.../FeatureServer' automatisch um '/0' ergänzt wird.grünnie geprüft
CreateLayerTests
test_ogr_provider_nutzt_link_direkt
Prüft, dass ein OGR-Provider den Link unverändert an QgsVectorLayer übergibt.grünnie geprüft
CreateLayerTests
test_ungueltiger_layer_meldet_layer_nicht_verfuegbar
Prüft, dass ein ungültig erzeugter Layer als 'layer_nicht_verfuegbar' gemeldet wird und None liefert.grünnie geprüft
CreateLayerTests
test_ausnahme_beim_erstellen_wird_abgefangen
Prüft, dass eine Ausnahme beim Layer-Erstellen abgefangen und als Fehlerergebnis gemeldet wird.grünnie geprüft
TransformGeometryTests
test_fehlender_layer_liefert_geometrie_unveraendert
Prüft, dass ohne Quell- oder Ziel-Layer die Geometrie unverändert zurückgegeben wird.grünnie geprüft
TransformGeometryTests
test_gleiche_crs_liefert_geometrie_unveraendert
Prüft, dass bei identischem CRS von Quelle und Ziel keine Transformation stattfindet.grünnie geprüft
TransformGeometryTests
test_unterschiedliche_crs_klont_und_transformiert_geometrie
Prüft, dass bei unterschiedlichem CRS eine geklonte, transformierte Geometrie geliefert wird.grünnie geprüft
TransformExtentTests
test_gleiche_crs_liefert_extent_unveraendert
Prüft, dass bei identischem CRS von Quelle und Ziel der Extent unverändert bleibt.grünnie geprüft
TransformExtentTests
test_unterschiedliche_crs_nutzt_coordinate_transform
Prüft, dass bei unterschiedlichem CRS der Extent über QgsCoordinateTransform umgerechnet wird.grünnie geprüft
FilterByExtentTests
test_ungueltiger_layer_wird_unveraendert_zurueckgegeben
Prüft, dass ein ungültiger Layer von filter_by_extent unverändert zurückgegeben wird.grünnie geprüft
FilterByExtentTests
test_ohne_extent_wird_layer_unveraendert_zurueckgegeben
Prüft, dass ohne Extent (None) der Layer unverändert zurückgegeben wird.grünnie geprüft
FilterByExtentTests
test_falscher_layertyp_wird_unveraendert_zurueckgegeben
Prüft, dass ein Nicht-Vektor-Layer (z. B. Rasterlayer) unverändert zurückgegeben wird.grünnie geprüft
FilterByExtentTests
test_keine_treffer_liefert_none
Prüft, dass ein Raumfilter ohne Treffer None statt eines leeren Layers liefert.grünnie geprüft
FilterByExtentTests
test_abbruch_liefert_none_und_meldet_needs_user_action
Prüft, dass ein Abbruch während des Raumfilters None liefert und gemeldet wird.grünnie geprüft
FilterByExtentTests
test_erfolgreicher_filter_liefert_neuen_layer_mit_features
Prüft, dass ein erfolgreicher BBOX-Filter einen neuen Speicherlayer mit den gefundenen Features liefert.grünnie geprüft
FilterByLayerTests
test_ungueltiger_layer_oder_filterlayer_wird_unveraendert_zurueckgegeben
Prüft, dass ein ungültiger Haupt- oder Filter-Layer unverändert zurückgegeben wird.grünnie geprüft
FilterByLayerTests
test_filterlayer_ohne_features_liefert_none
Prüft, dass ein Filter-Layer ohne Features (leere Vereinigungsgeometrie) None liefert.grünnie geprüft
FilterByLayerTests
test_erfolgreicher_geometriefilter_liefert_neuen_layer
Prüft, dass ein erfolgreicher Geometriefilter einen neuen Speicherlayer mit den passenden Features liefert.grünnie geprüft
FilterByLayerTests
test_keine_ueberschneidung_liefert_none
Prüft, dass ohne überschneidende Features None statt eines leeren Layers geliefert wird.grünnie geprüft
AddToProjectTests
test_gueltiger_layer_wird_dem_projekt_hinzugefuegt
Prüft, dass ein gültiger Layer über QgsProject.instance().addMapLayer hinzugefügt wird.grünnie geprüft
AddToProjectTests
test_ungueltiger_layer_wird_nicht_hinzugefuegt
Prüft, dass ein ungültiger Layer nicht ans Projekt übergeben wird.grünnie geprüft
AddToProjectTests
test_none_layer_wird_nicht_hinzugefuegt
Prüft, dass ein fehlender Layer (None) nicht ans Projekt übergeben wird.grünnie geprüft

— (Docstring fehlt)

TestLayerpruefer 10
flowchart TD
   root(["test_layerpruefer.py"])
   class root rootnode
   root --> g1["TestLayerpruefer (10)"]
@@ -480,7 +682,7 @@
   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
-

Ungetestete Funktionen (strukturell) – 176 von 229

+

Ungetestete Funktionen (strukturell) – 156 von 229

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

@@ -510,10 +712,8 @@ - - - - + + @@ -527,8 +727,6 @@ - - @@ -544,26 +742,10 @@ - - - - - - - - - - - - - - - - diff --git a/docs/tests/testkatalog.md b/docs/tests/testkatalog.md index b46d301..06d44c2 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, 32 Testdateien, 348 Testfälle – 305 grün, 35 rot (Baseline), 8 übersprungen. -Mit Beschreibung (Docstring): 203 von 348 (58 %). -Fachlich geprüft: 55 von 348 (16 %) aktuell, 0 veraltet seit Codeänderung, 293 nie geprüft. -Strukturelle Lücken (heuristisch, Namensabgleich): 249 von 413 (60 %) Funktionen/Methoden ohne erkennbaren Testbezug – Abschnitt „Ungetestete Funktionen“. +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“. ## Zusammenfassung | Paket | Testdateien | Testfälle | grün | rot (Baseline) | übersprungen | mit Beschreibung | fachlich geprüft | ohne Testbezug | | --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | -| `sn_basis` | 15 | 96 | 96 | 0 | 0 | 96 von 96 (100 %) | 55 von 96 (57 %) | 176 von 229 (77 %) | +| `sn_basis` | 19 | 166 | 166 | 0 | 0 | 166 von 166 (100 %) | 55 von 166 (33 %) | 156 von 229 (68 %) | | `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** | **32** | **348** | **305** | **35** | **8** | **203 von 348 (58 %)** | **55 von 348 (16 %)** | **249 von 413 (60 %)** | +| **Summe** | **36** | **418** | **375** | **35** | **8** | **273 von 418 (65 %)** | **55 von 418 (13 %)** | **229 von 413 (55 %)** | ### Legende @@ -36,7 +36,7 @@ Strukturelle Lücken (heuristisch, Namensabgleich): 249 von 413 (60 %) Funktione ## Paket `sn_basis` -Plattform-Plugin, Ordner `Plugin_SN_Basis` – 15 Testdateien mit 96 Testfällen (96 grün, 0 rot, 0 übersprungen). +Plattform-Plugin, Ordner `Plugin_SN_Basis` – 19 Testdateien mit 166 Testfällen (166 grün, 0 rot, 0 übersprungen). ### `Plugin_SN_Basis/tests/test_bootstrap.py` @@ -78,6 +78,92 @@ Testgruppen: | `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 | +### `Plugin_SN_Basis/tests/test_datenabruf.py` + +Worum es in der Datei geht: Tests für sn_basis/modules/Datenabruf.py (Datenabruf-Kernpipeline, Issue #63). + +Testgruppen: + +- `DetermineSpatialFilterTests` (7 Testfälle): — (Docstring fehlt) +- `BuildProviderUrlTests` (9 Testfälle): — (Docstring fehlt) +- `FetchFeaturesTests` (5 Testfälle): — (Docstring fehlt) +- `DatenabrufOrchestrierungTests` (3 Testfälle): — (Docstring fehlt) + +| Testfall | prüft | Status | geprüft | +| --- | --- | --- | --- | +| `DetermineSpatialFilterTests.test_raumfilter_ohne_liefert_none` | Prüft, dass Raumfilter 'ohne' unabhängig vom Layer immer None liefert. | grün | nie geprüft | +| `DetermineSpatialFilterTests.test_fehlender_layer_liefert_none` | Prüft, dass ohne Verfahrensgebiet-Layer kein Raumfilter gebaut wird. | grün | nie geprüft | +| `DetermineSpatialFilterTests.test_unbekannter_raumfilter_liefert_none` | Prüft, dass ein unbekannter Raumfilter-Wert None liefert, statt einen Fehler zu werfen. | grün | nie geprüft | +| `DetermineSpatialFilterTests.test_verfahrensgebiet_liefert_extent_und_crs` | Prüft, dass Raumfilter 'Verfahrensgebiet' Extent und CRS des Verfahrensgebiet-Layers liefert. | grün | nie geprüft | +| `DetermineSpatialFilterTests.test_verfahrensgebiet_ohne_extent_liefert_none` | Prüft, dass ein Verfahrensgebiet-Layer ohne ermittelbaren Extent None liefert. | grün | nie geprüft | +| `DetermineSpatialFilterTests.test_pufferlayer_liefert_extent_des_pufferlayers` | Prüft, dass Raumfilter 'Pufferlayer' Extent und CRS des erzeugten Pufferlayers liefert. | grün | nie geprüft | +| `DetermineSpatialFilterTests.test_pufferlayer_ohne_puffer_liefert_none` | Prüft, dass 'Pufferlayer' None liefert, wenn kein Pufferlayer erzeugt werden konnte. | grün | nie geprüft | +| `BuildProviderUrlTests.test_wms_liefert_link_unveraendert` | Prüft, dass bei Provider WMS der Link unverändert durchgereicht wird, auch mit Raumfilter. | grün | nie geprüft | +| `BuildProviderUrlTests.test_url_praefix_wird_entfernt` | Prüft, dass ein vorangestelltes 'url=' aus dem Link entfernt wird. | grün | nie geprüft | +| `BuildProviderUrlTests.test_wfs_baut_standardparameter_und_bbox_mit_crs` | Prüft, dass WFS-Abrufe Standardparameter, umbenanntes TYPENAMES und BBOX mit CRS-URN erhalten. | grün | nie geprüft | +| `BuildProviderUrlTests.test_wfs_repariert_doppeltes_fragezeichen` | Prüft, dass ein zweites '?' im WFS-Link zu '&' korrigiert wird, statt eine ungültige URL zu erzeugen. | grün | nie geprüft | +| `BuildProviderUrlTests.test_wfs_ohne_raumfilter_setzt_keine_bbox` | Prüft, dass WFS ohne Raumfilter (bbox_geom=None) keinen BBOX-Parameter setzt. | grün | nie geprüft | +| `BuildProviderUrlTests.test_rest_provider_haengt_query_endpunkt_an` | Prüft, dass REST/ArcGIS-Links ohne '/query'-Endpunkt automatisch ergänzt werden. | grün | nie geprüft | +| `BuildProviderUrlTests.test_rest_provider_mit_bbox_baut_geometry_envelope_und_srid` | Prüft, dass REST-Abrufe mit Raumfilter eine Geometry-Envelope und inSR/outSR aus dem CRS setzen. | grün | nie geprüft | +| `BuildProviderUrlTests.test_default_provider_haengt_generischen_bbox_parameter_an` | Prüft, dass ein unbekannter Provider mit Raumfilter einen generischen bbox-Parameter erhält. | grün | nie geprüft | +| `BuildProviderUrlTests.test_default_provider_ohne_raumfilter_laesst_query_unveraendert` | Prüft, dass ein unbekannter Provider ohne Raumfilter keinen bbox-Parameter ergänzt. | grün | nie geprüft | +| `FetchFeaturesTests.test_wms_liefert_keine_features_ohne_fehler` | Prüft, dass bei Provider WMS kein Featureabruf stattfindet und kein Fehler gemeldet wird. | grün | nie geprüft | +| `FetchFeaturesTests.test_abbruch_vor_abruf_liefert_fehlermeldung` | Prüft, dass ein bereits gesetzter Abbruch vor dem eigentlichen Abruf erkannt wird. | grün | nie geprüft | +| `FetchFeaturesTests.test_json_featurecollection_wird_geparst` | Prüft, dass eine JSON-FeatureCollection-Antwort in eine Feature-Liste umgewandelt wird. | grün | nie geprüft | +| `FetchFeaturesTests.test_netzwerkfehler_wird_als_fehlermeldung_gemeldet` | Prüft, dass ein fehlgeschlagener HTTP-Abruf eine Fehlermeldung statt einer Ausnahme liefert. | grün | nie geprüft | +| `FetchFeaturesTests.test_wfs_xml_liefert_anzahl_aus_numberofmatched` | Prüft, dass eine WFS-XML-Antwort ohne JSON die Trefferzahl aus numberOfMatched übernimmt. | grün | nie geprüft | +| `DatenabrufOrchestrierungTests.test_fehlende_pflichtfelder_werden_als_ungueltig_gemeldet` | Prüft, dass eine Zeile ohne Link/Provider mit Aktion 'pflichtfelder_fehlen' gemeldet und übersprungen wird. | grün | nie geprüft | +| `DatenabrufOrchestrierungTests.test_wms_zeile_ohne_features_landet_in_ausserhalb` | Prüft, dass eine erfolgreich abgerufene WMS-Zeile mit 0 Features als 'ausserhalb' gezählt wird. | grün | nie geprüft | +| `DatenabrufOrchestrierungTests.test_abbruch_ueber_progress_stoppt_weitere_zeilen` | Prüft, dass ein Abbruch über das Progress-Objekt die Verarbeitung weiterer Zeilen stoppt. | grün | nie geprüft | + +### `Plugin_SN_Basis/tests/test_datenschreiber.py` + +Worum es in der Datei geht: Tests für sn_basis/modules/Datenschreiber.py (Schreib-/Ladepipeline, Issue #63). + +Testgruppen: + +- `WriteLayerToGpkgTests` (2 Testfälle): — (Docstring fehlt) +- `ResolveStylePathTests` (3 Testfälle): — (Docstring fehlt) +- `SchreibeDatenTests` (4 Testfälle): — (Docstring fehlt) +- `LadeLayerTests` (3 Testfälle): — (Docstring fehlt) +- `SchreibeLogTests` (2 Testfälle): — (Docstring fehlt) + +| Testfall | prüft | Status | geprüft | +| --- | --- | --- | --- | +| `WriteLayerToGpkgTests.test_ungueltiger_layer_liefert_fehlermeldung` | Prüft, dass ein ungültiger Layer eine Fehlermeldung statt eines Absturzes liefert. | grün | nie 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ün | nie geprüft | +| `ResolveStylePathTests.test_leerer_stilpfad_liefert_none` | Prüft, dass ein leerer oder fehlender Stilpfad None liefert. | grün | nie geprüft | +| `ResolveStylePathTests.test_absoluter_vorhandener_stilpfad_wird_aufgeloest` | Prüft, dass ein absoluter, vorhandener Stilpfad normalisiert und unverändert erkannt wird. | grün | nie 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ün | nie geprüft | +| `SchreibeDatenTests.test_ohne_speicherort_wirft_valueerror` | Prüft, dass schreibe_Daten ohne Speicherort einen ValueError wirft. | grün | nie 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ün | nie 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ün | nie 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ün | nie 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ün | nie geprüft | +| `LadeLayerTests.test_gueltiger_layer_wird_dem_projekt_hinzugefuegt` | Prüft, dass ein gültig ladbarer Layer ohne Fehlermeldung verarbeitet wird. | grün | nie 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ün | nie geprüft | +| `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_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). + +Testgruppen: + +- `ImportXlsxTests` (5 Testfälle): — (Docstring fehlt) +- `ExcelImporterKonstruktorTests` (2 Testfälle): — (Docstring fehlt) + +| Testfall | prüft | Status | geprüft | +| --- | --- | --- | --- | +| `ImportXlsxTests.test_erfolgreicher_import_liefert_zeilen_als_dicts` | Prüft, dass eine gültige Excel-Datei als Liste von Dicts mit den Header-Spalten geliefert wird. | grün | nie geprüft | +| `ImportXlsxTests.test_fehlende_datei_liefert_leere_liste` | Prüft, dass eine nicht vorhandene Datei eine leere Liste liefert, statt eine Ausnahme zu werfen. | grün | nie geprüft | +| `ImportXlsxTests.test_arbeitsblatt_ohne_header_liefert_leere_liste_und_meldet_kein_header` | Prüft, dass ein leeres Arbeitsblatt ohne Header-Zeile 'kein_header' meldet und eine leere Liste liefert. | grün | nie geprüft | +| `ImportXlsxTests.test_header_zeile_nur_leere_werte_liefert_kein_header` | Prüft, dass eine Header-Zeile aus ausschließlich leeren Zellen ebenfalls als 'kein_header' gilt. | grün | nie geprüft | +| `ImportXlsxTests.test_nicht_lesbare_datei_liefert_leere_liste_und_meldet_read_error` | Prüft, dass eine Datei mit ungültigem Excel-Inhalt 'read_error' meldet und eine leere Liste liefert. | grün | nie geprüft | +| `ExcelImporterKonstruktorTests.test_ohne_dateipfad_wirft_valueerror` | Prüft, dass ExcelImporter ohne Dateipfad einen ValueError wirft. | grün | nie geprüft | +| `ExcelImporterKonstruktorTests.test_ohne_pruefmanager_wirft_valueerror` | Prüft, dass ExcelImporter ohne Pruefmanager einen ValueError wirft. | grün | nie geprüft | + ### `Plugin_SN_Basis/tests/test_laenderkennung.py` Worum es in der Datei geht: Unit-Tests für `sn_basis.functions.laenderkennung`. @@ -94,6 +180,47 @@ 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_layerloader.py` + +Worum es in der Datei geht: Tests für sn_basis/modules/LayerLoader.py (Layer erzeugen/filtern/laden, Issue #63). + +Testgruppen: + +- `CreateLayerTests` (7 Testfälle): — (Docstring fehlt) +- `TransformGeometryTests` (3 Testfälle): — (Docstring fehlt) +- `TransformExtentTests` (2 Testfälle): — (Docstring fehlt) +- `FilterByExtentTests` (6 Testfälle): — (Docstring fehlt) +- `FilterByLayerTests` (4 Testfälle): — (Docstring fehlt) +- `AddToProjectTests` (3 Testfälle): — (Docstring fehlt) + +| Testfall | prüft | Status | geprüft | +| --- | --- | --- | --- | +| `CreateLayerTests.test_wfs_baut_uri_ohne_getfeature_parameter` | Prüft, dass für WFS die GetFeature-spezifischen Parameter aus der URI entfernt werden. | grün | nie geprüft | +| `CreateLayerTests.test_wfs_mit_url_praefix_wird_nicht_doppelt_gesetzt` | Prüft, dass ein bereits vorhandenes 'url='-Präfix im WFS-Link nicht verdoppelt wird. | grün | nie geprüft | +| `CreateLayerTests.test_wms_baut_url_praefix_und_nutzt_rasterlayer` | Prüft, dass WMS-Layer über QgsRasterLayer mit 'url='-Präfix erzeugt werden. | grün | nie geprüft | +| `CreateLayerTests.test_rest_featureserver_ergaenzt_layer_index` | Prüft, dass ein REST-Link auf '.../FeatureServer' automatisch um '/0' ergänzt wird. | grün | nie geprüft | +| `CreateLayerTests.test_ogr_provider_nutzt_link_direkt` | Prüft, dass ein OGR-Provider den Link unverändert an QgsVectorLayer übergibt. | grün | nie geprüft | +| `CreateLayerTests.test_ungueltiger_layer_meldet_layer_nicht_verfuegbar` | Prüft, dass ein ungültig erzeugter Layer als 'layer_nicht_verfuegbar' gemeldet wird und None liefert. | grün | nie geprüft | +| `CreateLayerTests.test_ausnahme_beim_erstellen_wird_abgefangen` | Prüft, dass eine Ausnahme beim Layer-Erstellen abgefangen und als Fehlerergebnis gemeldet wird. | grün | nie geprüft | +| `TransformGeometryTests.test_fehlender_layer_liefert_geometrie_unveraendert` | Prüft, dass ohne Quell- oder Ziel-Layer die Geometrie unverändert zurückgegeben wird. | grün | nie geprüft | +| `TransformGeometryTests.test_gleiche_crs_liefert_geometrie_unveraendert` | Prüft, dass bei identischem CRS von Quelle und Ziel keine Transformation stattfindet. | grün | nie geprüft | +| `TransformGeometryTests.test_unterschiedliche_crs_klont_und_transformiert_geometrie` | Prüft, dass bei unterschiedlichem CRS eine geklonte, transformierte Geometrie geliefert wird. | grün | nie geprüft | +| `TransformExtentTests.test_gleiche_crs_liefert_extent_unveraendert` | Prüft, dass bei identischem CRS von Quelle und Ziel der Extent unverändert bleibt. | grün | nie geprüft | +| `TransformExtentTests.test_unterschiedliche_crs_nutzt_coordinate_transform` | Prüft, dass bei unterschiedlichem CRS der Extent über QgsCoordinateTransform umgerechnet wird. | grün | nie geprüft | +| `FilterByExtentTests.test_ungueltiger_layer_wird_unveraendert_zurueckgegeben` | Prüft, dass ein ungültiger Layer von filter_by_extent unverändert zurückgegeben wird. | grün | nie geprüft | +| `FilterByExtentTests.test_ohne_extent_wird_layer_unveraendert_zurueckgegeben` | Prüft, dass ohne Extent (None) der Layer unverändert zurückgegeben wird. | grün | nie geprüft | +| `FilterByExtentTests.test_falscher_layertyp_wird_unveraendert_zurueckgegeben` | Prüft, dass ein Nicht-Vektor-Layer (z. B. Rasterlayer) unverändert zurückgegeben wird. | grün | nie geprüft | +| `FilterByExtentTests.test_keine_treffer_liefert_none` | Prüft, dass ein Raumfilter ohne Treffer None statt eines leeren Layers liefert. | grün | nie geprüft | +| `FilterByExtentTests.test_abbruch_liefert_none_und_meldet_needs_user_action` | Prüft, dass ein Abbruch während des Raumfilters None liefert und gemeldet wird. | grün | nie geprüft | +| `FilterByExtentTests.test_erfolgreicher_filter_liefert_neuen_layer_mit_features` | Prüft, dass ein erfolgreicher BBOX-Filter einen neuen Speicherlayer mit den gefundenen Features liefert. | grün | nie geprüft | +| `FilterByLayerTests.test_ungueltiger_layer_oder_filterlayer_wird_unveraendert_zurueckgegeben` | Prüft, dass ein ungültiger Haupt- oder Filter-Layer unverändert zurückgegeben wird. | grün | nie geprüft | +| `FilterByLayerTests.test_filterlayer_ohne_features_liefert_none` | Prüft, dass ein Filter-Layer ohne Features (leere Vereinigungsgeometrie) None liefert. | grün | nie geprüft | +| `FilterByLayerTests.test_erfolgreicher_geometriefilter_liefert_neuen_layer` | Prüft, dass ein erfolgreicher Geometriefilter einen neuen Speicherlayer mit den passenden Features liefert. | grün | nie geprüft | +| `FilterByLayerTests.test_keine_ueberschneidung_liefert_none` | Prüft, dass ohne überschneidende Features None statt eines leeren Layers geliefert wird. | grün | nie geprüft | +| `AddToProjectTests.test_gueltiger_layer_wird_dem_projekt_hinzugefuegt` | Prüft, dass ein gültiger Layer über QgsProject.instance().addMapLayer hinzugefügt wird. | grün | nie geprüft | +| `AddToProjectTests.test_ungueltiger_layer_wird_nicht_hinzugefuegt` | Prüft, dass ein ungültiger Layer nicht ans Projekt übergeben wird. | grün | nie geprüft | +| `AddToProjectTests.test_none_layer_wird_nicht_hinzugefuegt` | Prüft, dass ein fehlender Layer (None) nicht ans Projekt übergeben wird. | grün | nie geprüft | + ### `Plugin_SN_Basis/tests/test_layerpruefer.py` Worum es in der Datei geht: — (Docstring fehlt) @@ -781,7 +908,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 96 Testfällen ohne Beschreibung +### `sn_basis` – 0 von 166 Testfällen ohne Beschreibung Keine Lücken. @@ -986,7 +1113,7 @@ 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` – 176 von 229 (77 %) ohne Testbezug +### `sn_basis` – 156 von 229 (68 %) ohne Testbezug #### `functions/dialog_wrapper.py` (12) @@ -1034,12 +1161,10 @@ 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` (4) +#### `functions/qgiscore_wrapper.py` (2) -- `get_layer_extent` (Zeile 916) -- `create_buffer_layer` (Zeile 947) -- `layer_exists_in_gpkg` (Zeile 1013) -- `polygon_zu_linie` (Zeile 1052) +- `layer_exists_in_gpkg` (Zeile 1019) +- `polygon_zu_linie` (Zeile 1058) #### `functions/qgisui_wrapper.py` (9) @@ -1058,12 +1183,10 @@ Heuristik, kein Beweis: Diese Funktionen und Methoden kommen unter ihrem Namen i - `exec_dialog` (Zeile 60) - `debug_qt_status` (Zeile 64) -#### `functions/sys_wrapper.py` (5) +#### `functions/sys_wrapper.py` (3) - `join_path` (Zeile 36) - `ensure_dir` (Zeile 56) -- `read_text` (Zeile 69) -- `write_text` (Zeile 79) - `getattr_safe` (Zeile 102) #### `functions/verfahrensgebiet_manager.py` (5) @@ -1089,37 +1212,15 @@ Heuristik, kein Beweis: Diese Funktionen und Methoden kommen unter ihrem Namen i - `Dateipruefer._ist_gueltiger_gpkg_pfad` (Zeile 113) - `Dateipruefer._handle_leere_eingabe` (Zeile 227) -#### `modules/Datenabruf.py` (4) +#### `modules/Datenschreiber.py` (1) -- `Datenabruf.datenabruf` (Zeile 56) -- `Datenabruf._determine_spatial_filter` (Zeile 223) -- `Datenabruf._build_provider_url` (Zeile 278) -- `Datenabruf._fetch_features` (Zeile 421) - -#### `modules/Datenschreiber.py` (6) - -- `Datenschreiber._resolve_style_path` (Zeile 62) - `Datenschreiber._store_style_in_gpkg` (Zeile 77) -- `Datenschreiber.schreibe_Daten` (Zeile 152) -- `Datenschreiber.lade_Layer` (Zeile 249) -- `Datenschreiber.schreibe_log` (Zeile 344) -- `Datenschreiber._write_layer_to_gpkg` (Zeile 384) -#### `modules/excel_importer.py` (1) - -- `ExcelImporter.import_xlsx` (Zeile 32) - -#### `modules/LayerLoader.py` (9) +#### `modules/LayerLoader.py` (3) - `LayerLoader._was_canceled` (Zeile 42) - `LayerLoader._process_events` (Zeile 50) -- `LayerLoader._transform_geometry_to_layer_crs` (Zeile 57) -- `LayerLoader._transform_extent_to_layer_crs` (Zeile 85) -- `LayerLoader.create_layer` (Zeile 110) - `LayerLoader.apply_style` (Zeile 190) -- `LayerLoader.filter_by_extent` (Zeile 230) -- `LayerLoader.filter_by_layer` (Zeile 319) -- `LayerLoader.add_to_project` (Zeile 419) #### `modules/linkpruefer.py` (4) diff --git a/docs/wissen/fallstricke.md b/docs/wissen/fallstricke.md index aced3d6..a2dde29 100644 --- a/docs/wissen/fallstricke.md +++ b/docs/wissen/fallstricke.md @@ -8,6 +8,12 @@ Kurz, konkret, mit Datum und Quelle. Neue Einträge oben in der passenden Rubrik - **QGIS 3.40 ist seit Januar 2026 End of Life.** Aktueller LTR ist 3.44, Stable 4.2 (wird 25.09.2026 LTR). `workspace.toml` und alle `metadata.template` stehen noch auf `3.40` – offene Produktentscheidung, siehe `docs/konzept/07_qgis_tests_plan.md` Abschnitt 2. (04.09.2026, QGIS-Release-Fahrplan) - **Zwei Qt-Welten.** QGIS 3.40/3.44 laufen mit Qt5/PyQt5, QGIS 4 mit Qt6/PyQt6. `qt_wrapper` lädt PyQt6 zuerst, dann PyQt5, sonst Mock. Enum-Zugriffe unterscheiden sich (`Qt.AlignmentFlag.AlignTop` statt `Qt.AlignTop`), deshalb nur Wrapper-Aliase verwenden. (09/2026, Code) - **Mock-Modus ist kein QGIS.** `python scripts/run_tests.py` läuft in Sekunden, prüft aber nur Logik gegen Mock-Klassen. Geometrieoperationen, WFS, Layouts und Signale müssen in QGIS geprüft werden (`tests/test_qgis.bat` unter Windows). Manuelle QGIS-Tests im PR dokumentieren. (09/2026) +- **`_MockQgsProject` war unvollständig:** `transformContext()` und `addMapLayer()` fehlten, wodurch + `Datenschreiber._write_layer_to_gpkg` und `LayerLoader.add_to_project` im Mock-Modus für **jeden** gültigen + Layer eine Ausnahme geworfen bzw. eine Fehlermeldung erzeugt hätten – nicht durch einen Fehler in diesen + 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). - **`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`)
DateiFunktion/MethodeZeile
functions/dialog_wrapper.pyshow_info_dialog42
functions/dialog_wrapper.pyask_text56
functions/os_wrapper.pybasename68
functions/os_wrapper.pyis_case_sensitive_fs80
functions/os_wrapper.pypath_suffix96
functions/qgiscore_wrapper.pyget_layer_extent916
functions/qgiscore_wrapper.pycreate_buffer_layer947
functions/qgiscore_wrapper.pylayer_exists_in_gpkg1013
functions/qgiscore_wrapper.pypolygon_zu_linie1052
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/qt_wrapper.pydebug_qt_status64
functions/sys_wrapper.pyjoin_path36
functions/sys_wrapper.pyensure_dir56
functions/sys_wrapper.pyread_text69
functions/sys_wrapper.pywrite_text79
functions/sys_wrapper.pygetattr_safe102
functions/verfahrensgebiet_manager.py_on_layers_added109
functions/verfahrensgebiet_manager.py_on_layer_removed114
modules/Dateipruefer.pyDateipruefer._ist_leer98
modules/Dateipruefer.pyDateipruefer._ist_gueltiger_gpkg_pfad113
modules/Dateipruefer.pyDateipruefer._handle_leere_eingabe227
modules/Datenabruf.pyDatenabruf.datenabruf56
modules/Datenabruf.pyDatenabruf._determine_spatial_filter223
modules/Datenabruf.pyDatenabruf._build_provider_url278
modules/Datenabruf.pyDatenabruf._fetch_features421
modules/Datenschreiber.pyDatenschreiber._resolve_style_path62
modules/Datenschreiber.pyDatenschreiber._store_style_in_gpkg77
modules/Datenschreiber.pyDatenschreiber.schreibe_Daten152
modules/Datenschreiber.pyDatenschreiber.lade_Layer249
modules/Datenschreiber.pyDatenschreiber.schreibe_log344
modules/Datenschreiber.pyDatenschreiber._write_layer_to_gpkg384
modules/excel_importer.pyExcelImporter.import_xlsx32
modules/LayerLoader.pyLayerLoader._was_canceled42
modules/LayerLoader.pyLayerLoader._process_events50
modules/LayerLoader.pyLayerLoader._transform_geometry_to_layer_crs57
modules/LayerLoader.pyLayerLoader._transform_extent_to_layer_crs85
modules/LayerLoader.pyLayerLoader.create_layer110
modules/LayerLoader.pyLayerLoader.apply_style190
modules/LayerLoader.pyLayerLoader.filter_by_extent230
modules/LayerLoader.pyLayerLoader.filter_by_layer319
modules/LayerLoader.pyLayerLoader.add_to_project419
modules/linkpruefer.pyLinkpruefer._pfad33
modules/linkpruefer.pyLinkpruefer._ist_url41
modules/linkpruefer.pyLinkpruefer._pruefe_url81