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

sn_basis steht laut Prüfstand jetzt bei 0 ungeklärten Funktionen. Fallstricke.md um den
Windows-Fallstrick "sqlite3-Verbindung aus with-Block schließt nicht, TemporaryDirectory-
Cleanup schlägt fehl" ergänzt (Fund aus Basis #70).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-21 08:50:32 +02:00
co-authored by Claude Sonnet 5
parent cd11e409a3
commit 049a5ffe1d
3 changed files with 85 additions and 52 deletions
File diff suppressed because one or more lines are too long
+29 -27
View File
@@ -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, 49 Testdateien, 569 Testfälle – 526 grün, 35 rot (Baseline), 8 übersprungen.
Mit Beschreibung (Docstring): 424 von 569 (75 %).
Fachlich geprüft: 55 von 569 (10 %) aktuell, 0 veraltet seit Codeänderung, 514 nie geprüft.
Strukturelle Lücken (heuristisch, Namensabgleich): 149 von 413 (36 %) Funktionen/Methoden ohne erkennbaren Testbezug – Abschnitt „Ungetestete Funktionen“.
Gesamt: 3 Pakete, 49 Testdateien, 580 Testfälle – 537 grün, 35 rot (Baseline), 8 übersprungen.
Mit Beschreibung (Docstring): 435 von 580 (75 %).
Fachlich geprüft: 55 von 580 (9 %) aktuell, 0 veraltet seit Codeänderung, 525 nie geprüft.
Strukturelle Lücken (heuristisch, Namensabgleich): 145 von 413 (35 %) 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` | 32 | 317 | 317 | 0 | 0 | 317 von 317 (100 %) | 55 von 317 (17 %) | 76 von 229 (33 %) |
| `sn_basis` | 32 | 328 | 328 | 0 | 0 | 328 von 328 (100 %) | 55 von 328 (17 %) | 72 von 229 (31 %) |
| `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** | **49** | **569** | **526** | **35** | **8** | **424 von 569 (75 %)** | **55 von 569 (10 %)** | **149 von 413 (36 %)** |
| **Summe** | **49** | **580** | **537** | **35** | **8** | **435 von 580 (75 %)** | **55 von 580 (9 %)** | **145 von 413 (35 %)** |
### Legende
@@ -36,7 +36,7 @@ Strukturelle Lücken (heuristisch, Namensabgleich): 149 von 413 (36 %) Funktione
## Paket `sn_basis`
Plattform-Plugin, Ordner `Plugin_SN_Basis` – 32 Testdateien mit 317 Testfällen (317 grün, 0 rot, 0 übersprungen).
Plattform-Plugin, Ordner `Plugin_SN_Basis` – 32 Testdateien mit 328 Testfällen (328 grün, 0 rot, 0 übersprungen).
### `Plugin_SN_Basis/tests/test_base_dockwidget.py`
@@ -85,7 +85,7 @@ Worum es in der Datei geht: — (Docstring fehlt)
Testgruppen:
- `TestDateipruefer` (12 Testfälle): — (Docstring fehlt)
- `TestDateipruefer` (17 Testfälle): — (Docstring fehlt)
| Testfall | prüft | Status | geprüft |
| --- | --- | --- | --- |
@@ -101,6 +101,11 @@ Testgruppen:
| `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 |
| `TestDateipruefer.test_ist_leer_erkennt_none_und_nicht_string_als_leer` | Prüft, dass _ist_leer sowohl None als auch einen Nicht-String-Wert als leer meldet. | grün | nie geprüft |
| `TestDateipruefer.test_ist_leer_erkennt_reinen_whitespace_als_leer` | Prüft, dass _ist_leer eine Eingabe aus reinen Leerzeichen als leer meldet. | grün | nie geprüft |
| `TestDateipruefer.test_ist_leer_meldet_pfad_mit_sichtbaren_zeichen_nicht_als_leer` | Prüft, dass _ist_leer einen Pfad mit sichtbaren Zeichen nicht als leer meldet. | grün | nie geprüft |
| `TestDateipruefer.test_leere_eingabe_bevorzugt_leereingabe_erlaubt_vor_standarddatei` | Prüft, dass bei leerer Eingabe leereingabe_erlaubt Vorrang vor einer gesetzten Standarddatei hat. | grün | nie geprüft |
| `TestDateipruefer.test_leere_eingabe_bevorzugt_standarddatei_vor_temporaer_erlaubt` | Prüft, dass bei leerer Eingabe eine gesetzte Standarddatei Vorrang vor temporaer_erlaubt hat. | grün | nie geprüft |
### `Plugin_SN_Basis/tests/test_datenabruf.py`
@@ -151,6 +156,7 @@ Testgruppen:
- `SchreibeDatenTests` (4 Testfälle): — (Docstring fehlt)
- `LadeLayerTests` (3 Testfälle): — (Docstring fehlt)
- `SchreibeLogTests` (2 Testfälle): — (Docstring fehlt)
- `StoreStyleInGpkgTests` (4 Testfälle): Tests für Datenschreiber._store_style_in_gpkg (Issue #70, nachgezogen aus #63).
| Testfall | prüft | Status | geprüft |
| --- | --- | --- | --- |
@@ -168,6 +174,10 @@ Testgruppen:
| `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 |
| `StoreStyleInGpkgTests.test_legt_tabelle_an_und_speichert_stil_als_default` | Prüft, dass _store_style_in_gpkg die layer_styles-Tabelle anlegt und den Stil als Default speichert. | grün | nie geprüft |
| `StoreStyleInGpkgTests.test_setzt_bisherigen_default_stil_desselben_layers_zurueck` | Prüft, dass _store_style_in_gpkg den useAsDefault-Wert vorhandener Stile desselben Layers zurücksetzt. | grün | nie geprüft |
| `StoreStyleInGpkgTests.test_liest_geometriespalte_ueber_geometrycolumn_aus` | Prüft, dass _store_style_in_gpkg die Geometriespalte eines Layers mit geometryColumn() übernimmt. | grün | nie geprüft |
| `StoreStyleInGpkgTests.test_fehlender_stilpfad_meldet_fehler_ueber_pruefmanager_statt_absturz` | Prüft, dass ein nicht lesbarer Stilpfad über den Pruefmanager gemeldet wird statt eine Exception zu werfen. | grün | nie geprüft |
### `Plugin_SN_Basis/tests/test_dockmanager.py`
@@ -536,7 +546,7 @@ Worum es in der Datei geht: — (Docstring fehlt)
Testgruppen:
- `TestPruefmanager` (24 Testfälle): — (Docstring fehlt)
- `TestPruefmanager` (26 Testfälle): — (Docstring fehlt)
| Testfall | prüft | Status | geprüft |
| --- | --- | --- | --- |
@@ -556,6 +566,8 @@ Testgruppen:
| `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_entfernen` | Prüft, dass die Nutzerwahl 'entfernen' bei bestehendem Verfahrensgebiet zur Aktion 'verfahrensgebiet_entfernen' führt. | grün | nie geprüft |
| `TestPruefmanager.test_verfahrensgebiet_layer_existiert_ersetzen` | Prüft, dass die Nutzerwahl 'ersetzen' bei bestehendem Verfahrensgebiet zur Aktion 'verfahrensgebiet_ersetzen' führt. | 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 |
@@ -1236,7 +1248,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 317 Testfällen ohne Beschreibung
### `sn_basis` – 0 von 328 Testfällen ohne Beschreibung
Keine Lücken.
@@ -1442,7 +1454,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.
„beabsichtigt“ liest den Docstring der Funktion: Enthält er einen Vermerk wie „von Test abgesehen, weil …“ oder „Test ausgesetzt, zunächst Refactor“, gilt der fehlende Test als bewusste Entscheidung. Alles andere ist „ungeklärt“ – die eigentliche Arbeitsliste.
### `sn_basis` – 76 von 229 (33 %) ohne Testbezug (9 ungeklärt, 67 beabsichtigt)
### `sn_basis` – 72 von 229 (31 %) ohne Testbezug (0 ungeklärt, 72 beabsichtigt)
#### `functions/dialog_wrapper.py` (9)
@@ -1484,15 +1496,6 @@ Heuristik, kein Beweis: Diese Funktionen und Methoden kommen unter ihrem Namen i
- `DataGrabber._process_database_source` (Zeile 312) — **beabsichtigt:** von Test abgesehen, weil vernachlässigbar; HD 18.09.2026
- `DataGrabber._process_service_source` (Zeile 324) — **beabsichtigt:** von Test abgesehen, weil vernachlässigbar; HD 18.09.2026
#### `modules/Dateipruefer.py` (2)
- `Dateipruefer._ist_leer` (Zeile 98) — ungeklärt
- `Dateipruefer._handle_leere_eingabe` (Zeile 227) — ungeklärt
#### `modules/Datenschreiber.py` (1)
- `Datenschreiber._store_style_in_gpkg` (Zeile 77) — ungeklärt
#### `modules/LayerLoader.py` (2)
- `LayerLoader._was_canceled` (Zeile 42) — **beabsichtigt:** von Test abgesehen, weil vernachlässigbar; HD 18.09.2026
@@ -1500,9 +1503,9 @@ Heuristik, kein Beweis: Diese Funktionen und Methoden kommen unter ihrem Namen i
#### `modules/linkpruefer.py` (3)
- `Linkpruefer._ist_url` (Zeile 41) — ungeklärt
- `Linkpruefer._pruefe_url` (Zeile 81) — ungeklärt
- `Linkpruefer._pruefe_dateipfad` (Zeile 115) — ungeklärt
- `Linkpruefer._ist_url` (Zeile 41) — **beabsichtigt:** von Test abgesehen, weil bereits über pruefe() in test_linkpruefer.py indirekt
- `Linkpruefer._pruefe_url` (Zeile 84) — **beabsichtigt:** von Test abgesehen, weil bereits über pruefe() in test_linkpruefer.py vollständig
- `Linkpruefer._pruefe_dateipfad` (Zeile 121) — **beabsichtigt:** von Test abgesehen, weil bereits über pruefe() in test_linkpruefer.py vollständig
#### `modules/print_layout.py` (11)
@@ -1547,13 +1550,12 @@ Heuristik, kein Beweis: Diese Funktionen und Methoden kommen unter ihrem Namen i
- `PrintLogic._get_plot_dimensions_mm` (Zeile 1078) — **beabsichtigt:** Test ausgesetzt, zunächst Refactor
- `PrintLogic._get_required_map_dimensions_mm` (Zeile 1088) — **beabsichtigt:** Test ausgesetzt, zunächst Refactor
#### `modules/Pruefmanager.py` (5)
#### `modules/Pruefmanager.py` (4)
- `Pruefmanager.report_summary` (Zeile 45) — **beabsichtigt:** von Test abgesehen, weil vernachlässigbar; HD 18.09.2026
- `Pruefmanager.zeige_hinweis` (Zeile 63) — **beabsichtigt:** von Test abgesehen, weil vernachlässigbar; HD 18.09.2026
- `Pruefmanager._handle_datei_existiert` (Zeile 87) — ungeklärt
- `Pruefmanager._handle_verfahrensgebiet_layer_existiert` (Zeile 234) — ungeklärt
- `Pruefmanager._ask_use_or_replace_pufferlayer` (Zeile 277) — ungeklärt
- `Pruefmanager._handle_datei_existiert` (Zeile 87) — **beabsichtigt:** von Test abgesehen, weil bereits über verarbeite() in test_pruefmanager.py vollständig
- `Pruefmanager._ask_use_or_replace_pufferlayer` (Zeile 280) — **beabsichtigt:** von Test abgesehen, weil toter Code: referenziert self.pruefmanager, das auf
#### `ui/tabs/print_tab.py` (7)
+7
View File
@@ -8,6 +8,13 @@ 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)
- **`sqlite3.connect()` in einem `with`-Block schließt die Verbindung nicht.** Das `with`-Statement committet
bzw. rollt nur zurück, `conn` bleibt offen (siehe `Datenschreiber._store_style_in_gpkg`). Unter Windows
sperrt das die Datei, bis die Verbindung per Garbage Collection oder explizitem `close()` freigegeben wird –
ein Test, der danach dasselbe `tempfile.TemporaryDirectory()` verlassen will, bricht mit
`PermissionError: [WinError 32]` ab. Betroffene Produktionsfunktion nicht nebenbei umschreiben (kein
Refactoring im Testticket); stattdessen im Test `tempfile.mkdtemp()` + `try/finally` mit `gc.collect()`
vor `shutil.rmtree(..., ignore_errors=True)` verwenden. (21.09.2026, Issue Basis #70)
- **`_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