# sn_basis/test/test_sys_wrapper.py """sn_basis/tests/test_sys_wrapper.py Unit-Tests für sn_basis.functions.sys_wrapper.get_plugin_root(). """ import os import unittest from pathlib import Path from tempfile import TemporaryDirectory from unittest.mock import patch from sn_basis.functions import sys_wrapper def _verknuepfung_anlegen(ziel: Path, quelle: Path) -> None: """Legt eine Verzeichnisverknüpfung an (Symlink, unter Windows notfalls Junction). Entspricht exakt der Logik in scripts/link_qgis_profile.py, mit der Klone ins QGIS-Profil verknüpft werden (dort ohne Admin-Rechte per Junction). """ try: os.symlink(quelle, ziel, target_is_directory=True) except (OSError, NotImplementedError): if os.name == "nt": import _winapi _winapi.CreateJunction(str(quelle), str(ziel)) else: raise class TestGetPluginRoot(unittest.TestCase): def test_get_plugin_root_folgt_keiner_verzeichnisverknuepfung(self): """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).""" with TemporaryDirectory() as tmp: tmp_path = Path(tmp) echtes_ziel = tmp_path / "echt" / "sn_basis" / "functions" echtes_ziel.mkdir(parents=True) verlinkter_ordner = tmp_path / "verlinkt" verlinkter_ordner.mkdir() verlinkte_sn_basis = verlinkter_ordner / "sn_basis" _verknuepfung_anlegen(verlinkte_sn_basis, echtes_ziel.parent) fake_file = verlinkte_sn_basis / "functions" / "sys_wrapper.py" with patch.object(sys_wrapper, "__file__", str(fake_file)): ergebnis = sys_wrapper.get_plugin_root() self.assertEqual(ergebnis, verlinkter_ordner) class JoinPathTests(unittest.TestCase): def test_verbindet_mehrere_pfadbestandteile(self): """Prüft, dass join_path mehrere Bestandteile OS-sicher zu einem Path zusammenfügt.""" ergebnis = sys_wrapper.join_path("a", "b", "c.txt") self.assertEqual(ergebnis, Path("a") / "b" / "c.txt") class EnsureDirTests(unittest.TestCase): def test_legt_fehlendes_verzeichnis_inklusive_eltern_an(self): """Prüft, dass ensure_dir ein fehlendes Verzeichnis samt Elternverzeichnissen anlegt.""" with TemporaryDirectory() as tmp: ziel = Path(tmp) / "a" / "b" / "c" ergebnis = sys_wrapper.ensure_dir(ziel) self.assertTrue(ziel.is_dir()) self.assertEqual(ergebnis, ziel) def test_vorhandenes_verzeichnis_wirft_keinen_fehler(self): """Prüft, dass ensure_dir bei einem bereits vorhandenen Verzeichnis keinen Fehler wirft.""" with TemporaryDirectory() as tmp: sys_wrapper.ensure_dir(Path(tmp)) # darf nicht scheitern class GetattrSafeTests(unittest.TestCase): def test_liefert_vorhandenes_attribut(self): """Prüft, dass getattr_safe ein vorhandenes Attribut liefert.""" class _Beispiel: wert = 42 self.assertEqual(sys_wrapper.getattr_safe(_Beispiel(), "wert"), 42) def test_liefert_default_bei_fehlendem_attribut(self): """Prüft, dass getattr_safe bei fehlendem Attribut den Default-Wert liefert.""" class _Beispiel: pass self.assertEqual(sys_wrapper.getattr_safe(_Beispiel(), "fehlt", "ersatz"), "ersatz") self.assertIsNone(sys_wrapper.getattr_safe(_Beispiel(), "fehlt")) if __name__ == "__main__": unittest.main()