From 0e986f2cb220046f936927a6cc76518c99f3c4ec Mon Sep 17 00:00:00 2001 From: Robert Tuck Date: Tue, 14 Jan 2025 13:38:29 +0000 Subject: [PATCH] Convert i24 to device_factory. Improvements to clearing of device_factory caches during unit tests --- .../serial/fixed_target/i24ssx_moveonclick.py | 4 +-- .../serial/setup_beamline/setup_beamline.py | 4 +-- tests/conftest.py | 11 +++++++ .../beamlines/i24/serial/conftest.py | 31 ++++++++++++------- tests/unit_tests/conftest.py | 17 ++++++++++ tests/unit_tests/hyperion/conftest.py | 18 ----------- 6 files changed, 52 insertions(+), 33 deletions(-) diff --git a/src/mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_moveonclick.py b/src/mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_moveonclick.py index 97d7f01b4..c2faa3ec2 100755 --- a/src/mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_moveonclick.py +++ b/src/mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_moveonclick.py @@ -215,6 +215,6 @@ def start_viewer(oav: OAV, pmac: PMAC, RE: RunEngine, oav1: str = OAV1_CAM): if __name__ == "__main__": RE = RunEngine(call_returns_result=True) # Get devices out of dodal - oav: OAV = i24.oav() - pmac: PMAC = i24.pmac() + oav: OAV = i24.oav(connect_immediately=True) + pmac: PMAC = i24.pmac(connect_immediately=True) start_viewer(oav, pmac, RE) diff --git a/src/mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py b/src/mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py index 8135153fe..f4899f1e5 100644 --- a/src/mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py +++ b/src/mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py @@ -16,9 +16,9 @@ def get_beam_center_device(detector_in_use: str) -> DetectorBeamCenter: if detector_in_use == "eiger": - return i24.eiger_beam_center() + return i24.eiger_beam_center(connect_immediately=True) else: - return i24.pilatus_beam_center() + return i24.pilatus_beam_center(connect_immediately=True) def setup_beamline_for_collection_plan( diff --git a/tests/conftest.py b/tests/conftest.py index 5356de234..a99935c56 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -58,6 +58,7 @@ ) from dodal.log import LOGGER as dodal_logger from dodal.log import set_up_all_logging_handlers +from dodal.utils import AnyDeviceFactory from event_model.documents import Event, EventDescriptor, RunStart, RunStop from ispyb.sp.mxacquisition import MXAcquisition from ophyd.sim import NullStatus @@ -103,12 +104,22 @@ HyperionThreeDGridScan, ) from mx_bluesky.hyperion.parameters.rotation import MultiRotationScan, RotationScan +from unit_tests.conftest import device_factories_for_beamline i03.DAQ_CONFIGURATION_PATH = "tests/test_data/test_daq_configuration" TEST_GRAYLOG_PORT = 5555 +@pytest.fixture(scope="session") +def active_device_factories() -> set[AnyDeviceFactory]: + """Obtain the set of device factories that should have their caches cleared + after every test invocation. + + Override this in sub-packages for the specific beamlines under test.""" + return device_factories_for_beamline(i03) + + def raw_params_from_file(filename): with open(filename) as f: return json.loads(f.read()) diff --git a/tests/unit_tests/beamlines/i24/serial/conftest.py b/tests/unit_tests/beamlines/i24/serial/conftest.py index 4dbf0f079..b3a2cdef9 100644 --- a/tests/unit_tests/beamlines/i24/serial/conftest.py +++ b/tests/unit_tests/beamlines/i24/serial/conftest.py @@ -16,6 +16,7 @@ from dodal.devices.i24.focus_mirrors import FocusMirrorsMode, HFocusMode, VFocusMode from dodal.devices.i24.pmac import PMAC from dodal.devices.zebra import Zebra +from dodal.utils import AnyDeviceFactory from ophyd_async.epics.motor import Motor from ophyd_async.testing import callback_on_mock_put, get_mock_put, set_mock_value @@ -25,6 +26,12 @@ FixedTargetParameters, get_chip_format, ) +from unit_tests.conftest import device_factories_for_beamline + + +@pytest.fixture(scope="session") +def active_device_factories(active_device_factories) -> set[AnyDeviceFactory]: + return active_device_factories | device_factories_for_beamline(i24) @pytest.fixture @@ -78,7 +85,7 @@ def patch_motor(motor: Motor, initial_position: float = 0): @pytest.fixture def zebra(RE) -> Zebra: - zebra = i24.zebra(fake_with_ophyd_sim=True, wait_for_connection=True) + zebra = i24.zebra(connect_immediately=True, mock=True) def mock_disarm(_, wait): set_mock_value(zebra.pc.arm.armed, 0) @@ -93,7 +100,7 @@ def mock_arm(_, wait): @pytest.fixture def shutter(RE) -> HutchShutter: - shutter = i24.shutter(fake_with_ophyd_sim=True) + shutter = i24.shutter(connect_immediately=True, mock=True) set_mock_value(shutter.interlock.status, HUTCH_SAFE_FOR_OPERATIONS) def set_status(value: ShutterDemand, *args, **kwargs): @@ -106,7 +113,7 @@ def set_status(value: ShutterDemand, *args, **kwargs): @pytest.fixture def detector_stage(RE): - detector_motion = i24.detector_motion(fake_with_ophyd_sim=True) + detector_motion = i24.detector_motion(connect_immediately=True, mock=True) with patch_motor(detector_motion.y), patch_motor(detector_motion.z): yield detector_motion @@ -114,20 +121,20 @@ def detector_stage(RE): @pytest.fixture def aperture(RE): - aperture: Aperture = i24.aperture(fake_with_ophyd_sim=True) + aperture: Aperture = i24.aperture(connect_immediately=True, mock=True) with patch_motor(aperture.x), patch_motor(aperture.y): yield aperture @pytest.fixture def backlight(RE) -> DualBacklight: - backlight = i24.backlight(fake_with_ophyd_sim=True) + backlight = i24.backlight(connect_immediately=True, mock=True) return backlight @pytest.fixture def beamstop(RE): - beamstop: Beamstop = i24.beamstop(fake_with_ophyd_sim=True) + beamstop: Beamstop = i24.beamstop(connect_immediately=True, mock=True) with ( patch_motor(beamstop.x), @@ -140,7 +147,7 @@ def beamstop(RE): @pytest.fixture def pmac(RE): - pmac: PMAC = i24.pmac(fake_with_ophyd_sim=True) + pmac: PMAC = i24.pmac(connect_immediately=True, mock=True) with ( patch_motor(pmac.x), patch_motor(pmac.y), @@ -151,13 +158,13 @@ def pmac(RE): @pytest.fixture def dcm(RE) -> DCM: - dcm = i24.dcm(fake_with_ophyd_sim=True) + dcm = i24.dcm(connect_immediately=True, mock=True) return dcm @pytest.fixture def eiger_beam_center(RE) -> DetectorBeamCenter: - bc: DetectorBeamCenter = i24.eiger_beam_center(fake_with_ophyd_sim=True) + bc: DetectorBeamCenter = i24.eiger_beam_center(connect_immediately=True, mock=True) set_mock_value(bc.beam_x, 1605) set_mock_value(bc.beam_y, 1702) return bc @@ -165,7 +172,9 @@ def eiger_beam_center(RE) -> DetectorBeamCenter: @pytest.fixture def pilatus_beam_center(RE) -> DetectorBeamCenter: - bc: DetectorBeamCenter = i24.pilatus_beam_center(fake_with_ophyd_sim=True) + bc: DetectorBeamCenter = i24.pilatus_beam_center( + connect_immediately=True, mock=True + ) set_mock_value(bc.beam_x, 1298) set_mock_value(bc.beam_y, 1307) return bc @@ -173,7 +182,7 @@ def pilatus_beam_center(RE) -> DetectorBeamCenter: @pytest.fixture def mirrors(RE) -> FocusMirrorsMode: - mirrors: FocusMirrorsMode = i24.focus_mirrors(fake_with_ophyd_sim=True) + mirrors: FocusMirrorsMode = i24.focus_mirrors(connect_immediately=True, mock=True) set_mock_value(mirrors.horizontal, HFocusMode.FOCUS_10) set_mock_value(mirrors.vertical, VFocusMode.FOCUS_10) return mirrors diff --git a/tests/unit_tests/conftest.py b/tests/unit_tests/conftest.py index 56675a37a..dd7548dc2 100644 --- a/tests/unit_tests/conftest.py +++ b/tests/unit_tests/conftest.py @@ -1,9 +1,11 @@ import asyncio import time +from types import ModuleType import pytest from bluesky.run_engine import RunEngine from dodal.common.beamlines import beamline_parameters +from dodal.utils import AnyDeviceFactory, collect_factories @pytest.fixture @@ -42,3 +44,18 @@ def mock_beamline_module_filepaths(bl_name, bl_module): beamline_parameters.BEAMLINE_PARAMETER_PATHS[bl_name] = ( "tests/test_data/i04_beamlineParameters" ) + + +def device_factories_for_beamline(beamline_module: ModuleType) -> set[AnyDeviceFactory]: + return { + f + for f in collect_factories(beamline_module, include_skipped=True).values() + if hasattr(f, "cache_clear") + } + + +@pytest.fixture(scope="function", autouse=True) +def clear_device_factory_caches_after_every_test(active_device_factories): + yield None + for f in active_device_factories: + f.cache_clear() # type: ignore diff --git a/tests/unit_tests/hyperion/conftest.py b/tests/unit_tests/hyperion/conftest.py index c8fd1dc9f..9e012c754 100644 --- a/tests/unit_tests/hyperion/conftest.py +++ b/tests/unit_tests/hyperion/conftest.py @@ -2,28 +2,10 @@ from unittest.mock import patch import pytest -from dodal.beamlines import i03 -from dodal.utils import collect_factories BANNED_PATHS = [Path("/dls"), Path("/dls_sw")] -@pytest.fixture(scope="session") -def i03_device_factories(): - return [ - f - for f in collect_factories(i03, include_skipped=True).values() - if hasattr(f, "cache_clear") - ] - - -@pytest.fixture(scope="function", autouse=True) -def clear_device_factory_caches_after_every_test(i03_device_factories): - yield None - for f in i03_device_factories: - f.cache_clear() # type: ignore - - @pytest.fixture(autouse=True) def patch_open_to_prevent_dls_reads_in_tests(): unpatched_open = open