This commit is contained in:
2026-02-05 11:42:19 +01:00
parent 1b9a56f4d5
commit a94eaede46
30 changed files with 216 additions and 215 deletions
+162
View File
@@ -1,11 +1,19 @@
# pylint: skip-file # pylint: skip-file
import json
import time
from unittest.mock import MagicMock 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.config_helper import ConfigHelper
from bec_lib.device import Device as BECDevice from bec_lib.device import Device as BECDevice
from bec_lib.device import Positioner as BECPositioner from bec_lib.device import Positioner as BECPositioner
from bec_lib.device import ReadoutPriority from bec_lib.device import ReadoutPriority
from bec_lib.devicemanager import DeviceContainer 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): class FakeDevice(BECDevice):
@@ -308,3 +316,157 @@ def check_remote_data_size(widget, plot_name, num_elements):
Used in the qtbot.waitUntil function. Used in the qtbot.waitUntil function.
""" """
return len(widget.get_all_data()[plot_name]["x"]) == num_elements 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)
+9 -155
View File
@@ -21,7 +21,14 @@ from qtpy.QtCore import QEvent, QEventLoop
from qtpy.QtWidgets import QApplication, QMessageBox from qtpy.QtWidgets import QApplication, QMessageBox
from bec_widgets.cli.rpc.rpc_register import RPCRegister 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 bec_dispatcher as bec_dispatcher_module
from bec_widgets.utils import error_popups from bec_widgets.utils import error_popups
from bec_widgets.utils.bec_dispatcher import QtRedisConnector from bec_widgets.utils.bec_dispatcher import QtRedisConnector
@@ -40,11 +47,6 @@ def pytest_runtest_makereport(item, call):
item.stash["failed"] = rep.failed 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) @pytest.fixture(autouse=True)
def qapplication(qtbot, request, testable_qtimer_class): # pylint: disable=unused-argument def qapplication(qtbot, request, testable_qtimer_class): # pylint: disable=unused-argument
qapp = QApplication.instance() qapp = QApplication.instance()
@@ -134,103 +136,6 @@ def suppress_message_box(monkeypatch):
monkeypatch.setattr(QMessageBox, "exec_", lambda *args, **kwargs: QMessageBox.Ok) 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 @pytest.fixture
def grid_scan_history_msg(tmpdir): def grid_scan_history_msg(tmpdir):
x_grid, y_grid = np.meshgrid(np.linspace(-5, 5, 10), np.linspace(-5, 5, 10)) 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") @pytest.fixture(scope="function")
def mock_client_w_devices(mocked_client): def mock_client_w_devices(mocked_client):
mocked_client.device_manager.add_devices(DEVICES) 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 mocked_client.dap._available_dap_plugins = patched_models
yield mocked_client 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
+1 -1
View File
@@ -1,9 +1,9 @@
import pytest import pytest
from qtpy.QtWidgets import QDoubleSpinBox, QLineEdit 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.plot_base import PlotBase
from bec_widgets.widgets.plots.setting_menus.axis_settings import AxisSettings from bec_widgets.widgets.plots.setting_menus.axis_settings import AxisSettings
from tests.unit_tests.conftest import create_widget
@pytest.fixture @pytest.fixture
+1 -1
View File
@@ -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) 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): class MyWidget(BECConnector, QWidget):
def __init__(self, parent=None, client=None, **kwargs): def __init__(self, parent=None, client=None, **kwargs):
+1 -1
View File
@@ -27,7 +27,7 @@ def widget_busy(qtbot, mocked_client):
@pytest.fixture @pytest.fixture
def widget_idle(qtbot): def widget_idle(qtbot, mocked_client):
w = _TestBusyWidget(client=mocked_client, start_busy=False) w = _TestBusyWidget(client=mocked_client, start_busy=False)
qtbot.addWidget(w) qtbot.addWidget(w)
w.resize(320, 200) w.resize(320, 200)
+1 -2
View File
@@ -2,12 +2,11 @@ from qtpy.QtCore import Qt
from qtpy.QtGui import QColor from qtpy.QtGui import QColor
from qtpy.QtWidgets import QColorDialog 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 ( from bec_widgets.widgets.utility.visual.color_button_native.color_button_native import (
ColorButtonNative, ColorButtonNative,
) )
from .conftest import create_widget
def test_color_button_native(qtbot): def test_color_button_native(qtbot):
cb = create_widget(qtbot, ColorButtonNative) cb = create_widget(qtbot, ColorButtonNative)
+1 -1
View File
@@ -4,11 +4,11 @@ from pydantic import ValidationError
from qtpy.QtGui import QColor from qtpy.QtGui import QColor
from qtpy.QtWidgets import QVBoxLayout, QWidget 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 import Colors, ConnectionConfig
from bec_widgets.utils.bec_widget import BECWidget from bec_widgets.utils.bec_widget import BECWidget
from bec_widgets.utils.colors import apply_theme from bec_widgets.utils.colors import apply_theme
from bec_widgets.widgets.plots.waveform.curve import CurveConfig from bec_widgets.widgets.plots.waveform.curve import CurveConfig
from tests.unit_tests.conftest import create_widget
def test_color_validation_CSS(): def test_color_validation_CSS():
+1 -2
View File
@@ -4,12 +4,11 @@ import pytest
from qtpy.QtCore import QPointF, Qt from qtpy.QtCore import QPointF, Qt
from qtpy.QtGui import QTransform from qtpy.QtGui import QTransform
from bec_widgets.tests.utils import create_widget
from bec_widgets.utils import Crosshair from bec_widgets.utils import Crosshair
from bec_widgets.widgets.plots.image.image_item import ImageItem from bec_widgets.widgets.plots.image.image_item import ImageItem
from bec_widgets.widgets.plots.waveform.waveform import Waveform from bec_widgets.widgets.plots.waveform.waveform import Waveform
from .conftest import create_widget
# pylint: disable = redefined-outer-name # pylint: disable = redefined-outer-name
+1 -1
View File
@@ -6,13 +6,13 @@ from bec_lib.scan_history import ScanHistory
from qtpy.QtGui import QValidator from qtpy.QtGui import QValidator
from qtpy.QtWidgets import QComboBox, QVBoxLayout 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_setting import CurveSetting
from bec_widgets.widgets.plots.waveform.settings.curve_settings.curve_tree import ( from bec_widgets.widgets.plots.waveform.settings.curve_settings.curve_tree import (
CurveTree, CurveTree,
ScanIndexValidator, ScanIndexValidator,
) )
from bec_widgets.widgets.plots.waveform.waveform import Waveform from bec_widgets.widgets.plots.waveform.waveform import Waveform
from tests.unit_tests.conftest import create_widget
################################################## ##################################################
# CurveSetting # CurveSetting
+1 -2
View File
@@ -1,9 +1,8 @@
import pytest import pytest
from bec_widgets.tests.utils import create_widget
from bec_widgets.widgets.dap.dap_combo_box.dap_combo_box import DapComboBox from bec_widgets.widgets.dap.dap_combo_box.dap_combo_box import DapComboBox
from .conftest import create_widget
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def dap_combobox(qtbot, mocked_client): def dap_combobox(qtbot, mocked_client):
+9 -9
View File
@@ -27,8 +27,8 @@ if TYPE_CHECKING: # pragma: no cover
@pytest.fixture @pytest.fixture
def device_browser(qtbot, mocked_client): def device_browser(qtbot, mock_client_w_devices):
dev_browser = DeviceBrowser(client=mocked_client) dev_browser = DeviceBrowser(client=mock_client_w_devices)
dev_browser.dev["samx"].read_configuration = mock.MagicMock() dev_browser.dev["samx"].read_configuration = mock.MagicMock()
qtbot.addWidget(dev_browser) qtbot.addWidget(dev_browser)
qtbot.waitExposed(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) qtbot.waitUntil(lambda: widget.device not in device_browser.dev_list._item_dict, timeout=10000)
def test_signal_display(mocked_client, qtbot): def test_signal_display(mock_client_w_devices, qtbot):
signal_display = SignalDisplay(client=mocked_client, device="test_device") signal_display = SignalDisplay(client=mock_client_w_devices, device="test_device")
qtbot.addWidget(signal_display) qtbot.addWidget(signal_display)
device_mock = mock.MagicMock() device_mock = mock.MagicMock()
signal_display.dev = {"test_device": device_mock} signal_display.dev = {"test_device": device_mock}
@@ -156,10 +156,10 @@ def test_signal_display(mocked_client, qtbot):
device_mock.read_configuration.assert_called() 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() device_mock = mock.MagicMock()
mocked_client.device_manager.devices = {"test_device_1": device_mock} mock_client_w_devices.device_manager.devices = {"test_device_1": device_mock}
signal_display = SignalDisplay(client=mocked_client, device="test_device_2") signal_display = SignalDisplay(client=mock_client_w_devices, device="test_device_2")
qtbot.addWidget(signal_display) qtbot.addWidget(signal_display)
assert ( assert (
signal_display._content_layout.itemAt(1).widget().text() 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() 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 = mock.MagicMock(spec=Device)
device_mock._info = {"signals": {"signal_1": {"kind_str": "omitted"}}} 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.dev = {"test_device_1": device_mock}
signal_display._populate() signal_display._populate()
+1 -2
View File
@@ -4,6 +4,7 @@ import pytest
from bec_lib.device import ReadoutPriority from bec_lib.device import ReadoutPriority
from qtpy.QtWidgets import QWidget 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 ( from bec_widgets.widgets.control.device_input.base_classes.device_input_base import (
BECDeviceFilter, BECDeviceFilter,
DeviceInputBase, 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 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 # DeviceInputBase is meant to be mixed in a QWidget
class DeviceInputWidget(DeviceInputBase, QWidget): class DeviceInputWidget(DeviceInputBase, QWidget):
@@ -9,17 +9,17 @@ from bec_widgets.widgets.control.device_input.device_line_edit.device_line_edit
@pytest.fixture @pytest.fixture
def device_input_combobox(qtbot, mocked_client): def device_input_combobox(qtbot, mock_client_w_devices):
widget = DeviceComboBox(client=mocked_client) widget = DeviceComboBox(client=mock_client_w_devices)
qtbot.addWidget(widget) qtbot.addWidget(widget)
qtbot.waitExposed(widget) qtbot.waitExposed(widget)
yield widget yield widget
@pytest.fixture @pytest.fixture
def device_input_combobox_with_kwargs(qtbot, mocked_client): def device_input_combobox_with_kwargs(qtbot, mock_client_w_devices):
widget = DeviceComboBox( widget = DeviceComboBox(
client=mocked_client, client=mock_client_w_devices,
gui_id="test_gui_id", gui_id="test_gui_id",
device_filter=[BECDeviceFilter.POSITIONER], device_filter=[BECDeviceFilter.POSITIONER],
default="samx", default="samx",
@@ -72,17 +72,17 @@ def test_get_device_from_input_combobox_init(device_input_combobox):
@pytest.fixture @pytest.fixture
def device_input_line_edit(qtbot, mocked_client): def device_input_line_edit(qtbot, mock_client_w_devices):
widget = DeviceLineEdit(client=mocked_client) widget = DeviceLineEdit(client=mock_client_w_devices)
qtbot.addWidget(widget) qtbot.addWidget(widget)
qtbot.waitExposed(widget) qtbot.waitExposed(widget)
yield widget yield widget
@pytest.fixture @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( widget = DeviceLineEdit(
client=mocked_client, client=mock_client_w_devices,
gui_id="test_gui_id", gui_id="test_gui_id",
device_filter=[BECDeviceFilter.POSITIONER], device_filter=[BECDeviceFilter.POSITIONER],
default="samx", default="samx",
@@ -56,6 +56,7 @@ from bec_widgets.widgets.control.device_manager.components.ophyd_validation.vali
ValidationListItem, ValidationListItem,
) )
from bec_widgets.widgets.utility.toggle.toggle import ToggleSwitch from bec_widgets.widgets.utility.toggle.toggle import ToggleSwitch
from tests.unit_tests.conftest import mocked_client
class TestConstants: class TestConstants:
@@ -362,7 +363,7 @@ class TestDeviceTable:
assert hasattr(device_table, "client_callback_id") assert hasattr(device_table, "client_callback_id")
def test_device_table_client_device_update_callback( 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 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 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. removed device to CAN_CONNECT and all others to CONNECTED.
""" """
mocked_client = mock_client_w_devices
device_configs_changed_calls = [] device_configs_changed_calls = []
requested_update_for_multiple_device_validations = [] requested_update_for_multiple_device_validations = []
+1 -2
View File
@@ -4,6 +4,7 @@ import pytest
from bec_lib.device import Signal from bec_lib.device import Signal
from qtpy.QtWidgets import QWidget 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.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_input_base import BECDeviceFilter
from bec_widgets.widgets.control.device_input.base_classes.device_signal_input_base import ( 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, SignalLineEdit,
) )
from .conftest import create_widget
class FakeSignal(Signal): class FakeSignal(Signal):
"""Fake signal to test the DeviceSignalInputBase.""" """Fake signal to test the DeviceSignalInputBase."""
+1 -2
View File
@@ -1,13 +1,12 @@
import pytest import pytest
from bec_widgets.tests.utils import create_widget
from bec_widgets.utils.filter_io import FilterIO from bec_widgets.utils.filter_io import FilterIO
from bec_widgets.widgets.control.device_input.device_line_edit.device_line_edit import ( from bec_widgets.widgets.control.device_input.device_line_edit.device_line_edit import (
DeviceLineEdit, DeviceLineEdit,
) )
from bec_widgets.widgets.dap.dap_combo_box.dap_combo_box import DapComboBox from bec_widgets.widgets.dap.dap_combo_box.dap_combo_box import DapComboBox
from .conftest import create_widget
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def dap_mock(qtbot, mocked_client): def dap_mock(qtbot, mocked_client):
+1 -1
View File
@@ -4,10 +4,10 @@ import numpy as np
import pytest import pytest
from qtpy.QtCore import QPointF, Qt 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.image import Image
from bec_widgets.widgets.plots.image.setting_widgets.image_roi_tree import ROIPropertyTree 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 bec_widgets.widgets.plots.roi.image_roi import CircularROI, RectangularROI
from tests.unit_tests.conftest import create_widget
@pytest.fixture @pytest.fixture
+1 -1
View File
@@ -5,6 +5,7 @@ from typing import Literal
import numpy as np import numpy as np
import pytest import pytest
from bec_widgets.tests.utils import create_widget
from bec_widgets.widgets.plots.image.image import Image from bec_widgets.widgets.plots.image.image import Image
from bec_widgets.widgets.plots.roi.image_roi import ( from bec_widgets.widgets.plots.roi.image_roi import (
CircularROI, CircularROI,
@@ -12,7 +13,6 @@ from bec_widgets.widgets.plots.roi.image_roi import (
RectangularROI, RectangularROI,
ROIController, ROIController,
) )
from tests.unit_tests.conftest import create_widget
@pytest.fixture(params=["rect", "circle", "ellipse"]) @pytest.fixture(params=["rect", "circle", "ellipse"])
+1 -1
View File
@@ -4,8 +4,8 @@ import pytest
from bec_lib.endpoints import MessageEndpoints from bec_lib.endpoints import MessageEndpoints
from qtpy.QtCore import QPointF from qtpy.QtCore import QPointF
from bec_widgets.tests.utils import create_widget
from bec_widgets.widgets.plots.image.image import Image from bec_widgets.widgets.plots.image.image import Image
from tests.unit_tests.conftest import create_widget
################################################## ##################################################
# Image widget base functionality tests # Image widget base functionality tests
+1 -2
View File
@@ -3,10 +3,9 @@ from unittest import mock
import numpy as np import numpy as np
import pytest import pytest
from bec_widgets.tests.utils import create_widget
from bec_widgets.widgets.dap.lmfit_dialog.lmfit_dialog import LMFitDialog from bec_widgets.widgets.dap.lmfit_dialog.lmfit_dialog import LMFitDialog
from .conftest import create_widget
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def lmfit_dialog(qtbot, mocked_client): def lmfit_dialog(qtbot, mocked_client):
+1 -2
View File
@@ -5,6 +5,7 @@ from qtpy.QtCore import QEvent, QPoint, QPointF
from qtpy.QtGui import QEnterEvent from qtpy.QtGui import QEnterEvent
from qtpy.QtWidgets import QApplication, QFrame, QLabel 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 ( from bec_widgets.widgets.containers.main_window.addons.hover_widget import (
HoverWidget, HoverWidget,
WidgetTooltip, 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.addons.web_links import BECWebLinksMixin
from bec_widgets.widgets.containers.main_window.main_window import BECMainWindow from bec_widgets.widgets.containers.main_window.main_window import BECMainWindow
from .conftest import create_widget
@pytest.fixture @pytest.fixture
def bec_main_window(qtbot, mocked_client): def bec_main_window(qtbot, mocked_client):
+1 -2
View File
@@ -1,9 +1,8 @@
from qtpy.QtTest import QSignalSpy 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 bec_widgets.widgets.plots.motor_map.motor_map import MotorMap
from .conftest import create_widget
def test_motor_map_initialization(qtbot, mocked_client): def test_motor_map_initialization(qtbot, mocked_client):
"""Test the initialization of the MotorMap widget.""" """Test the initialization of the MotorMap widget."""
@@ -1,9 +1,8 @@
import numpy as np import numpy as np
from bec_widgets.tests.utils import create_widget
from bec_widgets.widgets.plots.multi_waveform.multi_waveform import MultiWaveform from bec_widgets.widgets.plots.multi_waveform.multi_waveform import MultiWaveform
from .conftest import create_widget
################################################## ##################################################
# MultiWaveform widget base functionality tests # MultiWaveform widget base functionality tests
################################################## ##################################################
+1 -2
View File
@@ -1,9 +1,8 @@
import numpy as np import numpy as np
from bec_widgets.tests.utils import create_widget
from bec_widgets.widgets.plots.plot_base import PlotBase, UIMode from bec_widgets.widgets.plots.plot_base import PlotBase, UIMode
from .conftest import create_widget
# pylint: disable=unused-import # pylint: disable=unused-import
# pylint: disable=missing-function-docstring # pylint: disable=missing-function-docstring
# pylint: disable=redefined-outer-name # pylint: disable=redefined-outer-name
+1 -3
View File
@@ -7,7 +7,7 @@ from qtpy.QtCore import Qt, QTimer
from qtpy.QtGui import QValidator from qtpy.QtGui import QValidator
from qtpy.QtWidgets import QPushButton 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 ( from bec_widgets.widgets.control.device_control.positioner_box import (
PositionerBox, PositionerBox,
PositionerControlLine, PositionerControlLine,
@@ -16,8 +16,6 @@ from bec_widgets.widgets.control.device_input.device_line_edit.device_line_edit
DeviceLineEdit, DeviceLineEdit,
) )
from .conftest import create_widget
class PositionerWithoutPrecision(Positioner): class PositionerWithoutPrecision(Positioner):
"""just placeholder for testing embedded isinstance check in DeviceCombobox""" """just placeholder for testing embedded isinstance check in DeviceCombobox"""
+1 -2
View File
@@ -2,10 +2,9 @@ from unittest import mock
import pytest import pytest
from bec_widgets.tests.utils import create_widget
from bec_widgets.widgets.control.device_control.positioner_box import PositionerBox2D from bec_widgets.widgets.control.device_control.positioner_box import PositionerBox2D
from .conftest import create_widget
@pytest.fixture @pytest.fixture
def positioner_box_2d(qtbot, mocked_client): def positioner_box_2d(qtbot, mocked_client):
+1 -2
View File
@@ -2,6 +2,7 @@ from unittest.mock import MagicMock, patch
import numpy as np import numpy as np
from bec_widgets.tests.utils import create_widget
from bec_widgets.widgets.plots.scatter_waveform.scatter_curve import ( from bec_widgets.widgets.plots.scatter_waveform.scatter_curve import (
ScatterCurveConfig, ScatterCurveConfig,
ScatterDeviceSignal, ScatterDeviceSignal,
@@ -11,8 +12,6 @@ from bec_widgets.widgets.plots.scatter_waveform.settings.scatter_curve_setting i
ScatterCurveSettings, ScatterCurveSettings,
) )
from .conftest import create_widget
def test_waveform_initialization(qtbot, mocked_client): def test_waveform_initialization(qtbot, mocked_client):
""" """
@@ -3,11 +3,10 @@ from unittest import mock
import pyqtgraph as pg import pyqtgraph as pg
import pytest import pytest
from bec_widgets.tests.utils import create_widget
from bec_widgets.utils.bec_signal_proxy import BECSignalProxy from bec_widgets.utils.bec_signal_proxy import BECSignalProxy
from bec_widgets.widgets.dap.dap_combo_box.dap_combo_box import DapComboBox from bec_widgets.widgets.dap.dap_combo_box.dap_combo_box import DapComboBox
from .conftest import create_widget
@pytest.fixture @pytest.fixture
def dap_combo_box(qtbot, mocked_client): def dap_combo_box(qtbot, mocked_client):
+1 -2
View File
@@ -12,6 +12,7 @@ from pyqtgraph.graphicsItems.DateAxisItem import DateAxisItem
from qtpy.QtCore import QTimer from qtpy.QtCore import QTimer
from qtpy.QtWidgets import QApplication, QCheckBox, QDialog, QDialogButtonBox, QDoubleSpinBox 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.plot_base import UIMode
from bec_widgets.widgets.plots.waveform.curve import DeviceSignal from bec_widgets.widgets.plots.waveform.curve import DeviceSignal
from bec_widgets.widgets.plots.waveform.waveform import Waveform 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, ScanHistoryBrowser,
) )
from .conftest import create_widget
# pylint: disable=unexpected-keyword-arg # pylint: disable=unexpected-keyword-arg
################################################## ##################################################
+1 -1
View File
@@ -2,8 +2,8 @@ import pytest
from qtpy.QtCore import QPoint, QSize, Qt from qtpy.QtCore import QPoint, QSize, Qt
from qtpy.QtWidgets import QLabel, QPushButton, QVBoxLayout, QWidget 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 bec_widgets.widgets.utility.widget_finder.widget_finder import WidgetFinderComboBox
from tests.unit_tests.conftest import create_widget
@pytest.fixture @pytest.fixture