Coverage for tests/conftest.py: 97%
96 statements
« prev ^ index » next coverage.py v7.15.0, created at 2026-07-03 15:51 +0000
« prev ^ index » next coverage.py v7.15.0, created at 2026-07-03 15:51 +0000
1import shutil
2import tempfile
3from unittest.mock import Mock, patch
5import pytest
6import sys
7import os
8from PyQt6.QtCore import QSettings, QObject, pyqtSignal
9from PyQt6.QtWidgets import QPushButton, QWidget
12# Add the project path to PYTHONPATH
13sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
15class SignalEmitter(QObject):
16 """Helper class for mocked signals"""
17 selected_files = pyqtSignal(list)
18 language_changed = pyqtSignal(str)
20@pytest.fixture
21def signal_emitter():
22 return SignalEmitter()
24@pytest.fixture
25def temp_workspace():
26 """Create a temporary directory for the workspace"""
27 temp_dir = tempfile.mkdtemp()
28 os.makedirs(os.path.join(temp_dir, "pipeline"), exist_ok=True)
29 with open(os.path.join(temp_dir, "pipeline", "output.txt"), "w") as f:
30 f.write("output content")
31 os.makedirs(os.path.join(temp_dir, "sub-01", "pet"))
32 with open(os.path.join(temp_dir, "sub-01", "pet", "pet.nii"), "w") as f:
33 f.write("PET")
34 os.makedirs(os.path.join(temp_dir, "sub-01", "anat"))
35 with open(os.path.join(temp_dir, "sub-01", "anat", "T1w.nii"), "w") as f:
36 f.write("T1w")
37 os.makedirs(os.path.join(temp_dir, "sub-02"))
39 manual_dir = os.path.join(temp_dir, "derivatives", "manual_masks", "sub-01", "anat")
40 os.makedirs(manual_dir)
41 with open(os.path.join(manual_dir, "mask.nii.gz"), "w") as f:
42 f.write("test_mask")
44 with open(os.path.join(temp_dir, "test.txt"), "w") as f:
45 f.write("test content")
46 with open(os.path.join(temp_dir, "brain.nii"), "w") as f:
47 f.write("nifti data")
48 with open(os.path.join(temp_dir, "brain.json"), "w") as f:
49 f.write("{}")
50 # NIfTI.gz file with JSON
51 with open(os.path.join(temp_dir, "scan.nii.gz"), "w") as f:
52 f.write("compressed")
53 with open(os.path.join(temp_dir, "scan.json"), "w") as f:
54 f.write("{}")
56 yield temp_dir
57 shutil.rmtree(temp_dir, ignore_errors=True)
59@pytest.fixture
60def mock_context(temp_workspace, signal_emitter):
61 """Create a mock context with all necessary components"""
62 def create_buttons():
63 # Return real QPushButtons instead of Mock
64 return QPushButton("Next"), QPushButton("Back")
66 context = {
67 "language_changed": signal_emitter.language_changed,
68 "selected_files_signal": signal_emitter.selected_files,
69 "settings": QSettings("TestOrg", "TestApp"),
70 "workspace_path": temp_workspace,
71 "create_buttons": create_buttons,
72 "import_page": Mock(spec=['open_folder_dialog']),
73 "update_main_buttons": Mock(),
74 "return_to_import": Mock(),
75 "main_window": Mock(),
76 "history": [],
77 "open_nifti_viewer": Mock(),
78 "tree_view": Mock()
79 }
80 return context
82@pytest.fixture(autouse=True)
83def clean_settings():
84 """Clean settings before and after each test"""
85 settings = QSettings("TestOrg", "TestApp")
86 settings.clear()
87 yield
88 settings.clear()
90@pytest.fixture
91def mock_logger():
92 """Mock for the logger"""
93 from unittest.mock import Mock
94 logger = Mock()
95 logger.info = Mock()
96 logger.error = Mock()
97 logger.debug = Mock()
98 logger.warning = Mock()
99 return logger
101class DummySignal:
102 def connect(self, slot):
103 pass
105class DummyFileSelectorWidget(QWidget):
106 """Mock of FileSelectorWidget used in tests."""
107 def __init__(self, *args, **kwargs):
108 super().__init__()
109 self.has_file = DummySignal()
110 self._selected_files = []
111 # Mock for verification in tests
112 self.clear_selected_files = Mock()
114 def get_selected_files(self):
115 return self._selected_files
117 def reset(self):
118 self._selected_files.clear()
120 def setEnabled(self, value: bool):
121 pass
123@pytest.fixture
124def mock_file_selector():
125 """Patch FileSelectorWidget with a compatible mock."""
126 with patch(
127 "main.ui.skull_stripping_page.FileSelectorWidget",
128 return_value=DummyFileSelectorWidget()
129 ) as mock:
130 yield mock
132@pytest.fixture
133def mock_file_selector_mask():
134 """Patch FileSelectorWidget in ui_mask_selection_page module with a valid widget."""
135 with patch(
136 "main.ui.nifti_mask_selection_page.FileSelectorWidget",
137 return_value=DummyFileSelectorWidget()
138 ) as mock:
139 yield mock
141@pytest.fixture
142def mock_file_selector_dl():
143 """Patch FileSelectorWidget in the ui_dl_selection_page module."""
144 with patch(
145 "main.ui.dl_selection_page.FileSelectorWidget",
146 return_value=DummyFileSelectorWidget()
147 ) as mock:
148 yield mock
150# Pytest configuration
151def pytest_configure(config):
152 """Global pytest configuration"""
153 config.addinivalue_line(
154 "markers", "slow: marks tests as slow (deselect with '-m \"not slow\"')"
155 )
156 config.addinivalue_line(
157 "markers", "integration: marks tests as integration tests"
158 )
159 config.addinivalue_line(
160 "markers", "unit: marks tests as unit tests"
161 )