37 neue Testfälle für die 31 verbleibenden "vielleicht testen"- Funktionen: os_wrapper.is_case_sensitive_fs, qgiscore_wrapper. create_buffer_layer (nur die Wächter, echte Pufferlogik importiert qgis.core direkt), qgisui_wrapper.find_dock_widgets/add_menu/remove_menu, DataGrabber._aggregate_results, pruef_ergebnis.dateipfad, Navigation (add_action, finalize_menu_and_toolbar, set_active_plugin, remove_action, remove_all), SettingsTab._build_input und PrintTab (18 Methoden: Zustandslogik, Signal-Handling, Atlas-/Theme-Verwaltung). PrintTab._build_ui bekommt stattdessen den Vermerk "von Test abgesehen, weil vernachlässigbar; HD 18.09.2026" - reine Qt-Widget-Konstruktion ohne eigenständig prüfbare Logik. Damit ist die Kategorie "vielleicht testen" für sn_basis aufgelöst: jede Funktion ist jetzt getestet oder mit einem begründeten Vermerk versehen. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
108 lines
4.9 KiB
Python
108 lines
4.9 KiB
Python
"""Tests für sn_basis/functions/qgisui_wrapper.py::add_layer_to_project/find_dock_widgets/add_menu/remove_menu (Issue #65/#67)."""
|
|
|
|
import unittest
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
from sn_basis.functions import qgisui_wrapper as qui
|
|
|
|
|
|
class AddLayerToProjectTests(unittest.TestCase):
|
|
def test_none_layer_liefert_false(self):
|
|
"""Prüft, dass add_layer_to_project für einen fehlenden Layer (None) False liefert."""
|
|
self.assertFalse(qui.add_layer_to_project(None))
|
|
|
|
def test_mock_modus_liefert_true_ohne_projektzugriff(self):
|
|
"""Prüft, dass im Mock-Modus (ohne QGIS) ein gültiger Layer True liefert, ohne das Projekt anzufassen."""
|
|
with patch.object(qui, "QGIS_AVAILABLE", False):
|
|
self.assertTrue(qui.add_layer_to_project(object()))
|
|
|
|
def test_mit_qgis_fuegt_layer_dem_projekt_hinzu(self):
|
|
"""Prüft, dass bei verfügbarem QGIS der Layer über QgsProject.instance().addMapLayer hinzugefügt wird."""
|
|
layer = object()
|
|
mock_project = MagicMock()
|
|
with patch.object(qui, "QGIS_AVAILABLE", True), patch.object(qui, "QgsProject", mock_project):
|
|
ergebnis = qui.add_layer_to_project(layer)
|
|
|
|
self.assertTrue(ergebnis)
|
|
mock_project.instance.return_value.addMapLayer.assert_called_once_with(layer)
|
|
|
|
def test_mit_qgis_fehler_liefert_false(self):
|
|
"""Prüft, dass ein Fehler beim Hinzufügen zum Projekt abgefangen wird und False liefert."""
|
|
mock_project = MagicMock()
|
|
mock_project.instance.side_effect = RuntimeError("kaputt")
|
|
with patch.object(qui, "QGIS_AVAILABLE", True), patch.object(qui, "QgsProject", mock_project):
|
|
self.assertFalse(qui.add_layer_to_project(object()))
|
|
|
|
|
|
class FindDockWidgetsTests(unittest.TestCase):
|
|
def test_ohne_main_window_liefert_leere_liste(self):
|
|
"""Prüft, dass find_dock_widgets ohne verfügbares Hauptfenster eine leere Liste liefert."""
|
|
with patch.object(qui, "get_main_window", return_value=None):
|
|
self.assertEqual(qui.find_dock_widgets(), [])
|
|
|
|
def test_liefert_dock_widgets_des_main_window(self):
|
|
"""Prüft, dass find_dock_widgets die vom Hauptfenster gefundenen Dock-Widgets durchreicht."""
|
|
fake_docks = [object(), object()]
|
|
fake_window = MagicMock()
|
|
fake_window.findChildren.return_value = fake_docks
|
|
with patch.object(qui, "get_main_window", return_value=fake_window):
|
|
self.assertEqual(qui.find_dock_widgets(), fake_docks)
|
|
|
|
def test_fehler_beim_suchen_liefert_leere_liste(self):
|
|
"""Prüft, dass ein Fehler beim Suchen der Dock-Widgets abgefangen wird und eine leere Liste liefert."""
|
|
fake_window = MagicMock()
|
|
fake_window.findChildren.side_effect = RuntimeError("kaputt")
|
|
with patch.object(qui, "get_main_window", return_value=fake_window):
|
|
self.assertEqual(qui.find_dock_widgets(), [])
|
|
|
|
|
|
class _FakeMenu:
|
|
def __init__(self) -> None:
|
|
self.menuAction = lambda: "MENU_ACTION"
|
|
|
|
|
|
class AddRemoveMenuTests(unittest.TestCase):
|
|
def test_add_menu_ohne_main_window_tut_nichts(self):
|
|
"""Prüft, dass add_menu ohne Hauptfenster keine Ausnahme wirft."""
|
|
fake_iface = MagicMock()
|
|
fake_iface.mainWindow.return_value = None
|
|
with patch.object(qui, "iface", fake_iface):
|
|
qui.add_menu(_FakeMenu()) # darf keine Ausnahme werfen
|
|
|
|
def test_add_menu_mit_echtem_qt_menu_fuegt_es_der_menubar_hinzu(self):
|
|
"""Prüft, dass ein echtes Qt-Menü (mit menuAction) der Menüleiste hinzugefügt wird."""
|
|
menu = _FakeMenu()
|
|
fake_iface = MagicMock()
|
|
with patch.object(qui, "iface", fake_iface):
|
|
qui.add_menu(menu)
|
|
|
|
fake_iface.mainWindow.return_value.menuBar.return_value.addMenu.assert_called_once_with(menu)
|
|
|
|
def test_add_menu_ohne_menuaction_wird_ignoriert(self):
|
|
"""Prüft, dass ein Objekt ohne menuAction nicht an die Menüleiste übergeben wird."""
|
|
fake_iface = MagicMock()
|
|
with patch.object(qui, "iface", fake_iface):
|
|
qui.add_menu(object())
|
|
|
|
fake_iface.mainWindow.return_value.menuBar.return_value.addMenu.assert_not_called()
|
|
|
|
def test_remove_menu_entfernt_ueber_menuaction(self):
|
|
"""Prüft, dass remove_menu das Menü über dessen menuAction() aus der Menüleiste entfernt."""
|
|
menu = _FakeMenu()
|
|
fake_iface = MagicMock()
|
|
with patch.object(qui, "iface", fake_iface):
|
|
qui.remove_menu(menu)
|
|
|
|
fake_iface.mainWindow.return_value.menuBar.return_value.removeAction.assert_called_once_with("MENU_ACTION")
|
|
|
|
def test_remove_menu_ohne_main_window_tut_nichts(self):
|
|
"""Prüft, dass remove_menu ohne Hauptfenster keine Ausnahme wirft."""
|
|
fake_iface = MagicMock()
|
|
fake_iface.mainWindow.return_value = None
|
|
with patch.object(qui, "iface", fake_iface):
|
|
qui.remove_menu(_FakeMenu()) # darf keine Ausnahme werfen
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|