0
0
mirror of https://github.com/bec-project/bec_widgets.git synced 2025-07-14 03:31:50 +02:00

fix: compatibility adjustment to .ui loading and tests for PySide6

This commit is contained in:
2024-04-23 23:21:08 +02:00
parent 0fea8d6065
commit 07b99d91a5
19 changed files with 219 additions and 1131 deletions

View File

@ -150,7 +150,7 @@ def test_spiral_bar(rpc_server_dock):
dock = BECDockArea(rpc_server_dock.gui_id)
dock_server = rpc_server_dock.gui
d0 = dock.add_dock("dock_0")
d0 = dock.add_dock(name="dock_0")
bar = d0.add_widget_bec("SpiralProgressBar")
assert bar.__class__.__name__ == "SpiralProgressBar"

View File

@ -17,8 +17,8 @@ def cli_figure():
def test_rpc_call_plot(cli_figure):
fig, mock_rpc_call = cli_figure
fig.plot("samx", "bpm4i")
mock_rpc_call.assert_called_with("plot", "samx", "bpm4i")
fig.plot(x_name="samx", y_name="bpm4i")
mock_rpc_call.assert_called_with("plot", x_name="samx", y_name="bpm4i")
def test_rpc_call_accepts_device_as_input(cli_figure):

View File

@ -44,8 +44,8 @@ def test_mouse_moved_signals(qtbot):
# Create a slot that will store the emitted values as tuples
emitted_values_1D = []
def slot(x, y_values):
emitted_values_1D.append((x, y_values))
def slot(coordinates):
emitted_values_1D.append(coordinates)
# Connect the signal to the custom slot
crosshair.coordinatesChanged1D.connect(slot)
@ -59,7 +59,7 @@ def test_mouse_moved_signals(qtbot):
crosshair.mouse_moved(event_mock)
# Assert the expected behavior
assert emitted_values_1D == [(2.0, [5.0])]
assert emitted_values_1D == [(2, [5])]
def test_mouse_moved_signals_outside(qtbot):
@ -106,8 +106,8 @@ def test_mouse_moved_signals_2D(qtbot):
# Create a slot that will store the emitted values as tuples
emitted_values_2D = []
def slot(x, y):
emitted_values_2D.append((x, y))
def slot(coordinates):
emitted_values_2D.append(coordinates)
# Connect the signal to the custom slot
crosshair.coordinatesChanged2D.connect(slot)

View File

