22
33from __future__ import annotations
44
5- import os
6- import sys
75from pathlib import Path
86from typing import Any
97
108import pytest
119
12- from redsun .containers import AppContainer , AppConfig , StorageConfig , device , presenter , view
10+ from redsun .containers import (
11+ AppConfig ,
12+ AppContainer ,
13+ StorageConfig ,
14+ device ,
15+ presenter ,
16+ view ,
17+ )
1318from redsun .containers .components import (
1419 _DeviceComponent ,
1520 _PresenterComponent ,
@@ -61,10 +66,7 @@ def test_presenter_component_build(self) -> None:
6166 assert presenter is comp .instance
6267 assert "built" in repr (comp )
6368
64- @pytest .mark .skipif (
65- sys .platform == "linux" and not os .environ .get ("DISPLAY" ),
66- reason = "requires a display (Qt)" ,
67- )
69+ @pytest .mark .qt
6870 def test_view_component_build (self ) -> None :
6971 from mock_pkg .view import MockQtView
7072 from qtpy .QtWidgets import QApplication
@@ -277,10 +279,7 @@ class TestApp(AppContainer):
277279 assert "ctrl" in TestApp ._presenter_components
278280 assert isinstance (TestApp ._presenter_components ["ctrl" ], _PresenterComponent )
279281
280- @pytest .mark .skipif (
281- sys .platform == "linux" and not os .environ .get ("DISPLAY" ),
282- reason = "Fails on Linux CI without a display (Qt required for view components)" ,
283- )
282+ @pytest .mark .qt
284283 def test_component_field_collects_view (self ) -> None :
285284 from mock_pkg .view import MockQtView
286285 from qtpy .QtWidgets import QApplication
@@ -442,7 +441,6 @@ class TestAppConfig:
442441
443442 def test_app_config_has_schema_version (self ) -> None :
444443 from redsun .containers import AppConfig
445- from redsun .virtual import RedSunConfig
446444
447445 cfg : AppConfig = {
448446 "schema_version" : 1.0 ,
@@ -457,7 +455,6 @@ def test_app_config_has_schema_version(self) -> None:
457455 assert "session" in AppConfig .__optional_keys__
458456
459457 def test_app_config_has_component_fields (self ) -> None :
460- from redsun .containers import AppConfig
461458
462459 cfg : AppConfig = {
463460 "schema_version" : 1.0 ,
@@ -478,14 +475,15 @@ def test_redsun_config_no_component_fields(self) -> None:
478475 assert "views" not in RedSunConfig .__annotations__
479476
480477
478+ @pytest .mark .qt
481479class TestQtAppContainer :
482480 """Tests for QtAppContainer lifecycle correctness."""
483481
484482 def test_build_before_run_creates_qapplication (self ) -> None :
485- from mock_pkg .view import MockQtView
486483 from mock_pkg .device import MyMotor
487-
484+ from mock_pkg . view import MockQtView
488485 from qtpy .QtWidgets import QApplication
486+
489487 from redsun .qt import QtAppContainer
490488
491489 class _TestQtApp (QtAppContainer ):
@@ -508,6 +506,7 @@ class _TestQtApp(QtAppContainer):
508506
509507 def test_run_reuses_qapplication_created_by_build (self ) -> None :
510508 from qtpy .QtWidgets import QApplication
509+
511510 from redsun .qt import QtAppContainer
512511
513512 class _TestQtApp (QtAppContainer ):
@@ -528,7 +527,7 @@ class TestComponentNaming:
528527 """
529528
530529 def test_device_alias_overrides_attr_name (self ) -> None :
531- """alias takes priority over the attribute name as device name."""
530+ """Alias takes priority over the attribute name as device name."""
532531 from mock_pkg .device import MyMotor
533532
534533 class TestApp (AppContainer ):
@@ -561,7 +560,7 @@ class TestApp(AppContainer):
561560 assert app .devices ["motor" ].name == "motor"
562561
563562 def test_presenter_alias_overrides_attr_name (self ) -> None :
564- """alias takes priority over the attribute name for presenters."""
563+ """Alias takes priority over the attribute name for presenters."""
565564 from mock_pkg .controller import MockController
566565 from mock_pkg .device import MyMotor
567566
@@ -603,6 +602,7 @@ class TestStorageInjection:
603602 def mock_writer (self ):
604603 """Patch _build_writer to return a MagicMock, avoiding acquire-zarr dependency."""
605604 from unittest .mock import MagicMock , patch
605+
606606 from redsun .storage import Writer
607607
608608 writer = MagicMock (spec = Writer )
@@ -667,7 +667,7 @@ class TestApp(AppContainer):
667667 assert not hasattr (motor , "storage" )
668668
669669 def test_storage_none_when_no_config (self ) -> None :
670- """Without a storage section, device.storage remains None ."""
670+ """Without a storage section, device.storage is not injected ."""
671671 from mock_pkg .device import MockDetectorWithStorage
672672
673673 class TestApp (AppContainer ):
@@ -686,7 +686,7 @@ class TestApp(AppContainer):
686686 app .build ()
687687
688688 cam = app .devices ["cam" ]
689- assert cam . storage is None # type: ignore[union-attr]
689+ assert not hasattr ( cam , "storage" )
690690
691691 def test_storage_injected_via_inheritance (
692692 self , tmp_path : Path , mock_writer : Any
@@ -696,6 +696,7 @@ def test_storage_injected_via_inheritance(
696696
697697 class ExtendedDetector (MockDetectorWithStorage ):
698698 """Subclass that inherits StorageDescriptor from MockDetectorWithStorage."""
699+
699700 pass
700701
701702 class TestApp (AppContainer ):
@@ -766,10 +767,12 @@ class TestApp(AppContainer, config=str(cfg_file)):
766767
767768 def test_default_base_path_uses_session_name (self ) -> None :
768769 """When base_path is omitted, _build_writer is called with the session name."""
769- from unittest .mock import MagicMock , patch , call
770- from redsun . storage import Writer
770+ from unittest .mock import MagicMock , patch
771+
771772 from mock_pkg .device import MockDetectorWithStorage
772773
774+ from redsun .storage import Writer
775+
773776 writer = MagicMock (spec = Writer )
774777
775778 class TestApp (AppContainer ):
@@ -798,8 +801,9 @@ class TestApp(AppContainer):
798801
799802 def test_build_writer_creates_session_directory (self , tmp_path : Path ) -> None :
800803 """_build_writer creates ~/redsun-storage/<session> when base_path is omitted."""
801- from unittest .mock import patch
802804 from pathlib import Path as _Path
805+ from unittest .mock import patch
806+
803807 from redsun .containers .container import _build_writer
804808
805809 storage_cfg = StorageConfig (backend = "zarr" )
0 commit comments