From 49629201ae9afffe30299535ab9a8502cfe077a9 Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Tue, 3 Feb 2026 16:35:11 +0000 Subject: [PATCH 1/3] Add test parametrization --- tests/chtobisr.py | 66 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 45 insertions(+), 21 deletions(-) diff --git a/tests/chtobisr.py b/tests/chtobisr.py index 79f9d912..76e833b1 100644 --- a/tests/chtobisr.py +++ b/tests/chtobisr.py @@ -16,6 +16,12 @@ "name": DEVICE_PREFIX, "directory": get_default_ioc_dir("CHTOBISR"), "emulator": EMULATOR, + "macros": { + "ADDR1": 1, + "ADDR2": 2, + "ADDR3": 3, + }, + "pv_for_existence": "1:DISABLE", }, ] @@ -30,82 +36,100 @@ class ChtobisrTests(unittest.TestCase): def setUp(self): self._lewis, self._ioc = get_running_lewis_and_ioc(EMULATOR, DEVICE_PREFIX) - self.ca = ChannelAccess(device_prefix=DEVICE_PREFIX, default_timeout=30) + self.ca = { + 1: ChannelAccess(device_prefix=DEVICE_PREFIX + ":1", default_timeout=30), + 2: ChannelAccess(device_prefix=DEVICE_PREFIX + ":2", default_timeout=30), + 3: ChannelAccess(device_prefix=DEVICE_PREFIX + ":3", default_timeout=30), + } self._lewis.backdoor_set_on_device("connected", True) self._lewis.backdoor_run_function_on_device("reset") + @parameterized.expand([(1,), (2,), (3,)]) @skip_if_recsim("Lewis backdoor not available in RecSim") - def test_GIVEN_ID_requested_WHEN_device_connected_THEN_ID_is_returned(self): + def test_GIVEN_ID_requested_WHEN_device_connected_THEN_ID_is_returned(self, addr: int): expected_value = "Coherent OBIS Laser Remote - EMULATOR" self._lewis.backdoor_set_on_device("id", expected_value) - self.ca.assert_that_pv_is("ID", expected_value) + self.ca[addr].assert_that_pv_is("ID", expected_value) + @parameterized.expand([(1,), (2,), (3,)]) @skip_if_recsim("Lewis backdoor not available in RecSim") - def test_GIVEN_ID_requested_WHEN_device_disconnected_THEN_alarm_is_raised(self): - self.ca.assert_that_pv_alarm_is("ID", self.ca.Alarms.NONE) + def test_GIVEN_ID_requested_WHEN_device_disconnected_THEN_alarm_is_raised(self, addr: int): + self.ca[addr].assert_that_pv_alarm_is("ID", self.ca[addr].Alarms.NONE) with self._lewis.backdoor_simulate_disconnected_device(): - self.ca.assert_that_pv_alarm_is("ID", self.ca.Alarms.INVALID) + self.ca[addr].assert_that_pv_alarm_is("ID", self.ca[addr].Alarms.INVALID) # Assert alarms clear on reconnection - self.ca.assert_that_pv_alarm_is("ID", self.ca.Alarms.NONE) + self.ca[addr].assert_that_pv_alarm_is("ID", self.ca[addr].Alarms.NONE) + @parameterized.expand([(1,), (2,), (3,)]) @skip_if_recsim("Lewis backdoor not available in RecSim") - def test_GIVEN_reset_requested_THEN_emulator_is_reset(self): + def test_GIVEN_reset_requested_THEN_emulator_is_reset(self, addr: int): self._lewis.backdoor_set_on_device("interlock", "ON") - self.ca.assert_that_pv_is("INTERLOCK", "CLOSED") + self.ca[addr].assert_that_pv_is("INTERLOCK", "CLOSED") self._lewis.backdoor_run_function_on_device("reset") - self.ca.assert_that_pv_is("INTERLOCK", "OPEN") + self.ca[addr].assert_that_pv_is("INTERLOCK", "OPEN") + @parameterized.expand([(1,), (2,), (3,)]) @skip_if_recsim("Lewis backdoor not available in RecSim") - def test_GIVEN_reset_requested_WHEN_device_connected_THEN_device_is_reset(self): + def test_GIVEN_reset_requested_WHEN_device_connected_THEN_device_is_reset(self, addr: int): self._lewis.backdoor_set_on_device("interlock", "ON") - self.ca.assert_that_pv_is("INTERLOCK", "CLOSED") - self.ca.set_pv_value("RESET:SP", "TRUE") - self.ca.assert_that_pv_is("INTERLOCK", "OPEN") + self.ca[addr].assert_that_pv_is("INTERLOCK", "CLOSED") + self.ca[addr].set_pv_value("RESET:SP", "TRUE") + self.ca[addr].assert_that_pv_is("INTERLOCK", "OPEN") + @parameterized.expand([(1,), (2,), (3,)]) @skip_if_recsim("Lewis backdoor not available in RecSim") def test_GIVEN_interlock_status_requested_WHEN_device_connected_THEN_interlock_status_is_returned( self, + addr: int ): self._lewis.backdoor_set_on_device("interlock", "OFF") - self.ca.assert_that_pv_is("INTERLOCK", "OPEN") + self.ca[addr].assert_that_pv_is("INTERLOCK", "OPEN") + @parameterized.expand([(1,), (2,), (3,)]) @skip_if_recsim("Lewis backdoor not available in RecSim") def test_GIVEN_status_requested_WHEN_lowest_status_bit_set_THEN_correct_status_code_is_returned( self, + addr: int, ): expected_value = 0x0001 self._lewis.backdoor_run_function_on_device("backdoor_set_status", ["laser_fault", True]) - self.ca.assert_that_pv_is("STAT:LOW.VAL", expected_value) + self.ca[addr].assert_that_pv_is("STAT:LOW.VAL", expected_value) + @parameterized.expand([(1,), (2,), (3,)]) @skip_if_recsim("Lewis backdoor not available in RecSim") def test_GIVEN_status_requested_WHEN_highest_status_bit_set_THEN_correct_status_code_is_returned( self, + addr: int, ): expected_value = 0x8000 self._lewis.backdoor_run_function_on_device( "backdoor_set_status", ["controller_indicator", True] ) - self.ca.assert_that_pv_is("STAT:HIGH.VAL", expected_value) + self.ca[addr].assert_that_pv_is("STAT:HIGH.VAL", expected_value) + @parameterized.expand([(1,), (2,), (3,)]) @skip_if_recsim("Lewis backdoor not available in RecSim") def test_GIVEN_faults_requested_WHEN_lowest_fault_bit_set_THEN_correct_fault_code_is_returned( self, + addr: int ): expected_value = 0x0001 self._lewis.backdoor_run_function_on_device( "backdoor_set_fault", ["base_plate_temp_fault", True] ) - self.ca.assert_that_pv_is("FAULT:LOW.VAL", expected_value) + self.ca[addr].assert_that_pv_is("FAULT:LOW.VAL", expected_value) + @parameterized.expand([(1,), (2,), (3,)]) @skip_if_recsim("Lewis backdoor not available in RecSim") def test_GIVEN_faults_requested_WHEN_highest_fault_bit_set_THEN_correct_fault_code_is_returned( self, + addr: int ): expected_value = 0x8000 self._lewis.backdoor_run_function_on_device( "backdoor_set_fault", ["controller_status", True] ) - self.ca.assert_that_pv_is("FAULT:HIGH.VAL", expected_value) + self.ca[addr].assert_that_pv_is("FAULT:HIGH.VAL", expected_value) @parameterized.expand( parameterized_list( @@ -141,7 +165,7 @@ def test_GIVEN_status_active_WHEN_read_status_THEN_pv_reads_status_state( self._lewis.backdoor_run_function_on_device( "backdoor_set_status", [backdoor_name, state] ) - self.ca.assert_that_pv_is(pv_name, str(state)) + self.ca[1].assert_that_pv_is(pv_name, str(state)) @parameterized.expand( parameterized_list( @@ -179,4 +203,4 @@ def test_GIVEN_fault_active_WHEN_read_faults_THEN_pv_reads_fault_state( self._lewis.backdoor_run_function_on_device( "backdoor_set_fault", [backdoor_name, state] ) - self.ca.assert_that_pv_is(pv_name, str(state)) + self.ca[1].assert_that_pv_is(pv_name, str(state)) From 8001d5ab376e7d39ee3c6ae32324c9ddf8e0732d Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Wed, 4 Feb 2026 11:03:09 +0000 Subject: [PATCH 2/3] Multi-device tests & test new functions --- tests/chtobisr.py | 55 +++++++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/tests/chtobisr.py b/tests/chtobisr.py index 76e833b1..774b7533 100644 --- a/tests/chtobisr.py +++ b/tests/chtobisr.py @@ -37,9 +37,15 @@ class ChtobisrTests(unittest.TestCase): def setUp(self): self._lewis, self._ioc = get_running_lewis_and_ioc(EMULATOR, DEVICE_PREFIX) self.ca = { - 1: ChannelAccess(device_prefix=DEVICE_PREFIX + ":1", default_timeout=30), - 2: ChannelAccess(device_prefix=DEVICE_PREFIX + ":2", default_timeout=30), - 3: ChannelAccess(device_prefix=DEVICE_PREFIX + ":3", default_timeout=30), + 1: ChannelAccess( + device_prefix=DEVICE_PREFIX + ":1", default_timeout=30, default_wait_time=0.0 + ), + 2: ChannelAccess( + device_prefix=DEVICE_PREFIX + ":2", default_timeout=30, default_wait_time=0.0 + ), + 3: ChannelAccess( + device_prefix=DEVICE_PREFIX + ":3", default_timeout=30, default_wait_time=0.0 + ), } self._lewis.backdoor_set_on_device("connected", True) self._lewis.backdoor_run_function_on_device("reset") @@ -48,7 +54,7 @@ def setUp(self): @skip_if_recsim("Lewis backdoor not available in RecSim") def test_GIVEN_ID_requested_WHEN_device_connected_THEN_ID_is_returned(self, addr: int): expected_value = "Coherent OBIS Laser Remote - EMULATOR" - self._lewis.backdoor_set_on_device("id", expected_value) + self._lewis.backdoor_run_function_on_device("backdoor_set_id", [addr, expected_value]) self.ca[addr].assert_that_pv_is("ID", expected_value) @parameterized.expand([(1,), (2,), (3,)]) @@ -63,7 +69,7 @@ def test_GIVEN_ID_requested_WHEN_device_disconnected_THEN_alarm_is_raised(self, @parameterized.expand([(1,), (2,), (3,)]) @skip_if_recsim("Lewis backdoor not available in RecSim") def test_GIVEN_reset_requested_THEN_emulator_is_reset(self, addr: int): - self._lewis.backdoor_set_on_device("interlock", "ON") + self._lewis.backdoor_run_function_on_device("backdoor_set_interlock", [addr, "ON"]) self.ca[addr].assert_that_pv_is("INTERLOCK", "CLOSED") self._lewis.backdoor_run_function_on_device("reset") self.ca[addr].assert_that_pv_is("INTERLOCK", "OPEN") @@ -71,7 +77,7 @@ def test_GIVEN_reset_requested_THEN_emulator_is_reset(self, addr: int): @parameterized.expand([(1,), (2,), (3,)]) @skip_if_recsim("Lewis backdoor not available in RecSim") def test_GIVEN_reset_requested_WHEN_device_connected_THEN_device_is_reset(self, addr: int): - self._lewis.backdoor_set_on_device("interlock", "ON") + self._lewis.backdoor_run_function_on_device("backdoor_set_interlock", [addr, "ON"]) self.ca[addr].assert_that_pv_is("INTERLOCK", "CLOSED") self.ca[addr].set_pv_value("RESET:SP", "TRUE") self.ca[addr].assert_that_pv_is("INTERLOCK", "OPEN") @@ -79,10 +85,9 @@ def test_GIVEN_reset_requested_WHEN_device_connected_THEN_device_is_reset(self, @parameterized.expand([(1,), (2,), (3,)]) @skip_if_recsim("Lewis backdoor not available in RecSim") def test_GIVEN_interlock_status_requested_WHEN_device_connected_THEN_interlock_status_is_returned( - self, - addr: int + self, addr: int ): - self._lewis.backdoor_set_on_device("interlock", "OFF") + self._lewis.backdoor_run_function_on_device("backdoor_set_interlock", [addr, "OFF"]) self.ca[addr].assert_that_pv_is("INTERLOCK", "OPEN") @parameterized.expand([(1,), (2,), (3,)]) @@ -92,7 +97,9 @@ def test_GIVEN_status_requested_WHEN_lowest_status_bit_set_THEN_correct_status_c addr: int, ): expected_value = 0x0001 - self._lewis.backdoor_run_function_on_device("backdoor_set_status", ["laser_fault", True]) + self._lewis.backdoor_run_function_on_device( + "backdoor_set_status", [addr, "laser_fault", True] + ) self.ca[addr].assert_that_pv_is("STAT:LOW.VAL", expected_value) @parameterized.expand([(1,), (2,), (3,)]) @@ -103,31 +110,29 @@ def test_GIVEN_status_requested_WHEN_highest_status_bit_set_THEN_correct_status_ ): expected_value = 0x8000 self._lewis.backdoor_run_function_on_device( - "backdoor_set_status", ["controller_indicator", True] + "backdoor_set_status", [addr, "controller_indicator", True] ) self.ca[addr].assert_that_pv_is("STAT:HIGH.VAL", expected_value) @parameterized.expand([(1,), (2,), (3,)]) @skip_if_recsim("Lewis backdoor not available in RecSim") def test_GIVEN_faults_requested_WHEN_lowest_fault_bit_set_THEN_correct_fault_code_is_returned( - self, - addr: int + self, addr: int ): expected_value = 0x0001 self._lewis.backdoor_run_function_on_device( - "backdoor_set_fault", ["base_plate_temp_fault", True] + "backdoor_set_fault", [addr, "base_plate_temp_fault", True] ) self.ca[addr].assert_that_pv_is("FAULT:LOW.VAL", expected_value) @parameterized.expand([(1,), (2,), (3,)]) @skip_if_recsim("Lewis backdoor not available in RecSim") def test_GIVEN_faults_requested_WHEN_highest_fault_bit_set_THEN_correct_fault_code_is_returned( - self, - addr: int + self, addr: int ): expected_value = 0x8000 self._lewis.backdoor_run_function_on_device( - "backdoor_set_fault", ["controller_status", True] + "backdoor_set_fault", [addr, "controller_status", True] ) self.ca[addr].assert_that_pv_is("FAULT:HIGH.VAL", expected_value) @@ -163,7 +168,7 @@ def test_GIVEN_status_active_WHEN_read_status_THEN_pv_reads_status_state( ): for state in [False, True]: self._lewis.backdoor_run_function_on_device( - "backdoor_set_status", [backdoor_name, state] + "backdoor_set_status", [1, backdoor_name, state] ) self.ca[1].assert_that_pv_is(pv_name, str(state)) @@ -201,6 +206,18 @@ def test_GIVEN_fault_active_WHEN_read_faults_THEN_pv_reads_fault_state( ): for state in [False, True]: self._lewis.backdoor_run_function_on_device( - "backdoor_set_fault", [backdoor_name, state] + "backdoor_set_fault", [1, backdoor_name, state] ) self.ca[1].assert_that_pv_is(pv_name, str(state)) + + @parameterized.expand([(1,), (2,), (3,)]) + @skip_if_recsim("Lewis backdoor not available in RecSim") + def test_GIVEN_source_power_set_then_power_read_back(self, addr: int): + self.ca[addr].assert_setting_setpoint_sets_readback(1.23, "AMP") + self.ca[addr].assert_setting_setpoint_sets_readback(4.56, "AMP") + + @parameterized.expand([(1,), (2,), (3,)]) + @skip_if_recsim("Lewis backdoor not available in RecSim") + def test_GIVEN_source_state_set_then_state_read_back(self, addr: int): + self.ca[addr].assert_setting_setpoint_sets_readback("ON", "STAT") + self.ca[addr].assert_setting_setpoint_sets_readback("OFF", "STAT") From d95f02284a90fdcd73dfbfc48da6e497cb6492a1 Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Wed, 4 Feb 2026 11:30:28 +0000 Subject: [PATCH 3/3] pyright --- tests/chtobisr.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/chtobisr.py b/tests/chtobisr.py index 774b7533..6236445a 100644 --- a/tests/chtobisr.py +++ b/tests/chtobisr.py @@ -1,9 +1,11 @@ +import typing import unittest from parameterized import parameterized from utils.channel_access import ChannelAccess -from utils.ioc_launcher import get_default_ioc_dir +from utils.emulator_launcher import EmulatorLauncher +from utils.ioc_launcher import BaseLauncher, get_default_ioc_dir from utils.test_modes import TestModes from utils.testing import get_running_lewis_and_ioc, parameterized_list, skip_if_recsim @@ -35,7 +37,10 @@ class ChtobisrTests(unittest.TestCase): """ def setUp(self): - self._lewis, self._ioc = get_running_lewis_and_ioc(EMULATOR, DEVICE_PREFIX) + self._lewis, self._ioc = typing.cast( + tuple[EmulatorLauncher, BaseLauncher], + get_running_lewis_and_ioc(EMULATOR, DEVICE_PREFIX), + ) self.ca = { 1: ChannelAccess( device_prefix=DEVICE_PREFIX + ":1", default_timeout=30, default_wait_time=0.0