@ -1,115 +0,0 @@
# pylint: disable = no-name-in-module,missing-class-docstring, missing-module-docstring
import json
from unittest.mock import MagicMock, patch
import numpy as np
import pyqtgraph as pg
import pytest
import zmq
from bec_widgets.examples.eiger_plot.eiger_plot import EigerPlot
# Common fixture for all tests
@pytest.fixture
def eiger_plot_instance(qtbot):
widget = EigerPlot()
qtbot.addWidget(widget)
qtbot.waitExposed(widget)
yield widget
widget.close()
@pytest.mark.parametrize(
"fft_checked, rotation_index, transpose_checked, log_checked, expected_image",
[
(False, 0, False, False, np.array([[2, 1], [1, 5]], dtype=float)), # just mask
(False, 1, False, False, np.array([[1, 5], [2, 1]], dtype=float)), # 90 deg rotation
(False, 2, False, False, np.array([[5, 1], [1, 2]], dtype=float)), # 180 deg rotation
(False, 0, True, False, np.array([[2, 1], [1, 5]], dtype=float)), # transposed
(False, 0, False, True, np.array([[0.30103, 0.0], [0.0, 0.69897]], dtype=float)), # log
(True, 0, False, False, np.array([[5.0, 3.0], [3.0, 9.0]], dtype=float)), # FFT
],
)
def test_on_image_update(
qtbot,
eiger_plot_instance,
fft_checked,
rotation_index,
transpose_checked,
log_checked,
expected_image,
):
# Initialize image and mask
eiger_plot_instance.image = np.array([[1, 2], [3, 4]], dtype=float)
eiger_plot_instance.mask = np.array([[0, 1], [1, 0]], dtype=float)
# Mock UI elements
eiger_plot_instance.checkBox_FFT = MagicMock()
eiger_plot_instance.checkBox_FFT.isChecked.return_value = fft_checked
eiger_plot_instance.comboBox_rotation = MagicMock()
eiger_plot_instance.comboBox_rotation.currentIndex.return_value = rotation_index
eiger_plot_instance.checkBox_transpose = MagicMock()
eiger_plot_instance.checkBox_transpose.isChecked.return_value = transpose_checked
eiger_plot_instance.checkBox_log = MagicMock()
eiger_plot_instance.checkBox_log.isChecked.return_value = log_checked
eiger_plot_instance.imageItem = MagicMock()
# Call the method
eiger_plot_instance.on_image_update()
# Validate the transformations
np.testing.assert_array_almost_equal(eiger_plot_instance.image, expected_image, decimal=5)
# Validate that setImage was called
eiger_plot_instance.imageItem.setImage.assert_called_with(
eiger_plot_instance.image, autoLevels=False
)
def test_init_ui(eiger_plot_instance):
assert isinstance(eiger_plot_instance.plot_item, pg.PlotItem)
assert isinstance(eiger_plot_instance.imageItem, pg.ImageItem)
assert isinstance(eiger_plot_instance.hist, pg.HistogramLUTItem)
def test_start_zmq_consumer(eiger_plot_instance):
with patch("threading.Thread") as MockThread:
eiger_plot_instance.start_zmq_consumer()
MockThread.assert_called_once()
MockThread.return_value.start.assert_called_once()
def test_zmq_consumer(eiger_plot_instance, qtbot):
fake_meta = json.dumps({"type": "int32", "shape": (2, 2)}).encode("utf-8")
fake_data = np.array([[1, 2], [3, 4]], dtype="int32").tobytes()
with patch("zmq.Context", autospec=True) as MockContext:
mock_socket = MagicMock()
mock_socket.recv_multipart.side_effect = ((fake_meta, fake_data),)
MockContext.return_value.socket.return_value = mock_socket
# Mocking the update_signal to check if it gets emitted
eiger_plot_instance.update_signal = MagicMock()
with patch("zmq.Poller"):
# will do only 1 iteration of the loop in the thread
eiger_plot_instance._zmq_consumer_exit_event.set()
# Run the method under test
consumer_thread = eiger_plot_instance.start_zmq_consumer()
consumer_thread.join()
# Check if zmq methods are called
# MockContext.assert_called_once()
assert MockContext.call_count == 1
mock_socket.connect.assert_called_with("tcp://129.129.95.38:20000")
mock_socket.setsockopt_string.assert_called_with(zmq.SUBSCRIBE, "")
mock_socket.recv_multipart.assert_called()
# Check if update_signal was emitted
eiger_plot_instance.update_signal.emit.assert_called_once()
# Validate the image data
np.testing.assert_array_equal(
eiger_plot_instance.image, np.array([[1, 2], [3, 4]], dtype="int32")
)

View File

