diff --git a/tests/tests_devices/test_mo1_bragg_angle.py b/tests/tests_devices/test_mo1_bragg_angle.py new file mode 100644 index 0000000..c09c055 --- /dev/null +++ b/tests/tests_devices/test_mo1_bragg_angle.py @@ -0,0 +1,88 @@ +"""Tests for the Mo1BraggAngle class.""" + +import threading +from unittest import mock + +import ophyd +import pytest +from ophyd_devices.tests.utils import MockPV, patch_dual_pvs + +from debye_bec.devices.mo1_bragg.mo1_bragg_angle import Mo1BraggAngle +from debye_bec.devices.mo1_bragg.mo1_bragg_devices import Mo1BraggStoppedError + +# pylint: disable=protected-access + + +@pytest.fixture(scope="function") +def mock_bragg() -> Mo1BraggAngle: + """Fixture for the Mo1BraggAngle device.""" + name = "bragg" + prefix = "X01DA-OP-MO1:BRAGG:" + with mock.patch.object(ophyd, "cl") as mock_cl: + mock_cl.get_pv = MockPV + mock_cl.thread_class = threading.Thread + dev = Mo1BraggAngle(name=name, prefix=prefix) + patch_dual_pvs(dev) + yield dev + + +def test_mo1_bragg_angle_init(mock_bragg): + """Test the initialization of the Mo1BraggAngle device.""" + assert mock_bragg.name == "bragg" + assert mock_bragg.prefix == "X01DA-OP-MO1:BRAGG:" + assert isinstance(mock_bragg.readback, ophyd.EpicsSignalRO) + assert isinstance(mock_bragg.setpoint, ophyd.EpicsSignalWithRBV) + assert isinstance(mock_bragg.low_lim, ophyd.EpicsSignalRO) + assert isinstance(mock_bragg.high_lim, ophyd.EpicsSignalRO) + + +def test_mo1_bragg_angle_egu(mock_bragg): + """Test the engineering unit of the Mo1BraggAngle device.""" + assert mock_bragg.egu == "deg" + + +def test_mo1_bragg_angle_limits(mock_bragg): + """Test the limits of the Mo1BraggAngle device.""" + mock_bragg.low_lim._read_pv.mock_data = -10 + mock_bragg.high_lim._read_pv.mock_data = 10 + + assert mock_bragg.limits == (-10, 10) + + +def test_mo1_bragg_angle_move(mock_bragg): + """Test the move method of the Mo1BraggAngle device.""" + mock_bragg.setpoint.put(0) + mock_bragg.readback._read_pv.mock_data = 0 # EpicsSignalRO + + # Change PV for motor is moving before starting the move + mock_bragg.motor_is_moving._read_pv.mock_data = 0 # EpicsSignalRO + status = mock_bragg.move(5) + assert status.done is False + + # Check setpoint is set correctly + assert mock_bragg.setpoint.get() == 5 + + # Update the motor is moving PV to simulate that the move is done + mock_bragg.motor_is_moving._read_pv.mock_data = 1 + assert mock_bragg.motor_is_moving.get() == 1 + + status.wait(timeout=5) # If the status does not resolve after 5 seconds, something is wrong + assert status.done is True + + +def test_mo1_bragg_angle_stop(mock_bragg): + """Test the stop method of the Mo1BraggAngle device.""" + assert mock_bragg.stopped is False + + mock_bragg.stop() + assert mock_bragg.stopped is True + + status = mock_bragg.move(5) + assert status.done is False + + # stopped should be resetted + assert mock_bragg.stopped is False + + with pytest.raises(Mo1BraggStoppedError): + mock_bragg.stop() + status.wait(timeout=5) # This should raise before due to stop() call