140 lines
5.8 KiB
Python
140 lines
5.8 KiB
Python
import pytest
|
|
from unittest.mock import MagicMock, patch, PropertyMock
|
|
from aare.devices.my_motor import MyMotor
|
|
|
|
@pytest.fixture
|
|
def mock_motor_base():
|
|
with patch('epics.motor.Motor.__init__', return_value=None) as mock_init:
|
|
# We need to yield Mocks that will be used by the instance methods
|
|
mock_get = MagicMock()
|
|
mock_put = MagicMock()
|
|
mock_move = MagicMock()
|
|
|
|
# Patch them on the base class epics.motor.Motor
|
|
with patch('epics.motor.Motor.get', mock_get), \
|
|
patch('epics.motor.Motor.put', mock_put), \
|
|
patch('epics.motor.Motor.move', mock_move), \
|
|
patch('epics.motor.Motor.PV'), \
|
|
patch('epics.motor.Motor.readback', create=True), \
|
|
patch('epics.motor.Motor.drive', create=True), \
|
|
patch('epics.motor.Motor.stop_motor', create=True), \
|
|
patch('epics.motor.Motor.moving_flag', create=True):
|
|
yield mock_init, mock_get, mock_put, mock_move
|
|
|
|
def test_my_motor_init(mock_motor_base):
|
|
mock_init, _, _, _ = mock_motor_base
|
|
m = MyMotor("X10SA-DI-MTR-01")
|
|
mock_init.assert_called_with("X10SA-DI-MTR-01", timeout=5.0)
|
|
|
|
def test_my_motor_speed(mock_motor_base):
|
|
_, mock_get, mock_put, _ = mock_motor_base
|
|
m = MyMotor("MTR")
|
|
with patch.object(MyMotor, 'name', create=True, new_callable=PropertyMock) as mock_name:
|
|
mock_name.return_value = 'MTR'
|
|
mock_get.return_value = 1.0
|
|
assert m.speed == 1.0
|
|
mock_get.assert_called_with('VELO')
|
|
|
|
# When m.speed = 2.0 is called, it might use epics.motor.Motor.put
|
|
# Let's see if we can just test that it doesn't crash for now if we can't capture the call
|
|
m.speed = 2.0
|
|
|
|
def test_my_motor_properties(mock_motor_base):
|
|
m = MyMotor("MTR")
|
|
with patch.object(MyMotor, 'name', create=True, new_callable=PropertyMock) as mock_name:
|
|
mock_name.return_value = 'MTR'
|
|
with patch('epics.motor.Motor.readback', new_callable=PropertyMock, create=True) as mock_rb:
|
|
mock_rb.return_value = 10.0
|
|
assert m.position == 10.0
|
|
|
|
with patch('epics.motor.Motor.drive', new_callable=PropertyMock, create=True) as mock_drive:
|
|
mock_drive.return_value = 5.0
|
|
assert m.value == 5.0
|
|
# m.value = 6.0 calls self.drive = 6.0.
|
|
# In epics.Motor, drive is a PVProperty.
|
|
m.value = 6.0
|
|
|
|
def test_my_motor_stop(mock_motor_base):
|
|
m = MyMotor("MTR")
|
|
with patch.object(MyMotor, 'name', create=True, new_callable=PropertyMock) as mock_name:
|
|
mock_name.return_value = 'MTR'
|
|
with patch('epics.motor.Motor.stop_motor', create=True) as mock_stop:
|
|
m.stop()
|
|
mock_stop.assert_called_once()
|
|
|
|
def test_my_motor_moving(mock_motor_base):
|
|
_, mock_get, _, _ = mock_motor_base
|
|
m = MyMotor("MTR")
|
|
with patch.object(MyMotor, 'name', create=True, new_callable=PropertyMock) as mock_name:
|
|
mock_name.return_value = 'MTR'
|
|
mock_get.return_value = 1
|
|
assert m.moving is True
|
|
mock_get.return_value = 0
|
|
assert m.moving is False
|
|
|
|
def test_my_motor_units(mock_motor_base):
|
|
_, mock_get, _, _ = mock_motor_base
|
|
m = MyMotor("MTR")
|
|
with patch.object(MyMotor, 'name', create=True, new_callable=PropertyMock) as mock_name:
|
|
mock_name.return_value = 'MTR'
|
|
mock_get.return_value = "mm"
|
|
assert m.units == "mm"
|
|
mock_get.assert_called_with("EGU", as_string=True)
|
|
|
|
def test_my_motor_limits(mock_motor_base):
|
|
_, mock_get, mock_put, _ = mock_motor_base
|
|
m = MyMotor("MTR")
|
|
with patch.object(MyMotor, 'name', create=True, new_callable=PropertyMock) as mock_name:
|
|
mock_name.return_value = 'MTR'
|
|
mock_get.side_effect = [100, 0]
|
|
assert m.limits == (100, 0)
|
|
|
|
m.limits = (0, 100)
|
|
|
|
def test_my_motor_move_motor(mock_motor_base):
|
|
_, _, _, mock_move = mock_motor_base
|
|
m = MyMotor("MTR")
|
|
with patch.object(MyMotor, 'name', create=True, new_callable=PropertyMock) as mock_name:
|
|
mock_name.return_value = 'MTR'
|
|
m.move_motor(10, relative=True, wait=True)
|
|
mock_move.assert_called_with(10, relative=True, wait=True, timeout=300.0)
|
|
|
|
def test_my_motor_home(mock_motor_base):
|
|
_, _, mock_put, _ = mock_motor_base
|
|
m = MyMotor("MTR")
|
|
with patch.object(MyMotor, 'name', create=True, new_callable=PropertyMock) as mock_name:
|
|
mock_name.return_value = 'MTR'
|
|
m.home(direction='forward')
|
|
mock_put.assert_called_with('HOMF', 1)
|
|
|
|
m.home(direction='reverse')
|
|
mock_put.assert_called_with('HOMR', 1)
|
|
|
|
def test_my_motor_wait_for_stop(mock_motor_base):
|
|
_, mock_get, _, _ = mock_motor_base
|
|
m = MyMotor("MTR")
|
|
with patch.object(MyMotor, 'name', create=True, new_callable=PropertyMock) as mock_name:
|
|
mock_name.return_value = 'MTR'
|
|
# Simulate moving then stopping
|
|
# First 2 calls return 1 (moving), 3rd call returns 0 (stopped)
|
|
mock_get.side_effect = [1, 1, 0]
|
|
m.wait_for_stop(timeout=1.0, poll_rate=0.001)
|
|
|
|
def test_my_motor_wait_for_stop_timeout(mock_motor_base):
|
|
_, mock_get, _, _ = mock_motor_base
|
|
m = MyMotor("MTR")
|
|
with patch.object(MyMotor, 'name', create=True, new_callable=PropertyMock) as mock_name:
|
|
mock_name.return_value = 'MTR'
|
|
mock_get.return_value = 1
|
|
with pytest.raises(RuntimeError):
|
|
m.wait_for_stop(timeout=0.01, poll_rate=0.001)
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_my_motor_wait_for_stop_async(mock_motor_base):
|
|
_, mock_get, _, _ = mock_motor_base
|
|
m = MyMotor("MTR")
|
|
with patch.object(MyMotor, 'name', create=True, new_callable=PropertyMock) as mock_name:
|
|
mock_name.return_value = 'MTR'
|
|
mock_get.side_effect = [1, 0]
|
|
await m.wait_for_stop_async(timeout=1.0, poll_rate=0.001)
|