From 40a673c5624d139502a8756ba662e8c2a2699573 Mon Sep 17 00:00:00 2001 From: smillmorel Date: Wed, 16 Sep 2026 19:15:48 -0400 Subject: [PATCH] test: isolate QSettings so user preferences cannot fail GUI tests MainWindow persists preferences (window layout, canvas backend) through QSettings("OTKO", "OTKO"), so tests constructing it were reading the developer's real settings: after switching to the Plotly backend the PyVista-specific viewport-axis tests failed with "PlotlyCanvas has no attribute renderer". A session fixture now redirects QSettings into a temp dir and is skipped when Qt is not installed, keeping the headless job Qt-free. --- tests/conftest.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/conftest.py b/tests/conftest.py index 82dd86a..c91c064 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -11,6 +11,7 @@ domain after every test. The import is inside the teardown so that from __future__ import annotations +import importlib.util import os from collections.abc import Iterator @@ -19,6 +20,27 @@ import pytest os.environ.setdefault("QT_QPA_PLATFORM", "offscreen") +@pytest.fixture(autouse=True, scope="session") +def _isolate_qsettings(tmp_path_factory: pytest.TempPathFactory) -> Iterator[None]: + """Redirect ``QSettings`` to a temp dir so tests never touch user state. + + ``MainWindow`` persists preferences (window layout, canvas backend) under + ``QSettings("OTKO", "OTKO")``. Without redirection a developer who, say, + switched to the Plotly backend would see PyVista-specific GUI tests fail + against their real settings. Skipped entirely when Qt is not installed, so + the headless job stays free of Qt. + """ + if importlib.util.find_spec("PySide6") is None: + yield + return + from PySide6.QtCore import QSettings + + settings_dir = tmp_path_factory.mktemp("qsettings") + for fmt in (QSettings.Format.NativeFormat, QSettings.Format.IniFormat): + QSettings.setPath(fmt, QSettings.Scope.UserScope, str(settings_dir)) + yield + + @pytest.fixture(autouse=True) def _wipe_opensees_domain() -> Iterator[None]: """Wipe the OpenseesPy domain after a test if the solver was imported."""