fix: isolate tests from production database
Tests that imported wled_controller.main at module level caused the real production database (data/ledgrab.db) to be opened before test fixtures could patch the config. This led to silent data loss. Patch the global config singleton at conftest module level (before any test imports main.py) to redirect all DB access to a temp directory.
This commit is contained in:
+57
-11
@@ -1,20 +1,52 @@
|
||||
"""Pytest configuration and shared fixtures."""
|
||||
"""Pytest configuration and shared fixtures.
|
||||
|
||||
IMPORTANT: This conftest patches the global config singleton BEFORE any test
|
||||
module can import ``wled_controller.main``. ``main.py`` reads ``get_config()``
|
||||
at module level to open the database — if the singleton is not patched first,
|
||||
the REAL production database (``data/ledgrab.db``) is opened and tests
|
||||
read/write/delete production data.
|
||||
"""
|
||||
|
||||
import tempfile
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from wled_controller.config import Config, StorageConfig, ServerConfig, AuthConfig
|
||||
from wled_controller.storage.database import Database
|
||||
from wled_controller.storage.device_store import Device, DeviceStore
|
||||
from wled_controller.storage.sync_clock import SyncClock
|
||||
from wled_controller.storage.sync_clock_store import SyncClockStore
|
||||
from wled_controller.storage.output_target_store import OutputTargetStore
|
||||
from wled_controller.storage.automation import (
|
||||
Automation,
|
||||
# ---------------------------------------------------------------------------
|
||||
# ISOLATE ALL TESTS FROM PRODUCTION DATA — must happen before any test module
|
||||
# imports ``wled_controller.main``.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
import wled_controller.config as _config_mod # noqa: E402
|
||||
|
||||
_test_tmp = Path(tempfile.mkdtemp(prefix="wled_test_"))
|
||||
_test_db_path = str(_test_tmp / "test_ledgrab.db")
|
||||
_test_assets_dir = str(_test_tmp / "test_assets")
|
||||
|
||||
_original_config = _config_mod.Config.load()
|
||||
_test_config = _original_config.model_copy(
|
||||
update={
|
||||
"storage": _config_mod.StorageConfig(database_file=_test_db_path),
|
||||
"assets": _config_mod.AssetsConfig(
|
||||
assets_dir=_test_assets_dir,
|
||||
max_file_size_mb=_original_config.assets.max_file_size_mb,
|
||||
),
|
||||
},
|
||||
)
|
||||
from wled_controller.storage.automation_store import AutomationStore
|
||||
from wled_controller.storage.value_source_store import ValueSourceStore
|
||||
_config_mod.config = _test_config
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
from wled_controller.config import Config, StorageConfig, ServerConfig, AuthConfig # noqa: E402
|
||||
from wled_controller.storage.database import Database # noqa: E402
|
||||
from wled_controller.storage.device_store import Device, DeviceStore # noqa: E402
|
||||
from wled_controller.storage.sync_clock import SyncClock # noqa: E402
|
||||
from wled_controller.storage.sync_clock_store import SyncClockStore # noqa: E402
|
||||
from wled_controller.storage.output_target_store import OutputTargetStore # noqa: E402
|
||||
from wled_controller.storage.automation import Automation # noqa: E402
|
||||
from wled_controller.storage.automation_store import AutomationStore # noqa: E402
|
||||
from wled_controller.storage.value_source_store import ValueSourceStore # noqa: E402
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -242,3 +274,17 @@ def sample_calibration():
|
||||
{"edge": "left", "led_start": 110, "led_count": 40, "reverse": True},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Session cleanup — remove temporary test directory
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
@pytest.fixture(scope="session", autouse=True)
|
||||
def _cleanup_test_tmp():
|
||||
"""Remove the temporary test directory after all tests complete."""
|
||||
import shutil
|
||||
|
||||
yield
|
||||
shutil.rmtree(_test_tmp, ignore_errors=True)
|
||||
|
||||
Reference in New Issue
Block a user