Files
slic/tests/test_utils_hastyepics.py
T
tligui_y f5fa0ee15e
Run CI Tests / test (push) Successful in 53s
Update tests/test_utils_hastyepics.py
2025-08-03 20:06:24 +02:00

116 lines
3.8 KiB
Python

import time
import epics
import pytest
from epics.device import Device
from epics.motor import MotorException
import sys
import os
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from slic.utils.hastyepics import *
from unittest.mock import patch, PropertyMock
def test_motor_instantiation_fast_vs_epics():
fast_times = []
slow_times = []
# Mock to simulate a real EPICS moteur
with patch('epics.Motor.get') as mock_get:
mock_get.return_value = 'motor'
# Mean of 10 runs
for _ in range(10):
t0 = time.perf_counter()
m_fast = Motor("TEST:MOTOR_t1")
t1 = time.perf_counter()
t2 = time.perf_counter()
m_slow = epics.Motor("TEST:MOTOR_t2")
t3 = time.perf_counter()
fast_times.append(t1 - t0)
slow_times.append(t3 - t2)
avg_fast = sum(fast_times) / len(fast_times)
avg_slow = sum(slow_times) / len(slow_times)
assert avg_fast < avg_slow, f"Fast version ({avg_fast:.6f}s) should be faster than EPICS ({avg_slow:.6f}s)"
def test_motor_without_suffix_and_dot():
# Suffix .VAL ... dot should be stripped from name
m1 = Motor("TEST:MOTOR_1.VAL")
assert m1._prefix == "TEST:MOTOR_1"
m2 = Motor("TEST:MOTOR_2.")
assert m2._prefix == "TEST:MOTOR_2"
m3 = Motor("TEST:MOTOR")
assert m3._prefix == "TEST:MOTOR"
def test_motor_invalid_name_raises():
# Should raise MotorException if name is none
with pytest.raises(MotorException):
Motor(None)
def test_motor_init_list_has_no_disabled():
assert "disabled" not in Motor._init_list
assert "disabled" not in Motor._extras
def test_motor_initializes_device_attrs():
# Check that Motor correctly initializes all Device PVs from _init_list
m = Motor("TEST:MOTOR")
print("_init_list contents:", m._init_list)
print("All attributes on motor:", dir(m))
for attr in m._init_list:
print(f"\nChecking attribute: {attr}")
assert hasattr(m, attr), f"Motor is missing attribute: {attr}"
pv = getattr(m, attr)
print(f"PV object: {pv}")
print("Type:", type(pv))
if pv is not None:
print(f"PV name: {pv.pvname}")
print(f"PV connected: {pv.connected}")
assert isinstance(pv, epics.pv.PV), f"{attr} is not a valid PV object"
assert not pv.connected, f"{attr} should not be connected yet"
def test_motor_pv_connection_skipped_by_default():
# PVs should not be connected right after Motor creation
m = Motor("TEST:MOTOR")
for key in m._extras:
pv = m.PV(key)
# Explicitly check that no connection was forced during init
assert not pv.connected, f"PV {key} was connected unexpectedly"
def test_motor_adds_all_extras_pvs():
# Given a test motor name
m = Motor("TEST:MOTOR")
# For each key in _extras, the motor should have an attribute with that name
for attr_name, suffix in m._extras.items():
# The attribute must exist
assert hasattr(m, attr_name), f"Missing attribute: {attr_name}"
# The attribute must be a PV
pv = getattr(m, attr_name)
assert isinstance(pv, PV), f"{attr_name} is not a PV"
# The PV's name should match the expected pattern
expected_name = f"TEST:MOTOR{suffix}"
assert pv.pvname == expected_name, f"PV name mismatch for {attr_name}"
assert not pv.connected, f"{attr_name} PV should not be connected immediately"
def test_motor_PV_method_exists_and_works():
# Motor.PV(): should call super().PV and return a PV object
m = Motor("TEST:MOTOR")
pv = m.PV("RBV", connect=False)
assert pv is not None
assert isinstance(pv, epics.pv.PV)