diff --git a/bec_widgets/tests/utils.py b/bec_widgets/tests/utils.py index 8b50b379..7ed18e5b 100644 --- a/bec_widgets/tests/utils.py +++ b/bec_widgets/tests/utils.py @@ -1,11 +1,19 @@ # pylint: skip-file +import json +import time from unittest.mock import MagicMock +import h5py +from bec_lib import messages +from bec_lib.bec_service import messages from bec_lib.config_helper import ConfigHelper from bec_lib.device import Device as BECDevice from bec_lib.device import Positioner as BECPositioner from bec_lib.device import ReadoutPriority from bec_lib.devicemanager import DeviceContainer +from bec_lib.messages import _StoredDataInfo +from bec_lib.scan_history import ScanHistory +from qtpy.QtCore import QEvent, QEventLoop class FakeDevice(BECDevice): @@ -308,3 +316,157 @@ def check_remote_data_size(widget, plot_name, num_elements): Used in the qtbot.waitUntil function. """ return len(widget.get_all_data()[plot_name]["x"]) == num_elements + + +class DummyData: + def __init__(self, val, timestamps): + self.val = val + self.timestamps = timestamps + + def get(self, key, default=None): + if key == "val": + return self.val + return default + + +def create_dummy_scan_item(): + """ + Helper to create a dummy scan item with both live_data and metadata/status_message info. + """ + dummy_live_data = { + "samx": {"samx": DummyData(val=[10, 20, 30], timestamps=[100, 200, 300])}, + "samy": {"samy": DummyData(val=[5, 10, 15], timestamps=[100, 200, 300])}, + "bpm4i": {"bpm4i": DummyData(val=[5, 6, 7], timestamps=[101, 201, 301])}, + "async_device": {"async_device": DummyData(val=[1, 2, 3], timestamps=[11, 21, 31])}, + } + dummy_scan = MagicMock() + dummy_scan.live_data = dummy_live_data + dummy_scan.metadata = { + "bec": { + "scan_id": "dummy", + "scan_report_devices": ["samx"], + "readout_priority": {"monitored": ["bpm4i"], "async": ["async_device"]}, + } + } + dummy_scan.status_message.info = { + "readout_priority": {"monitored": ["bpm4i"], "async": ["async_device"]}, + "scan_report_devices": ["samx"], + } + return dummy_scan + + +def inject_scan_history(widget, scan_history_factory, *history_args): + """ + Helper to inject scan history messages into client history. + """ + history_msgs = [] + for scan_id, scan_number in history_args: + history_msgs.append(scan_history_factory(scan_id=scan_id, scan_number=scan_number)) + widget.client.history = ScanHistory(widget.client, False) + for msg in history_msgs: + widget.client.history._scan_data[msg.scan_id] = msg + widget.client.history._scan_ids.append(msg.scan_id) + widget.client.queue.scan_storage.current_scan = None + return history_msgs + + +def create_history_file(file_path, data: dict, metadata: dict) -> messages.ScanHistoryMessage: + """ + Helper to create a history file with the given data. + The data should contain readout groups, e.g. + { + "baseline": {"samx": {"samx": {"value": [1, 2, 3], "timestamp": [100, 200, 300]}}, + "monitored": {"bpm4i": {"bpm4i": {"value": [5, 6, 7], "timestamp": [101, 201, 301]}}}, + "async": {"async_device": {"async_device": {"value": [1, 2, 3], "timestamp": [11, 21, 31]}}}, + } + + """ + + with h5py.File(file_path, "w") as f: + _metadata = f.create_group("entry/collection/metadata") + _metadata.create_dataset("sample_name", data="test_sample") + metadata_bec = f.create_group("entry/collection/metadata/bec") + for key, value in metadata.items(): + if isinstance(value, dict): + metadata_bec.create_group(key) + for sub_key, sub_value in value.items(): + if isinstance(sub_value, list): + sub_value = json.dumps(sub_value) + metadata_bec[key].create_dataset(sub_key, data=sub_value) + elif isinstance(sub_value, dict): + for sub_sub_key, sub_sub_value in sub_value.items(): + sub_sub_group = metadata_bec[key].create_group(sub_key) + # Handle _StoredDataInfo objects + if isinstance(sub_sub_value, _StoredDataInfo): + # Store the numeric shape + sub_sub_group.create_dataset("shape", data=sub_sub_value.shape) + # Store the dtype as a UTF-8 string + dt = sub_sub_value.dtype or "" + sub_sub_group.create_dataset( + "dtype", data=dt, dtype=h5py.string_dtype(encoding="utf-8") + ) + continue + if isinstance(sub_sub_value, list): + json_val = json.dumps(sub_sub_value) + sub_sub_group.create_dataset(sub_sub_key, data=json_val) + elif isinstance(sub_sub_value, dict): + for k2, v2 in sub_sub_value.items(): + val = json.dumps(v2) if isinstance(v2, list) else v2 + sub_sub_group.create_dataset(k2, data=val) + else: + sub_sub_group.create_dataset(sub_sub_key, data=sub_sub_value) + else: + metadata_bec[key].create_dataset(sub_key, data=sub_value) + else: + metadata_bec.create_dataset(key, data=value) + for group, devices in data.items(): + readout_group = f.create_group(f"entry/collection/readout_groups/{group}") + + for device, device_data in devices.items(): + dev_group = f.create_group(f"entry/collection/devices/{device}") + for signal, signal_data in device_data.items(): + signal_group = dev_group.create_group(signal) + for signal_key, signal_values in signal_data.items(): + signal_group.create_dataset(signal_key, data=signal_values) + + readout_group[device] = h5py.SoftLink(f"/entry/collection/devices/{device}") + msg = messages.ScanHistoryMessage( + scan_id=metadata["scan_id"], + scan_name=metadata["scan_name"], + exit_status=metadata["exit_status"], + file_path=file_path, + scan_number=metadata["scan_number"], + dataset_number=metadata["dataset_number"], + start_time=time.time(), + end_time=time.time(), + num_points=metadata["num_points"], + request_inputs=metadata["request_inputs"], + stored_data_info=metadata.get("stored_data_info"), + metadata={"scan_report_devices": metadata.get("scan_report_devices")}, + ) + return msg + + +def create_widget(qtbot, widget, *args, **kwargs): + """ + Create a widget and add it to the qtbot for testing. This is a helper function that + should be used in all tests that require a widget to be created. + + Args: + qtbot (fixture): pytest-qt fixture + widget (QWidget): widget class to be created + *args: positional arguments for the widget + **kwargs: keyword arguments for the widget + + Returns: + QWidget: the created widget + """ + widget = widget(*args, **kwargs) + qtbot.addWidget(widget) + qtbot.waitExposed(widget) + return widget + + +def process_all_deferred_deletes(qapp): + qapp.sendPostedEvents(None, QEvent.Type.DeferredDelete) + qapp.processEvents(QEventLoop.ProcessEventsFlag.AllEvents) diff --git a/tests/unit_tests/conftest.py b/tests/unit_tests/conftest.py index 2e6dce74..f3650878 100644 --- a/tests/unit_tests/conftest.py +++ b/tests/unit_tests/conftest.py @@ -21,7 +21,14 @@ from qtpy.QtCore import QEvent, QEventLoop from qtpy.QtWidgets import QApplication, QMessageBox from bec_widgets.cli.rpc.rpc_register import RPCRegister -from bec_widgets.tests.utils import DEVICES, DMMock, FakePositioner, Positioner +from bec_widgets.tests.utils import ( + DEVICES, + DMMock, + FakePositioner, + Positioner, + create_history_file, + process_all_deferred_deletes, +) from bec_widgets.utils import bec_dispatcher as bec_dispatcher_module from bec_widgets.utils import error_popups from bec_widgets.utils.bec_dispatcher import QtRedisConnector @@ -40,11 +47,6 @@ def pytest_runtest_makereport(item, call): item.stash["failed"] = rep.failed -def process_all_deferred_deletes(qapp): - qapp.sendPostedEvents(None, QEvent.Type.DeferredDelete) - qapp.processEvents(QEventLoop.ProcessEventsFlag.AllEvents) - - @pytest.fixture(autouse=True) def qapplication(qtbot, request, testable_qtimer_class): # pylint: disable=unused-argument qapp = QApplication.instance() @@ -134,103 +136,6 @@ def suppress_message_box(monkeypatch): monkeypatch.setattr(QMessageBox, "exec_", lambda *args, **kwargs: QMessageBox.Ok) -def create_widget(qtbot, widget, *args, **kwargs): - """ - Create a widget and add it to the qtbot for testing. This is a helper function that - should be used in all tests that require a widget to be created. - - Args: - qtbot (fixture): pytest-qt fixture - widget (QWidget): widget class to be created - *args: positional arguments for the widget - **kwargs: keyword arguments for the widget - - Returns: - QWidget: the created widget - """ - widget = widget(*args, **kwargs) - qtbot.addWidget(widget) - qtbot.waitExposed(widget) - return widget - - -def create_history_file(file_path, data: dict, metadata: dict) -> messages.ScanHistoryMessage: - """ - Helper to create a history file with the given data. - The data should contain readout groups, e.g. - { - "baseline": {"samx": {"samx": {"value": [1, 2, 3], "timestamp": [100, 200, 300]}}, - "monitored": {"bpm4i": {"bpm4i": {"value": [5, 6, 7], "timestamp": [101, 201, 301]}}}, - "async": {"async_device": {"async_device": {"value": [1, 2, 3], "timestamp": [11, 21, 31]}}}, - } - - """ - - with h5py.File(file_path, "w") as f: - _metadata = f.create_group("entry/collection/metadata") - _metadata.create_dataset("sample_name", data="test_sample") - metadata_bec = f.create_group("entry/collection/metadata/bec") - for key, value in metadata.items(): - if isinstance(value, dict): - metadata_bec.create_group(key) - for sub_key, sub_value in value.items(): - if isinstance(sub_value, list): - sub_value = json.dumps(sub_value) - metadata_bec[key].create_dataset(sub_key, data=sub_value) - elif isinstance(sub_value, dict): - for sub_sub_key, sub_sub_value in sub_value.items(): - sub_sub_group = metadata_bec[key].create_group(sub_key) - # Handle _StoredDataInfo objects - if isinstance(sub_sub_value, _StoredDataInfo): - # Store the numeric shape - sub_sub_group.create_dataset("shape", data=sub_sub_value.shape) - # Store the dtype as a UTF-8 string - dt = sub_sub_value.dtype or "" - sub_sub_group.create_dataset( - "dtype", data=dt, dtype=h5py.string_dtype(encoding="utf-8") - ) - continue - if isinstance(sub_sub_value, list): - json_val = json.dumps(sub_sub_value) - sub_sub_group.create_dataset(sub_sub_key, data=json_val) - elif isinstance(sub_sub_value, dict): - for k2, v2 in sub_sub_value.items(): - val = json.dumps(v2) if isinstance(v2, list) else v2 - sub_sub_group.create_dataset(k2, data=val) - else: - sub_sub_group.create_dataset(sub_sub_key, data=sub_sub_value) - else: - metadata_bec[key].create_dataset(sub_key, data=sub_value) - else: - metadata_bec.create_dataset(key, data=value) - for group, devices in data.items(): - readout_group = f.create_group(f"entry/collection/readout_groups/{group}") - - for device, device_data in devices.items(): - dev_group = f.create_group(f"entry/collection/devices/{device}") - for signal, signal_data in device_data.items(): - signal_group = dev_group.create_group(signal) - for signal_key, signal_values in signal_data.items(): - signal_group.create_dataset(signal_key, data=signal_values) - - readout_group[device] = h5py.SoftLink(f"/entry/collection/devices/{device}") - msg = messages.ScanHistoryMessage( - scan_id=metadata["scan_id"], - scan_name=metadata["scan_name"], - exit_status=metadata["exit_status"], - file_path=file_path, - scan_number=metadata["scan_number"], - dataset_number=metadata["dataset_number"], - start_time=time.time(), - end_time=time.time(), - num_points=metadata["num_points"], - request_inputs=metadata["request_inputs"], - stored_data_info=metadata.get("stored_data_info"), - metadata={"scan_report_devices": metadata.get("scan_report_devices")}, - ) - return msg - - @pytest.fixture def grid_scan_history_msg(tmpdir): x_grid, y_grid = np.meshgrid(np.linspace(-5, 5, 10), np.linspace(-5, 5, 10)) @@ -397,6 +302,7 @@ def mocked_client(bec_dispatcher): @pytest.fixture(scope="function") def mock_client_w_devices(mocked_client): mocked_client.device_manager.add_devices(DEVICES) + yield mocked_client ################################################## @@ -544,55 +450,3 @@ def mocked_client_with_dap(mocked_client, dap_plugin_message): mocked_client.dap._available_dap_plugins = patched_models yield mocked_client - - -class DummyData: - def __init__(self, val, timestamps): - self.val = val - self.timestamps = timestamps - - def get(self, key, default=None): - if key == "val": - return self.val - return default - - -def create_dummy_scan_item(): - """ - Helper to create a dummy scan item with both live_data and metadata/status_message info. - """ - dummy_live_data = { - "samx": {"samx": DummyData(val=[10, 20, 30], timestamps=[100, 200, 300])}, - "samy": {"samy": DummyData(val=[5, 10, 15], timestamps=[100, 200, 300])}, - "bpm4i": {"bpm4i": DummyData(val=[5, 6, 7], timestamps=[101, 201, 301])}, - "async_device": {"async_device": DummyData(val=[1, 2, 3], timestamps=[11, 21, 31])}, - } - dummy_scan = MagicMock() - dummy_scan.live_data = dummy_live_data - dummy_scan.metadata = { - "bec": { - "scan_id": "dummy", - "scan_report_devices": ["samx"], - "readout_priority": {"monitored": ["bpm4i"], "async": ["async_device"]}, - } - } - dummy_scan.status_message.info = { - "readout_priority": {"monitored": ["bpm4i"], "async": ["async_device"]}, - "scan_report_devices": ["samx"], - } - return dummy_scan - - -def inject_scan_history(widget, scan_history_factory, *history_args): - """ - Helper to inject scan history messages into client history. - """ - history_msgs = [] - for scan_id, scan_number in history_args: - history_msgs.append(scan_history_factory(scan_id=scan_id, scan_number=scan_number)) - widget.client.history = ScanHistory(widget.client, False) - for msg in history_msgs: - widget.client.history._scan_data[msg.scan_id] = msg - widget.client.history._scan_ids.append(msg.scan_id) - widget.client.queue.scan_storage.current_scan = None - return history_msgs diff --git a/tests/unit_tests/test_axis_settings.py b/tests/unit_tests/test_axis_settings.py index f84dfac8..46061e47 100644 --- a/tests/unit_tests/test_axis_settings.py +++ b/tests/unit_tests/test_axis_settings.py @@ -1,9 +1,9 @@ import pytest from qtpy.QtWidgets import QDoubleSpinBox, QLineEdit +from bec_widgets.tests.utils import create_widget from bec_widgets.widgets.plots.plot_base import PlotBase from bec_widgets.widgets.plots.setting_menus.axis_settings import AxisSettings -from tests.unit_tests.conftest import create_widget @pytest.fixture diff --git a/tests/unit_tests/test_bec_connector.py b/tests/unit_tests/test_bec_connector.py index c7260500..96d71a41 100644 --- a/tests/unit_tests/test_bec_connector.py +++ b/tests/unit_tests/test_bec_connector.py @@ -132,7 +132,7 @@ def test_bec_connector_change_object_name(bec_connector): assert not any(obj.objectName() == previous_name for obj in all_objects) -def test_bec_connector_export_settings(): +def test_bec_connector_export_settings(mocked_client): class MyWidget(BECConnector, QWidget): def __init__(self, parent=None, client=None, **kwargs): diff --git a/tests/unit_tests/test_busy_loader.py b/tests/unit_tests/test_busy_loader.py index 67faa8dc..b8c92967 100644 --- a/tests/unit_tests/test_busy_loader.py +++ b/tests/unit_tests/test_busy_loader.py @@ -27,7 +27,7 @@ def widget_busy(qtbot, mocked_client): @pytest.fixture -def widget_idle(qtbot): +def widget_idle(qtbot, mocked_client): w = _TestBusyWidget(client=mocked_client, start_busy=False) qtbot.addWidget(w) w.resize(320, 200) diff --git a/tests/unit_tests/test_color_button_native.py b/tests/unit_tests/test_color_button_native.py index a3654668..569016d2 100644 --- a/tests/unit_tests/test_color_button_native.py +++ b/tests/unit_tests/test_color_button_native.py @@ -2,12 +2,11 @@ from qtpy.QtCore import Qt from qtpy.QtGui import QColor from qtpy.QtWidgets import QColorDialog +from bec_widgets.tests.utils import create_widget from bec_widgets.widgets.utility.visual.color_button_native.color_button_native import ( ColorButtonNative, ) -from .conftest import create_widget - def test_color_button_native(qtbot): cb = create_widget(qtbot, ColorButtonNative) diff --git a/tests/unit_tests/test_color_utils.py b/tests/unit_tests/test_color_utils.py index 9dc77426..e1499e7c 100644 --- a/tests/unit_tests/test_color_utils.py +++ b/tests/unit_tests/test_color_utils.py @@ -4,11 +4,11 @@ from pydantic import ValidationError from qtpy.QtGui import QColor from qtpy.QtWidgets import QVBoxLayout, QWidget +from bec_widgets.tests.utils import create_widget from bec_widgets.utils import Colors, ConnectionConfig from bec_widgets.utils.bec_widget import BECWidget from bec_widgets.utils.colors import apply_theme from bec_widgets.widgets.plots.waveform.curve import CurveConfig -from tests.unit_tests.conftest import create_widget def test_color_validation_CSS(): diff --git a/tests/unit_tests/test_crosshair.py b/tests/unit_tests/test_crosshair.py index 7792aa6b..75fc14de 100644 --- a/tests/unit_tests/test_crosshair.py +++ b/tests/unit_tests/test_crosshair.py @@ -4,12 +4,11 @@ import pytest from qtpy.QtCore import QPointF, Qt from qtpy.QtGui import QTransform +from bec_widgets.tests.utils import create_widget from bec_widgets.utils import Crosshair from bec_widgets.widgets.plots.image.image_item import ImageItem from bec_widgets.widgets.plots.waveform.waveform import Waveform -from .conftest import create_widget - # pylint: disable = redefined-outer-name diff --git a/tests/unit_tests/test_curve_settings.py b/tests/unit_tests/test_curve_settings.py index e3753b38..ae699a7e 100644 --- a/tests/unit_tests/test_curve_settings.py +++ b/tests/unit_tests/test_curve_settings.py @@ -6,13 +6,13 @@ from bec_lib.scan_history import ScanHistory from qtpy.QtGui import QValidator from qtpy.QtWidgets import QComboBox, QVBoxLayout +from bec_widgets.tests.utils import create_widget from bec_widgets.widgets.plots.waveform.settings.curve_settings.curve_setting import CurveSetting from bec_widgets.widgets.plots.waveform.settings.curve_settings.curve_tree import ( CurveTree, ScanIndexValidator, ) from bec_widgets.widgets.plots.waveform.waveform import Waveform -from tests.unit_tests.conftest import create_widget ################################################## # CurveSetting diff --git a/tests/unit_tests/test_dap_combobox.py b/tests/unit_tests/test_dap_combobox.py index e469837e..ee0ab987 100644 --- a/tests/unit_tests/test_dap_combobox.py +++ b/tests/unit_tests/test_dap_combobox.py @@ -1,9 +1,8 @@ import pytest +from bec_widgets.tests.utils import create_widget from bec_widgets.widgets.dap.dap_combo_box.dap_combo_box import DapComboBox -from .conftest import create_widget - @pytest.fixture(scope="function") def dap_combobox(qtbot, mocked_client): diff --git a/tests/unit_tests/test_device_browser.py b/tests/unit_tests/test_device_browser.py index 6c1abb73..96adbb99 100644 --- a/tests/unit_tests/test_device_browser.py +++ b/tests/unit_tests/test_device_browser.py @@ -27,8 +27,8 @@ if TYPE_CHECKING: # pragma: no cover @pytest.fixture -def device_browser(qtbot, mocked_client): - dev_browser = DeviceBrowser(client=mocked_client) +def device_browser(qtbot, mock_client_w_devices): + dev_browser = DeviceBrowser(client=mock_client_w_devices) dev_browser.dev["samx"].read_configuration = mock.MagicMock() qtbot.addWidget(dev_browser) qtbot.waitExposed(dev_browser) @@ -146,8 +146,8 @@ def test_device_deletion(device_browser, qtbot): qtbot.waitUntil(lambda: widget.device not in device_browser.dev_list._item_dict, timeout=10000) -def test_signal_display(mocked_client, qtbot): - signal_display = SignalDisplay(client=mocked_client, device="test_device") +def test_signal_display(mock_client_w_devices, qtbot): + signal_display = SignalDisplay(client=mock_client_w_devices, device="test_device") qtbot.addWidget(signal_display) device_mock = mock.MagicMock() signal_display.dev = {"test_device": device_mock} @@ -156,10 +156,10 @@ def test_signal_display(mocked_client, qtbot): device_mock.read_configuration.assert_called() -def test_signal_display_no_device(mocked_client, qtbot): +def test_signal_display_no_device(mock_client_w_devices, qtbot): device_mock = mock.MagicMock() - mocked_client.device_manager.devices = {"test_device_1": device_mock} - signal_display = SignalDisplay(client=mocked_client, device="test_device_2") + mock_client_w_devices.device_manager.devices = {"test_device_1": device_mock} + signal_display = SignalDisplay(client=mock_client_w_devices, device="test_device_2") qtbot.addWidget(signal_display) assert ( signal_display._content_layout.itemAt(1).widget().text() @@ -170,11 +170,11 @@ def test_signal_display_no_device(mocked_client, qtbot): device_mock.read_configuration.assert_not_called() -def test_signal_display_omitted_not_added(mocked_client, qtbot): +def test_signal_display_omitted_not_added(mock_client_w_devices, qtbot): device_mock = mock.MagicMock(spec=Device) device_mock._info = {"signals": {"signal_1": {"kind_str": "omitted"}}} - signal_display = SignalDisplay(client=mocked_client, device="test_device_1") + signal_display = SignalDisplay(client=mock_client_w_devices, device="test_device_1") signal_display.dev = {"test_device_1": device_mock} signal_display._populate() diff --git a/tests/unit_tests/test_device_input_base.py b/tests/unit_tests/test_device_input_base.py index 8cf4a808..a0c38dbf 100644 --- a/tests/unit_tests/test_device_input_base.py +++ b/tests/unit_tests/test_device_input_base.py @@ -4,6 +4,7 @@ import pytest from bec_lib.device import ReadoutPriority from qtpy.QtWidgets import QWidget +from bec_widgets.tests.utils import create_widget from bec_widgets.widgets.control.device_input.base_classes.device_input_base import ( BECDeviceFilter, DeviceInputBase, @@ -11,8 +12,6 @@ from bec_widgets.widgets.control.device_input.base_classes.device_input_base imp ) from bec_widgets.widgets.control.device_input.device_combobox.device_combobox import DeviceComboBox -from .conftest import create_widget - # DeviceInputBase is meant to be mixed in a QWidget class DeviceInputWidget(DeviceInputBase, QWidget): diff --git a/tests/unit_tests/test_device_input_widgets.py b/tests/unit_tests/test_device_input_widgets.py index 94bf6423..9cc5ee38 100644 --- a/tests/unit_tests/test_device_input_widgets.py +++ b/tests/unit_tests/test_device_input_widgets.py @@ -9,17 +9,17 @@ from bec_widgets.widgets.control.device_input.device_line_edit.device_line_edit @pytest.fixture -def device_input_combobox(qtbot, mocked_client): - widget = DeviceComboBox(client=mocked_client) +def device_input_combobox(qtbot, mock_client_w_devices): + widget = DeviceComboBox(client=mock_client_w_devices) qtbot.addWidget(widget) qtbot.waitExposed(widget) yield widget @pytest.fixture -def device_input_combobox_with_kwargs(qtbot, mocked_client): +def device_input_combobox_with_kwargs(qtbot, mock_client_w_devices): widget = DeviceComboBox( - client=mocked_client, + client=mock_client_w_devices, gui_id="test_gui_id", device_filter=[BECDeviceFilter.POSITIONER], default="samx", @@ -72,17 +72,17 @@ def test_get_device_from_input_combobox_init(device_input_combobox): @pytest.fixture -def device_input_line_edit(qtbot, mocked_client): - widget = DeviceLineEdit(client=mocked_client) +def device_input_line_edit(qtbot, mock_client_w_devices): + widget = DeviceLineEdit(client=mock_client_w_devices) qtbot.addWidget(widget) qtbot.waitExposed(widget) yield widget @pytest.fixture -def device_input_line_edit_with_kwargs(qtbot, mocked_client): +def device_input_line_edit_with_kwargs(qtbot, mock_client_w_devices): widget = DeviceLineEdit( - client=mocked_client, + client=mock_client_w_devices, gui_id="test_gui_id", device_filter=[BECDeviceFilter.POSITIONER], default="samx", diff --git a/tests/unit_tests/test_device_manager_components.py b/tests/unit_tests/test_device_manager_components.py index c5057cf4..adf0fc56 100644 --- a/tests/unit_tests/test_device_manager_components.py +++ b/tests/unit_tests/test_device_manager_components.py @@ -56,6 +56,7 @@ from bec_widgets.widgets.control.device_manager.components.ophyd_validation.vali ValidationListItem, ) from bec_widgets.widgets.utility.toggle.toggle import ToggleSwitch +from tests.unit_tests.conftest import mocked_client class TestConstants: @@ -362,7 +363,7 @@ class TestDeviceTable: assert hasattr(device_table, "client_callback_id") def test_device_table_client_device_update_callback( - self, device_table: DeviceTable, mocked_client, qtbot + self, device_table: DeviceTable, mock_client_w_devices, qtbot ): """ Test that runs the client device update callback. This should update the status of devices in the table @@ -373,6 +374,7 @@ class TestDeviceTable: device from the client and run the callback. The table should update the status of the removed device to CAN_CONNECT and all others to CONNECTED. """ + mocked_client = mock_client_w_devices device_configs_changed_calls = [] requested_update_for_multiple_device_validations = [] diff --git a/tests/unit_tests/test_device_signal_input.py b/tests/unit_tests/test_device_signal_input.py index af4da830..b34f868b 100644 --- a/tests/unit_tests/test_device_signal_input.py +++ b/tests/unit_tests/test_device_signal_input.py @@ -4,6 +4,7 @@ import pytest from bec_lib.device import Signal from qtpy.QtWidgets import QWidget +from bec_widgets.tests.utils import create_widget from bec_widgets.utils.ophyd_kind_util import Kind from bec_widgets.widgets.control.device_input.base_classes.device_input_base import BECDeviceFilter from bec_widgets.widgets.control.device_input.base_classes.device_signal_input_base import ( @@ -15,8 +16,6 @@ from bec_widgets.widgets.control.device_input.signal_line_edit.signal_line_edit SignalLineEdit, ) -from .conftest import create_widget - class FakeSignal(Signal): """Fake signal to test the DeviceSignalInputBase.""" diff --git a/tests/unit_tests/test_filter_io.py b/tests/unit_tests/test_filter_io.py index 70f6c3cd..de301ed6 100644 --- a/tests/unit_tests/test_filter_io.py +++ b/tests/unit_tests/test_filter_io.py @@ -1,13 +1,12 @@ import pytest +from bec_widgets.tests.utils import create_widget from bec_widgets.utils.filter_io import FilterIO from bec_widgets.widgets.control.device_input.device_line_edit.device_line_edit import ( DeviceLineEdit, ) from bec_widgets.widgets.dap.dap_combo_box.dap_combo_box import DapComboBox -from .conftest import create_widget - @pytest.fixture(scope="function") def dap_mock(qtbot, mocked_client): diff --git a/tests/unit_tests/test_image_roi_tree.py b/tests/unit_tests/test_image_roi_tree.py index 30970ede..6f590a58 100644 --- a/tests/unit_tests/test_image_roi_tree.py +++ b/tests/unit_tests/test_image_roi_tree.py @@ -4,10 +4,10 @@ import numpy as np import pytest from qtpy.QtCore import QPointF, Qt +from bec_widgets.tests.utils import create_widget from bec_widgets.widgets.plots.image.image import Image from bec_widgets.widgets.plots.image.setting_widgets.image_roi_tree import ROIPropertyTree from bec_widgets.widgets.plots.roi.image_roi import CircularROI, RectangularROI -from tests.unit_tests.conftest import create_widget @pytest.fixture diff --git a/tests/unit_tests/test_image_rois.py b/tests/unit_tests/test_image_rois.py index 90e3b562..a651add9 100644 --- a/tests/unit_tests/test_image_rois.py +++ b/tests/unit_tests/test_image_rois.py @@ -5,6 +5,7 @@ from typing import Literal import numpy as np import pytest +from bec_widgets.tests.utils import create_widget from bec_widgets.widgets.plots.image.image import Image from bec_widgets.widgets.plots.roi.image_roi import ( CircularROI, @@ -12,7 +13,6 @@ from bec_widgets.widgets.plots.roi.image_roi import ( RectangularROI, ROIController, ) -from tests.unit_tests.conftest import create_widget @pytest.fixture(params=["rect", "circle", "ellipse"]) diff --git a/tests/unit_tests/test_image_view_next_gen.py b/tests/unit_tests/test_image_view_next_gen.py index ebfc4503..e3847dc8 100644 --- a/tests/unit_tests/test_image_view_next_gen.py +++ b/tests/unit_tests/test_image_view_next_gen.py @@ -4,8 +4,8 @@ import pytest from bec_lib.endpoints import MessageEndpoints from qtpy.QtCore import QPointF +from bec_widgets.tests.utils import create_widget from bec_widgets.widgets.plots.image.image import Image -from tests.unit_tests.conftest import create_widget ################################################## # Image widget base functionality tests diff --git a/tests/unit_tests/test_lmfit_dialog.py b/tests/unit_tests/test_lmfit_dialog.py index c21dbf91..5997d1a8 100644 --- a/tests/unit_tests/test_lmfit_dialog.py +++ b/tests/unit_tests/test_lmfit_dialog.py @@ -3,10 +3,9 @@ from unittest import mock import numpy as np import pytest +from bec_widgets.tests.utils import create_widget from bec_widgets.widgets.dap.lmfit_dialog.lmfit_dialog import LMFitDialog -from .conftest import create_widget - @pytest.fixture(scope="function") def lmfit_dialog(qtbot, mocked_client): diff --git a/tests/unit_tests/test_main_widnow.py b/tests/unit_tests/test_main_widnow.py index 7dac6482..f466eb35 100644 --- a/tests/unit_tests/test_main_widnow.py +++ b/tests/unit_tests/test_main_widnow.py @@ -5,6 +5,7 @@ from qtpy.QtCore import QEvent, QPoint, QPointF from qtpy.QtGui import QEnterEvent from qtpy.QtWidgets import QApplication, QFrame, QLabel +from bec_widgets.tests.utils import create_widget from bec_widgets.widgets.containers.main_window.addons.hover_widget import ( HoverWidget, WidgetTooltip, @@ -13,8 +14,6 @@ from bec_widgets.widgets.containers.main_window.addons.scroll_label import Scrol from bec_widgets.widgets.containers.main_window.addons.web_links import BECWebLinksMixin from bec_widgets.widgets.containers.main_window.main_window import BECMainWindow -from .conftest import create_widget - @pytest.fixture def bec_main_window(qtbot, mocked_client): diff --git a/tests/unit_tests/test_motor_map_next_gen.py b/tests/unit_tests/test_motor_map_next_gen.py index 918e66ea..123cf036 100644 --- a/tests/unit_tests/test_motor_map_next_gen.py +++ b/tests/unit_tests/test_motor_map_next_gen.py @@ -1,9 +1,8 @@ from qtpy.QtTest import QSignalSpy +from bec_widgets.tests.utils import create_widget from bec_widgets.widgets.plots.motor_map.motor_map import MotorMap -from .conftest import create_widget - def test_motor_map_initialization(qtbot, mocked_client): """Test the initialization of the MotorMap widget.""" diff --git a/tests/unit_tests/test_multi_waveform_next_gen.py b/tests/unit_tests/test_multi_waveform_next_gen.py index 2883995b..9b934831 100644 --- a/tests/unit_tests/test_multi_waveform_next_gen.py +++ b/tests/unit_tests/test_multi_waveform_next_gen.py @@ -1,9 +1,8 @@ import numpy as np +from bec_widgets.tests.utils import create_widget from bec_widgets.widgets.plots.multi_waveform.multi_waveform import MultiWaveform -from .conftest import create_widget - ################################################## # MultiWaveform widget base functionality tests ################################################## diff --git a/tests/unit_tests/test_plot_base_next_gen.py b/tests/unit_tests/test_plot_base_next_gen.py index a81f68f3..e24bd187 100644 --- a/tests/unit_tests/test_plot_base_next_gen.py +++ b/tests/unit_tests/test_plot_base_next_gen.py @@ -1,9 +1,8 @@ import numpy as np +from bec_widgets.tests.utils import create_widget from bec_widgets.widgets.plots.plot_base import PlotBase, UIMode -from .conftest import create_widget - # pylint: disable=unused-import # pylint: disable=missing-function-docstring # pylint: disable=redefined-outer-name diff --git a/tests/unit_tests/test_positioner_box.py b/tests/unit_tests/test_positioner_box.py index e6bff8f6..d5674b79 100644 --- a/tests/unit_tests/test_positioner_box.py +++ b/tests/unit_tests/test_positioner_box.py @@ -7,7 +7,7 @@ from qtpy.QtCore import Qt, QTimer from qtpy.QtGui import QValidator from qtpy.QtWidgets import QPushButton -from bec_widgets.tests.utils import Positioner +from bec_widgets.tests.utils import Positioner, create_widget from bec_widgets.widgets.control.device_control.positioner_box import ( PositionerBox, PositionerControlLine, @@ -16,8 +16,6 @@ from bec_widgets.widgets.control.device_input.device_line_edit.device_line_edit DeviceLineEdit, ) -from .conftest import create_widget - class PositionerWithoutPrecision(Positioner): """just placeholder for testing embedded isinstance check in DeviceCombobox""" diff --git a/tests/unit_tests/test_positioner_box_2d.py b/tests/unit_tests/test_positioner_box_2d.py index c570e62a..eeed7321 100644 --- a/tests/unit_tests/test_positioner_box_2d.py +++ b/tests/unit_tests/test_positioner_box_2d.py @@ -2,10 +2,9 @@ from unittest import mock import pytest +from bec_widgets.tests.utils import create_widget from bec_widgets.widgets.control.device_control.positioner_box import PositionerBox2D -from .conftest import create_widget - @pytest.fixture def positioner_box_2d(qtbot, mocked_client): diff --git a/tests/unit_tests/test_scatter_waveform.py b/tests/unit_tests/test_scatter_waveform.py index 445aeb52..318112c4 100644 --- a/tests/unit_tests/test_scatter_waveform.py +++ b/tests/unit_tests/test_scatter_waveform.py @@ -2,6 +2,7 @@ from unittest.mock import MagicMock, patch import numpy as np +from bec_widgets.tests.utils import create_widget from bec_widgets.widgets.plots.scatter_waveform.scatter_curve import ( ScatterCurveConfig, ScatterDeviceSignal, @@ -11,8 +12,6 @@ from bec_widgets.widgets.plots.scatter_waveform.settings.scatter_curve_setting i ScatterCurveSettings, ) -from .conftest import create_widget - def test_waveform_initialization(qtbot, mocked_client): """ diff --git a/tests/unit_tests/test_utils_bec_signal_proxy.py b/tests/unit_tests/test_utils_bec_signal_proxy.py index 59140b49..e9031e0a 100644 --- a/tests/unit_tests/test_utils_bec_signal_proxy.py +++ b/tests/unit_tests/test_utils_bec_signal_proxy.py @@ -3,11 +3,10 @@ from unittest import mock import pyqtgraph as pg import pytest +from bec_widgets.tests.utils import create_widget from bec_widgets.utils.bec_signal_proxy import BECSignalProxy from bec_widgets.widgets.dap.dap_combo_box.dap_combo_box import DapComboBox -from .conftest import create_widget - @pytest.fixture def dap_combo_box(qtbot, mocked_client): diff --git a/tests/unit_tests/test_waveform.py b/tests/unit_tests/test_waveform.py index 240c3e7a..59bd2167 100644 --- a/tests/unit_tests/test_waveform.py +++ b/tests/unit_tests/test_waveform.py @@ -12,6 +12,7 @@ from pyqtgraph.graphicsItems.DateAxisItem import DateAxisItem from qtpy.QtCore import QTimer from qtpy.QtWidgets import QApplication, QCheckBox, QDialog, QDialogButtonBox, QDoubleSpinBox +from bec_widgets.tests.utils import create_widget from bec_widgets.widgets.plots.plot_base import UIMode from bec_widgets.widgets.plots.waveform.curve import DeviceSignal from bec_widgets.widgets.plots.waveform.waveform import Waveform @@ -19,8 +20,6 @@ from bec_widgets.widgets.services.scan_history_browser.scan_history_browser impo ScanHistoryBrowser, ) -from .conftest import create_widget - # pylint: disable=unexpected-keyword-arg ################################################## diff --git a/tests/unit_tests/test_widget_finder.py b/tests/unit_tests/test_widget_finder.py index 1dc6a1ba..fe572144 100644 --- a/tests/unit_tests/test_widget_finder.py +++ b/tests/unit_tests/test_widget_finder.py @@ -2,8 +2,8 @@ import pytest from qtpy.QtCore import QPoint, QSize, Qt from qtpy.QtWidgets import QLabel, QPushButton, QVBoxLayout, QWidget +from bec_widgets.tests.utils import create_widget from bec_widgets.widgets.utility.widget_finder.widget_finder import WidgetFinderComboBox -from tests.unit_tests.conftest import create_widget @pytest.fixture