forked from AG_QGIS/Plugin_SN_Basis
155 lines
3.9 KiB
Python
155 lines
3.9 KiB
Python
"""
|
|
sn_basis/test/run_tests.py
|
|
|
|
Zentraler Test-Runner für sn_basis.
|
|
Wrapper-konform, QGIS-unabhängig, CI- und IDE-fähig.
|
|
"""
|
|
|
|
import unittest
|
|
import datetime
|
|
import inspect
|
|
import os
|
|
import sys
|
|
|
|
from pathlib import Path
|
|
|
|
# ---------------------------------------------------------
|
|
# Pre-Bootstrap: Plugin-Root in sys.path eintragen
|
|
# ---------------------------------------------------------
|
|
|
|
THIS_FILE = Path(__file__).resolve()
|
|
PLUGIN_ROOT = THIS_FILE.parents[2]
|
|
|
|
if str(PLUGIN_ROOT) not in sys.path:
|
|
sys.path.insert(0, str(PLUGIN_ROOT))
|
|
|
|
from sn_basis.functions import (
|
|
get_plugin_root,
|
|
add_to_sys_path,
|
|
)
|
|
|
|
# ---------------------------------------------------------
|
|
# Bootstrap: Plugin-Root in sys.path eintragen
|
|
# ---------------------------------------------------------
|
|
|
|
def bootstrap():
|
|
"""
|
|
Simuliert das QGIS-Plugin-Startverhalten:
|
|
stellt sicher, dass sn_basis importierbar ist.
|
|
"""
|
|
plugin_root = get_plugin_root()
|
|
add_to_sys_path(plugin_root)
|
|
|
|
|
|
bootstrap()
|
|
|
|
# ---------------------------------------------------------
|
|
# Farben
|
|
# ---------------------------------------------------------
|
|
|
|
RED = "\033[91m"
|
|
YELLOW = "\033[93m"
|
|
GREEN = "\033[92m"
|
|
CYAN = "\033[96m"
|
|
MAGENTA = "\033[95m"
|
|
RESET = "\033[0m"
|
|
|
|
GLOBAL_TEST_COUNTER = 0
|
|
|
|
# ---------------------------------------------------------
|
|
# Farbige TestResult-Klasse
|
|
# ---------------------------------------------------------
|
|
|
|
class ColoredTestResult(unittest.TextTestResult):
|
|
|
|
_last_test_class: type | None = None
|
|
|
|
|
|
def startTest(self, test):
|
|
global GLOBAL_TEST_COUNTER
|
|
GLOBAL_TEST_COUNTER += 1
|
|
self.stream.write(f"{CYAN}[Test {GLOBAL_TEST_COUNTER}]{RESET}\n")
|
|
super().startTest(test)
|
|
|
|
def startTestClass(self, test):
|
|
cls = test.__class__
|
|
file = inspect.getfile(cls)
|
|
filename = os.path.basename(file)
|
|
|
|
self.stream.write(
|
|
f"\n{MAGENTA}{'=' * 70}\n"
|
|
f"Starte Testklasse: {filename} → {cls.__name__}\n"
|
|
f"{'=' * 70}{RESET}\n"
|
|
)
|
|
|
|
def addError(self, test, err):
|
|
super().addError(test, err)
|
|
self.stream.write(f"{RED}ERROR{RESET}\n")
|
|
|
|
def addFailure(self, test, err):
|
|
super().addFailure(test, err)
|
|
self.stream.write(f"{RED}FAILURE{RESET}\n")
|
|
|
|
def addSkip(self, test, reason):
|
|
super().addSkip(test, reason)
|
|
self.stream.write(f"{YELLOW}SKIPPED{RESET}: {reason}\n")
|
|
|
|
def addSuccess(self, test):
|
|
super().addSuccess(test)
|
|
self.stream.write(f"{GREEN}OK{RESET}\n")
|
|
|
|
# ---------------------------------------------------------
|
|
# Farbiger TestRunner
|
|
# ---------------------------------------------------------
|
|
|
|
class ColoredTestRunner(unittest.TextTestRunner):
|
|
|
|
def _makeResult(self):
|
|
result = ColoredTestResult(
|
|
self.stream,
|
|
self.descriptions,
|
|
self.verbosity,
|
|
)
|
|
|
|
original_start_test = result.startTest
|
|
|
|
def patched_start_test(test):
|
|
if not hasattr(result, "_last_test_class") or \
|
|
result._last_test_class != test.__class__:
|
|
result.startTestClass(test)
|
|
result._last_test_class = test.__class__
|
|
original_start_test(test)
|
|
|
|
result.startTest = patched_start_test
|
|
return result
|
|
|
|
|
|
# ---------------------------------------------------------
|
|
# Testlauf starten
|
|
# ---------------------------------------------------------
|
|
|
|
def main():
|
|
print("\n" + "=" * 70)
|
|
print(
|
|
f"{CYAN}Testlauf gestartet am: "
|
|
f"{datetime.datetime.now():%Y-%m-%d %H:%M:%S}{RESET}"
|
|
)
|
|
print("=" * 70 + "\n")
|
|
|
|
loader = unittest.TestLoader()
|
|
|
|
suite = loader.discover(
|
|
start_dir=os.path.dirname(__file__),
|
|
pattern="test_*.py"
|
|
)
|
|
|
|
runner = ColoredTestRunner(verbosity=2)
|
|
result = runner.run(suite)
|
|
|
|
# Exit-Code für CI / Skripte
|
|
return 0 if result.wasSuccessful() else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|