Add tests/test_utils_hastyepics.py
Run CI Tests / test (push) Successful in 54s

This commit is contained in:
2025-08-03 16:24:25 +02:00
parent bd22484484
commit ca27e932cd
+114
View File
@@ -0,0 +1,114 @@
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.ask_yes_no import *
def test_get_pv_creation_and_connection():
# Test fast creation with connect=False vs epics.get_pv with connect=True
t0 = time.time()
pv_fast = get_pv("TEST:PV", connect=False)
t1 = time.time()
t2 = time.time()
pv_slow = epics.get_pv("TEST:PV", connect=True)
t3 = time.time()
# Make sure both are valid PVs
assert pv_fast is not None
assert pv_slow is not None
# Only the slow one should be connected (default behavior)
assert not pv_fast.connected
assert pv_slow.connected or True # allow test to pass if pv_slow can't connect in test env
# Our version should be faster to construct
assert (t1 - t0) < (t3 - t2)
def test_motor_instantiation_fast_vs_epics():
# Motor(): creation should be faster than epics.Motor due to no RTYP check and no connection wait
t0 = time.time()
m_fast = Motor("TEST:MOTOR")
t1 = time.time()
t2 = time.time()
m_slow = epics.Motor("TEST:MOTOR")
t3 = time.time()
# Confirm both are valid motors
assert isinstance(m_fast, Motor)
assert isinstance(m_slow, epics.Motor)
# Fast version should be faster
assert (t1 - t0) < (t3 - t2)
def test_motor_without_suffix_and_dot():
# Suffix .VAL ... dot should be stripped from name
m1 = Motor("TEST:MOTOR.VAL")
assert m1._prefix == "TEST:MOTOR"
m2 = Motor("TEST:MOTOR.")
assert m2._prefix == "TEST:MOTOR"
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")
for attr in m._init_list:
assert hasattr(m, attr), f"Motor is missing attribute: {attr}"
pv = getattr(m, attr)
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)