@ -239,14 +239,14 @@ def test_absolute_save_current_coordinates(motor_absolute_widget):
motor_absolute_widget.coordinates_signal.connect(capture_emit)
# Trigger saving current coordinates
motor_absolute_widget.pushButton_save.click()
motor_absolute_widget.ui.pushButton_save.click()
assert emitted_coordinates == [(motor_x_value, motor_y_value)]
def test_absolute_set_absolute_coordinates(motor_absolute_widget):
motor_absolute_widget.spinBox_absolute_x.setValue(5)
motor_absolute_widget.spinBox_absolute_y.setValue(10)
motor_absolute_widget.ui.spinBox_absolute_x.setValue(5)
motor_absolute_widget.ui.spinBox_absolute_y.setValue(10)
# Connect to the coordinates_signal to capture emitted values
emitted_values = []
@ -257,7 +257,7 @@ def test_absolute_set_absolute_coordinates(motor_absolute_widget):
motor_absolute_widget.coordinates_signal.connect(capture_coordinates)
# Simulate button click for absolute movement
motor_absolute_widget.pushButton_set.click()
motor_absolute_widget.ui.pushButton_set.click()
assert emitted_values == [(5, 10)]
@ -265,14 +265,14 @@ def test_absolute_set_absolute_coordinates(motor_absolute_widget):
def test_absolute_go_absolute_coordinates(motor_absolute_widget):
motor_absolute_widget.change_motors("samx", "samy")
motor_absolute_widget.spinBox_absolute_x.setValue(5)
motor_absolute_widget.spinBox_absolute_y.setValue(10)
motor_absolute_widget.ui.spinBox_absolute_x.setValue(5)
motor_absolute_widget.ui.spinBox_absolute_y.setValue(10)
with patch(
"bec_widgets.widgets.motor_control.motor_control.MotorThread.move_absolute",
new_callable=MagicMock,
) as mock_move_absolute:
motor_absolute_widget.pushButton_go_absolute.click()
motor_absolute_widget.ui.pushButton_go_absolute.click()
mock_move_absolute.assert_called_once_with("samx", "samy", (5, 10))
@ -292,8 +292,8 @@ def test_set_precision(motor_absolute_widget):
motor_absolute_widget.on_config_update(CONFIG_DEFAULT)
motor_absolute_widget.set_precision(2)
assert motor_absolute_widget.spinBox_absolute_x.decimals() == 2
assert motor_absolute_widget.spinBox_absolute_y.decimals() == 2
assert motor_absolute_widget.ui.spinBox_absolute_x.decimals() == 2
assert motor_absolute_widget.ui.spinBox_absolute_y.decimals() == 2
#######################################################
@ -338,29 +338,29 @@ def test_initialization_and_config_update(motor_relative_widget):
def test_move_motor_relative(motor_relative_widget):
motor_relative_widget.on_config_update(CONFIG_DEFAULT)
# Set step sizes
motor_relative_widget.spinBox_step_x.setValue(1)
motor_relative_widget.spinBox_step_y.setValue(1)
motor_relative_widget.ui.spinBox_step_x.setValue(1)
motor_relative_widget.ui.spinBox_step_y.setValue(1)
# Mock the move_relative method
motor_relative_widget.motor_thread.move_relative = MagicMock()
# Simulate button clicks
motor_relative_widget.toolButton_right.click()
motor_relative_widget.ui.toolButton_right.click()
motor_relative_widget.motor_thread.move_relative.assert_called_with(
motor_relative_widget.motor_x, 1
)
motor_relative_widget.toolButton_left.click()
motor_relative_widget.ui.toolButton_left.click()
motor_relative_widget.motor_thread.move_relative.assert_called_with(
motor_relative_widget.motor_x, -1
)
motor_relative_widget.toolButton_up.click()
motor_relative_widget.ui.toolButton_up.click()
motor_relative_widget.motor_thread.move_relative.assert_called_with(
motor_relative_widget.motor_y, 1
)
motor_relative_widget.toolButton_down.click()
motor_relative_widget.ui.toolButton_down.click()
motor_relative_widget.motor_thread.move_relative.assert_called_with(
motor_relative_widget.motor_y, -1
)
@ -376,21 +376,21 @@ def test_precision_update(motor_relative_widget):
motor_relative_widget.precision_signal.connect(capture_precision)
# Update precision
motor_relative_widget.spinBox_precision.setValue(1)
motor_relative_widget.ui.spinBox_precision.setValue(1)
assert emitted_values == [1]
assert motor_relative_widget.spinBox_step_x.decimals() == 1
assert motor_relative_widget.spinBox_step_y.decimals() == 1
assert motor_relative_widget.ui.spinBox_step_x.decimals() == 1
assert motor_relative_widget.ui.spinBox_step_y.decimals() == 1
def test_sync_step_sizes(motor_relative_widget):
motor_relative_widget.on_config_update(CONFIG_DEFAULT)
motor_relative_widget.checkBox_same_xy.setChecked(True)
motor_relative_widget.ui.checkBox_same_xy.setChecked(True)
# Change step size for X
motor_relative_widget.spinBox_step_x.setValue(2)
motor_relative_widget.ui.spinBox_step_x.setValue(2)
assert motor_relative_widget.spinBox_step_y.value() == 2
assert motor_relative_widget.ui.spinBox_step_y.value() == 2
def test_change_motor_relative(motor_relative_widget):
@ -420,11 +420,11 @@ def test_delete_selected_row(motor_coordinate_table):
motor_coordinate_table.add_coordinate((3.0, 4.0))
# Select the row
motor_coordinate_table.table.selectRow(0)
motor_coordinate_table.ui.table.selectRow(0)
# Delete the selected row
motor_coordinate_table.delete_selected_row()
assert motor_coordinate_table.table.rowCount() == 1
assert motor_coordinate_table.ui.table.rowCount() == 1
def test_add_coordinate_and_table_update(motor_coordinate_table):
@ -433,20 +433,24 @@ def test_add_coordinate_and_table_update(motor_coordinate_table):
# Add coordinate in Individual mode
motor_coordinate_table.add_coordinate((1.0, 2.0))
assert motor_coordinate_table.table.rowCount() == 1
assert motor_coordinate_table.ui.table.rowCount() == 1
# Check if the coordinates match
x_item_individual = motor_coordinate_table.table.cellWidget(0, 3) # Assuming X is in column 3
y_item_individual = motor_coordinate_table.table.cellWidget(0, 4) # Assuming Y is in column 4
x_item_individual = motor_coordinate_table.ui.table.cellWidget(
0, 3
) # Assuming X is in column 3
y_item_individual = motor_coordinate_table.ui.table.cellWidget(
0, 4
) # Assuming Y is in column 4
assert float(x_item_individual.text()) == 1.0
assert float(y_item_individual.text()) == 2.0
# Switch to Start/Stop and add coordinates
motor_coordinate_table.comboBox_mode.setCurrentIndex(1) # Switch mode
motor_coordinate_table.ui.comboBox_mode.setCurrentIndex(1) # Switch mode
motor_coordinate_table.add_coordinate((3.0, 4.0))
motor_coordinate_table.add_coordinate((5.0, 6.0))
assert motor_coordinate_table.table.rowCount() == 1
assert motor_coordinate_table.ui.table.rowCount() == 1
def test_plot_coordinates_signal(motor_coordinate_table):
@ -466,26 +470,26 @@ def test_plot_coordinates_signal(motor_coordinate_table):
assert received
def test_move_motor_action(motor_coordinate_table):
# Add a coordinate
motor_coordinate_table.add_coordinate((1.0, 2.0))
# Mock the motor thread move_absolute function
motor_coordinate_table.motor_thread.move_absolute = MagicMock()
# Trigger the move action
move_button = motor_coordinate_table.table.cellWidget(0, 1)
move_button.click()
motor_coordinate_table.motor_thread.move_absolute.assert_called_with(
motor_coordinate_table.motor_x, motor_coordinate_table.motor_y, (1.0, 2.0)
)
# def test_move_motor_action(motor_coordinate_table,qtbot):#TODO enable again after table refactor
# # Add a coordinate
# motor_coordinate_table.add_coordinate((1.0, 2.0))
#
# # Mock the motor thread move_absolute function
# motor_coordinate_table.motor_thread.move_absolute = MagicMock()
#
# # Trigger the move action
# move_button = motor_coordinate_table.table.cellWidget(0, 1)
# move_button.click()
#
# motor_coordinate_table.motor_thread.move_absolute.assert_called_with(
# motor_coordinate_table.motor_x, motor_coordinate_table.motor_y, (1.0, 2.0)
# )
def test_plot_coordinates_signal_individual(motor_coordinate_table, qtbot):
motor_coordinate_table.warning_message = False
motor_coordinate_table.set_precision(3)
motor_coordinate_table.comboBox_mode.setCurrentIndex(0)
motor_coordinate_table.ui.comboBox_mode.setCurrentIndex(0)
# This list will store the signals emitted during the test
emitted_signals = []
@ -506,8 +510,8 @@ def test_plot_coordinates_signal_individual(motor_coordinate_table, qtbot):
assert len(coordinates) > 0, "Coordinates list is empty."
assert reference_tag == "Individual"
assert color == "green"
assert motor_coordinate_table.table.cellWidget(0, 3).text() == "1.000"
assert motor_coordinate_table.table.cellWidget(0, 4).text() == "2.000"
assert motor_coordinate_table.ui.table.cellWidget(0, 3).text() == "1.000"
assert motor_coordinate_table.ui.table.cellWidget(0, 4).text() == "2.000"
#######################################################