2026-09-16 12:03:22 -04:00
|
|
|
"""Shared pytest configuration.
|
2026-09-08 02:12:15 -04:00
|
|
|
|
2026-09-16 12:03:22 -04:00
|
|
|
The GUI suite is headless by default: unless the caller already chose a
|
|
|
|
|
platform, ``QT_QPA_PLATFORM=offscreen`` is set here, before pytest-qt
|
|
|
|
|
builds its session ``QApplication``. An explicit caller value is respected.
|
|
|
|
|
|
|
|
|
|
OpenseesPy is a process-global singleton, so a lazy autouse guard wipes the
|
|
|
|
|
domain after every test. The import is inside the teardown so that
|
|
|
|
|
``tests/unit`` never imports the solver.
|
2026-09-08 02:12:15 -04:00
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
2026-09-16 19:15:48 -04:00
|
|
|
import importlib.util
|
2026-09-16 12:03:22 -04:00
|
|
|
import os
|
|
|
|
|
from collections.abc import Iterator
|
|
|
|
|
|
2026-09-08 02:12:15 -04:00
|
|
|
import pytest
|
|
|
|
|
|
2026-09-16 12:03:22 -04:00
|
|
|
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
|
|
|
|
|
|
2026-09-08 02:12:15 -04:00
|
|
|
|
2026-09-16 19:15:48 -04:00
|
|
|
@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
|
|
|
|
|
|
|
|
|
|
|
2026-09-08 02:12:15 -04:00
|
|
|
@pytest.fixture(autouse=True)
|
2026-09-16 12:03:22 -04:00
|
|
|
def _wipe_opensees_domain() -> Iterator[None]:
|
|
|
|
|
"""Wipe the OpenseesPy domain after a test if the solver was imported."""
|
|
|
|
|
yield
|
2026-09-08 02:12:15 -04:00
|
|
|
try:
|
2026-09-16 12:03:22 -04:00
|
|
|
from openseespy.opensees import wipe
|
|
|
|
|
except Exception: # pragma: no cover - solver not installed / import side effects
|
2026-09-08 02:12:15 -04:00
|
|
|
return
|
2026-09-16 12:03:22 -04:00
|
|
|
wipe()
|