Testkatalog neu erzeugt, Wissensbasis für Basis #65 nachgezogen

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 <noreply@anthropic.com>
This commit is contained in:
2026-09-18 11:20:37 +02:00
co-authored by Claude Sonnet 5
parent b47f740c10
commit 3f985ce209
4 changed files with 542 additions and 156 deletions
+1 -1
View File
@@ -63,7 +63,7 @@ Legende: ⚠ = über 600 Zeilen, nie komplett laden, per `grep -n "def "` navigi
| Pfad | Zweck | | 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) | | `styles/` | QML-Stile (Verfahrensgebiet, LSG, Denkmalschutz, Flurstücksbeschriftung) |
| `data/landkreise.json` | Landkreise mit Kennzahl | | `data/landkreise.json` | Landkreise mit Kennzahl |
| `assets/plan-qgis340ExitCrashFix.prompt.md` | KI-Planungsnotiz zum Exit-Crash (historisch) | | `assets/plan-qgis340ExitCrashFix.prompt.md` | KI-Planungsnotiz zum Exit-Crash (historisch) |
File diff suppressed because one or more lines are too long
+225 -87
View File
@@ -10,19 +10,19 @@ selbst (Docstrings) und aus der Testbaseline.
Stand der Baseline: `docs/status/testbaseline.json` (SHA-256 `aeabc946a7f3`) Stand der Baseline: `docs/status/testbaseline.json` (SHA-256 `aeabc946a7f3`)
Stand des Prüf-Audits: `docs/status/testpruefungen.json` (SHA-256 `68b590c8feef`) 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. Gesamt: 3 Pakete, 46 Testdateien, 501 Testfälle – 458 grün, 35 rot (Baseline), 8 übersprungen.
Mit Beschreibung (Docstring): 273 von 418 (65 %). Mit Beschreibung (Docstring): 356 von 501 (71 %).
Fachlich geprüft: 55 von 418 (13 %) aktuell, 0 veraltet seit Codeänderung, 363 nie geprüft. Fachlich geprüft: 55 von 501 (11 %) aktuell, 0 veraltet seit Codeänderung, 446 nie geprüft.
Strukturelle Lücken (heuristisch, Namensabgleich): 229 von 413 (55 %) Funktionen/Methoden ohne erkennbaren Testbezug – Abschnitt „Ungetestete Funktionen“. Strukturelle Lücken (heuristisch, Namensabgleich): 188 von 413 (46 %) Funktionen/Methoden ohne erkennbaren Testbezug – Abschnitt „Ungetestete Funktionen“.
## Zusammenfassung ## Zusammenfassung
| Paket | Testdateien | Testfälle | grün | rot (Baseline) | übersprungen | mit Beschreibung | fachlich geprüft | ohne Testbezug | | 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_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 %) | | `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 ### Legende
@@ -36,7 +36,23 @@ Strukturelle Lücken (heuristisch, Namensabgleich): 229 von 413 (55 %) Funktione
## Paket `sn_basis` ## 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` ### `Plugin_SN_Basis/tests/test_bootstrap.py`
@@ -67,7 +83,7 @@ Worum es in der Datei geht: — (Docstring fehlt)
Testgruppen: Testgruppen:
- `TestDateipruefer` (6 Testfälle): — (Docstring fehlt) - `TestDateipruefer` (12 Testfälle): — (Docstring fehlt)
| Testfall | prüft | Status | geprüft | | 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_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_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_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` ### `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_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 | | `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` ### `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). 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_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 | | `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` ### `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). 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_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 | | `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` ### `Plugin_SN_Basis/tests/test_print_layout.py`
Worum es in der Datei geht: — (Docstring fehlt) 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_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 | | `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` ### `Plugin_SN_Basis/tests/test_pruefmanager.py`
Worum es in der Datei geht: — (Docstring fehlt) Worum es in der Datei geht: — (Docstring fehlt)
Testgruppen: Testgruppen:
- `TestPruefmanager` (14 Testfälle): — (Docstring fehlt) - `TestPruefmanager` (24 Testfälle): — (Docstring fehlt)
| Testfall | prüft | Status | geprüft | | 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_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_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_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` ### `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_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 | | `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` ### `Plugin_SN_Basis/tests/test_stilpruefer.py`
Worum es in der Datei geht: — (Docstring fehlt) 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: Testgruppen:
- `TestGetPluginRoot` (1 Testfälle): — (Docstring fehlt) - `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 | | 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 | | `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` ### `Plugin_SN_Basis/tests/test_text_wrapper.py`
@@ -407,11 +600,13 @@ Testgruppen:
### `Plugin_SN_Basis/tests/test_verfahrensgebiet_manager.py` ### `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: Testgruppen:
- `TestVerfahrensgebietManager` (5 Testfälle): — (Docstring fehlt) - `TestVerfahrensgebietManager` (5 Testfälle): — (Docstring fehlt)
- `OnHandlerTests` (5 Testfälle): — (Docstring fehlt)
- `ListenerSetupTests` (3 Testfälle): — (Docstring fehlt)
| Testfall | prüft | Status | geprüft | | 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_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_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 | | `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` ## 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, aus dem Quelltext erschließen. Jeder Eintrag braucht eine einzeilige Beschreibung im Testfall,
dann verschwindet er hier von selbst. 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. 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. 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) - `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_vg_laden` (Zeile 185)
- `ask_detailpruefung_oder_abbrechen` (Zeile 235) - `ask_detailpruefung_oder_abbrechen` (Zeile 235)
- `ProgressDialog.set_total` (Zeile 328) - `ProgressDialog.set_total` (Zeile 328)
- `ProgressDialog.set_value` (Zeile 336) - `ProgressDialog.set_value` (Zeile 336)
- `ProgressDialog.set_label` (Zeile 348) - `ProgressDialog.set_label` (Zeile 348)
- `ProgressDialog.is_canceled` (Zeile 357) - `ProgressDialog.is_canceled` (Zeile 357)
- `ProgressDialog.close` (Zeile 366)
- `ProgressDialog.raise_to_front` (Zeile 373) - `ProgressDialog.raise_to_front` (Zeile 373)
- `create_progress_dialog` (Zeile 390) - `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) - `info` (Zeile 67)
- `error` (Zeile 77)
- `success` (Zeile 82) - `success` (Zeile 82)
#### `functions/os_wrapper.py` (6) #### `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) - `is_case_sensitive_fs` (Zeile 80)
- `path_suffix` (Zeile 96) - `path_suffix` (Zeile 96)
#### `functions/qgiscore_wrapper.py` (2) #### `functions/qgisui_wrapper.py` (5)
- `layer_exists_in_gpkg` (Zeile 1019)
- `polygon_zu_linie` (Zeile 1058)
#### `functions/qgisui_wrapper.py` (9)
- `get_main_window` (Zeile 131) - `get_main_window` (Zeile 131)
- `add_dock_widget` (Zeile 149)
- `remove_dock_widget` (Zeile 156)
- `find_dock_widgets` (Zeile 163)
- `add_menu` (Zeile 178) - `add_menu` (Zeile 178)
- `remove_menu` (Zeile 188) - `remove_menu` (Zeile 188)
- `add_toolbar` (Zeile 201) - `add_toolbar` (Zeile 201)
- `remove_toolbar` (Zeile 208) - `remove_toolbar` (Zeile 208)
- `add_layer_to_project` (Zeile 217)
#### `functions/qt_wrapper.py` (2) #### `functions/qt_wrapper.py` (2)
- `exec_dialog` (Zeile 60) - `exec_dialog` (Zeile 60)
- `debug_qt_status` (Zeile 64) - `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) #### `modules/DataGrabber.py` (4)
- `DataGrabber.set_source` (Zeile 68) - `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._process_service_source` (Zeile 320)
- `DataGrabber._aggregate_results` (Zeile 330) - `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_leer` (Zeile 98)
- `Dateipruefer._ist_gueltiger_gpkg_pfad` (Zeile 113)
- `Dateipruefer._handle_leere_eingabe` (Zeile 227) - `Dateipruefer._handle_leere_eingabe` (Zeile 227)
#### `modules/Datenschreiber.py` (1) #### `modules/Datenschreiber.py` (1)
- `Datenschreiber._store_style_in_gpkg` (Zeile 77) - `Datenschreiber._store_style_in_gpkg` (Zeile 77)
#### `modules/LayerLoader.py` (3) #### `modules/LayerLoader.py` (2)
- `LayerLoader._was_canceled` (Zeile 42) - `LayerLoader._was_canceled` (Zeile 42)
- `LayerLoader._process_events` (Zeile 50) - `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._ist_url` (Zeile 41)
- `Linkpruefer._pruefe_url` (Zeile 81) - `Linkpruefer._pruefe_url` (Zeile 81)
- `Linkpruefer._pruefe_dateipfad` (Zeile 115) - `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._get_required_map_dimensions_mm` (Zeile 1061)
- `PrintLogic.druckvorlage_anlegen` (Zeile 1161) - `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.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.report_summary` (Zeile 45)
- `Pruefmanager.zeige_hinweis` (Zeile 62) - `Pruefmanager.zeige_hinweis` (Zeile 62)
- `Pruefmanager.frage_ja_nein` (Zeile 67)
- `Pruefmanager.frage_text` (Zeile 73)
- `Pruefmanager._handle_datei_existiert` (Zeile 83) - `Pruefmanager._handle_datei_existiert` (Zeile 83)
- `Pruefmanager._handle_verfahrensgebiet_layer_existiert` (Zeile 230) - `Pruefmanager._handle_verfahrensgebiet_layer_existiert` (Zeile 230)
- `Pruefmanager._ask_use_or_replace_pufferlayer` (Zeile 273) - `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) #### `ui/navigation.py` (6)
- `Navigation.init_ui` (Zeile 33) - `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_action` (Zeile 104)
- `Navigation.remove_all` (Zeile 115) - `Navigation.remove_all` (Zeile 115)
#### `ui/tabs/print_tab.py` (27) #### `ui/tabs/print_tab.py` (25)
- `PrintTab.set_services` (Zeile 94) - `PrintTab.set_services` (Zeile 94)
- `PrintTab._build_ui` (Zeile 115) - `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._format_druckpuffer_label` (Zeile 425)
- `PrintTab._on_vorlage_erstellen` (Zeile 428) - `PrintTab._on_vorlage_erstellen` (Zeile 428)
- `PrintTab._disconnect_project_signals` (Zeile 441) - `PrintTab._disconnect_project_signals` (Zeile 441)
- `PrintTab.cleanup` (Zeile 459)
- `PrintTab._connect_project_signals` (Zeile 464) - `PrintTab._connect_project_signals` (Zeile 464)
- `PrintTab._on_project_changed` (Zeile 482)
- `PrintTab._toggle_atlas` (Zeile 489) - `PrintTab._toggle_atlas` (Zeile 489)
- `PrintTab._restore_atlas_layer_selection` (Zeile 495) - `PrintTab._restore_atlas_layer_selection` (Zeile 495)
- `PrintTab._disconnect_theme_collection_signals` (Zeile 519) - `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._on_auswahl_as_atlas_clicked` (Zeile 641)
- `PrintTab._populate_atlas_layer_combo` (Zeile 679) - `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._build_input` (Zeile 118)
- `SettingsTab.save_data` (Zeile 130)
- `SettingsTab.load_data` (Zeile 149)
### `sn_verfahrensgebiet` – 34 von 104 (33 %) ohne Testbezug ### `sn_verfahrensgebiet` – 34 von 104 (33 %) ohne Testbezug
+13
View File
@@ -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, 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 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). „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) - **`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`) - **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`) - **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`)