diff --git a/tests/test_utils_pv.py b/tests/test_utils_pv.py index e69af75e4..1ba84e39d 100644 --- a/tests/test_utils_pv.py +++ b/tests/test_utils_pv.py @@ -5,29 +5,32 @@ from slic.utils.pv import PV from epics import PV as EpicsPV -@pytest.fixture -def capture_stdout(monkeypatch): - buf = StringIO() - monkeypatch.setattr("sys.stdout", buf) - return buf - -# Fake PV class FakeEPICS(EpicsPV): def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) self._value = 0.0 self.units = "units" + self._callbacks = {} def get(self, *args, **kwargs): - print(f"[DEBUG] FakeEPICS.get() returning {self._value}") return self._value def put(self, value, *args, **kwargs): + old_value = self._value self._value = value + for cb in self._callbacks.values(): + cb(value=value) return value -# Fixture that monkeypatch epics.PV → FakeEPICS + def add_callback(self, callback): + cb_index = len(self._callbacks) + 1 + self._callbacks[cb_index] = callback + return cb_index + + def remove_callback(self, cb_index): + self._callbacks.pop(cb_index, None) + + @pytest.fixture def fake_epics_pv(monkeypatch): monkeypatch.setattr("epics.PV", FakeEPICS) @@ -42,18 +45,19 @@ def capture_stdout(monkeypatch): @pytest.mark.parametrize("value, expected_bar, expected_color, expected_repr", [ - (25.0, "██▌ ", colorama.Fore.GREEN, 'PV "TEST:PV" at 25.0 units'), - (50.0, "█████ ", colorama.Fore.GREEN, 'PV "TEST:PV" at 50.0 units'), - (75.0, "███████▌ ", colorama.Fore.GREEN, 'PV "TEST:PV" at 75.0 units'), + (25.0, "██▌ ", colorama.Fore.GREEN, 'PV "TEST:PV" at 25.0 units'), + (50.0, "█████ ", colorama.Fore.GREEN, 'PV "TEST:PV" at 50.0 units'), + (75.0, "███████▌ ", colorama.Fore.GREEN, 'PV "TEST:PV" at 75.0 units'), (100.0, "██████████", colorama.Fore.GREEN, 'PV "TEST:PV" at 100.0 units'), - (150.0, ">>>>>>>>>>", colorama.Fore.RED, 'PV "TEST:PV" at 150.0 units'), - (-50.0, "<<<<<<<<<<", colorama.Fore.RED, 'PV "TEST:PV" at -50.0 units') + (150.0, ">>>>>>>>>>", colorama.Fore.RED, 'PV "TEST:PV" at 150.0 units'), + (-50.0, "<<<<<<<<<<", colorama.Fore.RED, 'PV "TEST:PV" at -50.0 units') ]) - def test_progress_and_repr(fake_epics_pv, capture_stdout, value, expected_bar, expected_color, expected_repr): - pv = fake_epics_pv + # Verify initial value + assert pv.get() == 0.0 + # Test put() and progress bar pv.put(value, show_progress=True) output = capture_stdout.getvalue() @@ -66,29 +70,33 @@ def test_progress_and_repr(fake_epics_pv, capture_stdout, value, expected_bar, e # Verify value update assert pv.get() == pytest.approx(value) - # Test origin_repr - assert f"PV TEST:PV at {value} units" == pv.orig_repr() + # Test repr + assert repr(pv) == expected_repr + + # Test original repr + assert pv.orig_repr() == f"PV TEST:PV at {value} units" capture_stdout.truncate(0) + def test_use_callback_context_manager(fake_epics_pv): - # Test the use_callback context manager functionality pv = fake_epics_pv callback_log = [] + def test_callback(value, **kwargs): callback_log.append(value) - # Verify callback is added and removed properly - assert len(pv._pv._callbacks) == 0 # No callbacks initially + # Verify no callbacks initially + assert len(pv._pv._callbacks) == 0 - with pv.use_callback(test_callback) as callback_id: - # Callback should be added when entering context - assert len(pv._pv._callbacks) == 1 - assert callback_id in pv._pv._callbacks - - # Trigger callback - pv.put(10.0) - assert callback_log == [10.0] + with pv.use_callback(test_callback) as callback_id: + # Callback should be added + assert len(pv._pv._callbacks) == 1 + assert callback_id in pv._pv._callbacks + + # Trigger callback + pv.put(10.0) + assert callback_log == [10.0] - # Callback should be removed after context - assert len(pv._pv._callbacks) == 0 \ No newline at end of file + # Callback should be removed + assert len(pv._pv._callbacks) == 0 \ No newline at end of file