mirror of
https://github.com/bec-project/bec_widgets.git
synced 2025-07-14 11:41:49 +02:00
test: test_config_dialog.py added
This commit is contained in:
@ -1 +1 @@
|
|||||||
from .monitor import BECDeviceMonitor, ConfigDialog
|
from .monitor import BECMonitor, ConfigDialog
|
||||||
|
@ -17,8 +17,8 @@ from bec_widgets.qt_utils.yaml_dialog import load_yaml, save_yaml
|
|||||||
current_path = os.path.dirname(__file__)
|
current_path = os.path.dirname(__file__)
|
||||||
Ui_Form, BaseClass = uic.loadUiType(os.path.join(current_path, "config_dialog.ui"))
|
Ui_Form, BaseClass = uic.loadUiType(os.path.join(current_path, "config_dialog.ui"))
|
||||||
Tab_Ui_Form, Tab_BaseClass = uic.loadUiType(os.path.join(current_path, "tab_template.ui"))
|
Tab_Ui_Form, Tab_BaseClass = uic.loadUiType(os.path.join(current_path, "tab_template.ui"))
|
||||||
# test configs #TODO delete after loading works
|
|
||||||
|
|
||||||
|
# test configs for demonstration purpose
|
||||||
config_default = {
|
config_default = {
|
||||||
"plot_settings": {
|
"plot_settings": {
|
||||||
"background_color": "black",
|
"background_color": "black",
|
||||||
@ -408,7 +408,9 @@ class ConfigDialog(QWidget, Ui_Form):
|
|||||||
|
|
||||||
self.comboBox_appearance.setCurrentText(plot_settings.get("background_color", "black"))
|
self.comboBox_appearance.setCurrentText(plot_settings.get("background_color", "black"))
|
||||||
self.spinBox_n_column.setValue(plot_settings.get("num_columns", 1))
|
self.spinBox_n_column.setValue(plot_settings.get("num_columns", 1))
|
||||||
self.comboBox_colormap.setCurrentText(plot_settings.get("colormap", "magma"))
|
self.comboBox_colormap.setCurrentText(
|
||||||
|
plot_settings.get("colormap", "magma")
|
||||||
|
) # TODO make logic to allow also different colormaps -> validation of incoming dict
|
||||||
self.comboBox_scanTypes.setCurrentText(
|
self.comboBox_scanTypes.setCurrentText(
|
||||||
"Enabled" if plot_settings.get("scan_types", False) else "Disabled"
|
"Enabled" if plot_settings.get("scan_types", False) else "Disabled"
|
||||||
)
|
)
|
||||||
|
@ -118,6 +118,11 @@
|
|||||||
<string>magma</string>
|
<string>magma</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>plasma</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>viridis</string>
|
<string>viridis</string>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
plot_settings:
|
plot_settings:
|
||||||
background_color: "black"
|
background_color: "black"
|
||||||
num_columns: 2
|
num_columns: 2
|
||||||
colormap: "plasma"
|
colormap: "viridis"
|
||||||
scan_types: False
|
scan_types: False
|
||||||
|
|
||||||
plot_data:
|
plot_data:
|
||||||
|
@ -1,155 +1,30 @@
|
|||||||
from unittest.mock import MagicMock
|
import os
|
||||||
|
import yaml
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from unittest.mock import MagicMock
|
||||||
from PyQt5.QtWidgets import QApplication
|
from PyQt5.QtWidgets import QApplication
|
||||||
|
|
||||||
from bec_widgets.widgets import BECMonitor
|
from bec_widgets.widgets import BECMonitor
|
||||||
|
|
||||||
config_device = {
|
current_path = os.path.dirname(__file__)
|
||||||
"plot_settings": {
|
|
||||||
"background_color": "black",
|
|
||||||
"num_columns": 1,
|
|
||||||
"colormap": "plasma",
|
|
||||||
"scan_types": False,
|
|
||||||
},
|
|
||||||
"plot_data": [
|
|
||||||
{
|
|
||||||
"plot_name": "BPM4i plots vs samx",
|
|
||||||
"x": {
|
|
||||||
"label": "Motor Y",
|
|
||||||
"signals": [{"name": "samx", "entry": "samx"}],
|
|
||||||
},
|
|
||||||
"y": {
|
|
||||||
"label": "bpm4i",
|
|
||||||
"signals": [{"name": "bpm4i", "entry": "bpm4i"}],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"plot_name": "Gauss plots vs samx",
|
|
||||||
"x": {
|
|
||||||
"label": "Motor X",
|
|
||||||
"signals": [{"name": "samx", "entry": "samx"}],
|
|
||||||
},
|
|
||||||
"y": {
|
|
||||||
"label": "Gauss",
|
|
||||||
"signals": [
|
|
||||||
{"name": "gauss_adc1", "entry": "gauss_adc1"},
|
|
||||||
{"name": "gauss_adc2", "entry": "gauss_adc2"},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
config_device_no_entry = {
|
def load_config(config_path):
|
||||||
"plot_settings": {
|
"""Helper function to load config from yaml file."""
|
||||||
"background_color": "white",
|
with open(config_path, "r") as f:
|
||||||
"num_columns": 5, # Number of columns higher than the actual number of plots
|
config = yaml.safe_load(f)
|
||||||
"colormap": "plasma",
|
return config
|
||||||
"scan_types": False,
|
|
||||||
},
|
|
||||||
"plot_data": [
|
|
||||||
{
|
|
||||||
"plot_name": "BPM4i plots vs samx",
|
|
||||||
"x": {
|
|
||||||
"label": "Motor Y",
|
|
||||||
"signals": [{"name": "samx"}], # Entry is missing
|
|
||||||
},
|
|
||||||
"y": {
|
|
||||||
"label": "bpm4i",
|
|
||||||
"signals": [{"name": "bpm4i"}], # Entry is missing
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"plot_name": "Gauss plots vs samx",
|
|
||||||
"x": {
|
|
||||||
"label": "Motor X",
|
|
||||||
"signals": [{"name": "samx"}], # Entry is missing
|
|
||||||
},
|
|
||||||
"y": {
|
|
||||||
"label": "Gauss",
|
|
||||||
"signals": [{"name": "gauss_bpm"}], # Entry is missing
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
config_scan = {
|
|
||||||
"plot_settings": {
|
|
||||||
"background_color": "white",
|
|
||||||
"num_columns": 3,
|
|
||||||
"colormap": "plasma",
|
|
||||||
"scan_types": True,
|
|
||||||
},
|
|
||||||
"plot_data": {
|
|
||||||
"grid_scan": [
|
|
||||||
{
|
|
||||||
"plot_name": "Grid plot 1",
|
|
||||||
"x": {"label": "Motor X", "signals": [{"name": "samx", "entry": "samx"}]},
|
|
||||||
"y": {
|
|
||||||
"label": "BPM",
|
|
||||||
"signals": [
|
|
||||||
{"name": "gauss_bpm", "entry": "gauss_bpm"},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"plot_name": "Grid plot 2",
|
|
||||||
"x": {"label": "Motor X", "signals": [{"name": "samx", "entry": "samx"}]},
|
|
||||||
"y": {
|
|
||||||
"label": "BPM",
|
|
||||||
"signals": [
|
|
||||||
{"name": "gauss_adc1", "entry": "gauss_adc1"},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"plot_name": "Grid plot 3",
|
|
||||||
"x": {"label": "Motor Y", "signals": [{"name": "samx", "entry": "samx"}]},
|
|
||||||
"y": {
|
|
||||||
"label": "BPM",
|
|
||||||
"signals": [{"name": "gauss_adc2", "entry": "gauss_adc2"}],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"plot_name": "Grid plot 4",
|
|
||||||
"x": {"label": "Motor Y", "signals": [{"name": "samx", "entry": "samx"}]},
|
|
||||||
"y": {
|
|
||||||
"label": "BPM",
|
|
||||||
"signals": [{"name": "bpm4i", "entry": "bpm4i"}],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"line_scan": [
|
|
||||||
{
|
|
||||||
"plot_name": "Multiple Gauss Plot",
|
|
||||||
"x": {"label": "Motor X", "signals": [{"name": "samx"}]},
|
|
||||||
"y": {
|
|
||||||
"label": "BPM",
|
|
||||||
"signals": [
|
|
||||||
{"name": "gauss_bpm", "entry": "gauss_bpm"},
|
|
||||||
{"name": "gauss_adc1", "entry": "gauss_adc1"},
|
|
||||||
{"name": "gauss_adc2", "entry": "gauss_adc2"},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"plot_name": "BPM Plot",
|
|
||||||
"x": {"label": "Motor X", "signals": [{"name": "samx", "entry": "samx"}]},
|
|
||||||
"y": {
|
|
||||||
"label": "Multi",
|
|
||||||
"signals": [
|
|
||||||
{"name": "bpm4i", "entry": "bpm4i"},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def setup_monitor(qtbot, config):
|
config_device = load_config(os.path.join(current_path, "test_configs/config_device.yaml"))
|
||||||
|
config_device_no_entry = load_config(
|
||||||
|
os.path.join(current_path, "test_configs/config_device_no_entry.yaml")
|
||||||
|
)
|
||||||
|
config_scan = load_config(os.path.join(current_path, "test_configs/config_scan.yaml"))
|
||||||
|
|
||||||
|
|
||||||
|
def setup_monitor(qtbot, config): # TODO fixture or helper function?
|
||||||
"""Helper function to set up the BECDeviceMonitor widget."""
|
"""Helper function to set up the BECDeviceMonitor widget."""
|
||||||
client = MagicMock()
|
client = MagicMock()
|
||||||
widget = BECMonitor(config=config, client=client)
|
widget = BECMonitor(config=config, client=client)
|
||||||
@ -246,7 +121,7 @@ def mock_getitem(dev_name):
|
|||||||
return mock_instance
|
return mock_instance
|
||||||
|
|
||||||
|
|
||||||
# mocked messages and metadatas
|
# mocked messages and metadata
|
||||||
msg_1 = {
|
msg_1 = {
|
||||||
"data": {
|
"data": {
|
||||||
"samx": {"samx": {"value": 10}},
|
"samx": {"samx": {"value": 10}},
|
||||||
@ -316,7 +191,6 @@ def test_on_scan_segment(qtbot, config, msg, metadata, expected_data):
|
|||||||
plot_app = setup_monitor(qtbot, config)
|
plot_app = setup_monitor(qtbot, config)
|
||||||
|
|
||||||
# Initialize and run test
|
# Initialize and run test
|
||||||
# plot_app.init_curves = MagicMock()
|
|
||||||
plot_app.data = {}
|
plot_app.data = {}
|
||||||
plot_app.scanID = 0
|
plot_app.scanID = 0
|
||||||
|
|
||||||
|
179
tests/test_config_dialog.py
Normal file
179
tests/test_config_dialog.py
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
import os
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from PyQt5.QtWidgets import QTabWidget, QTableWidgetItem
|
||||||
|
|
||||||
|
from bec_widgets.widgets import ConfigDialog
|
||||||
|
|
||||||
|
current_path = os.path.dirname(__file__)
|
||||||
|
|
||||||
|
|
||||||
|
def load_config(config_path):
|
||||||
|
"""Helper function to load config from yaml file."""
|
||||||
|
with open(config_path, "r") as f:
|
||||||
|
config = yaml.safe_load(f)
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
|
# save configs as for test_bec_monitor.py
|
||||||
|
config_device = load_config(os.path.join(current_path, "test_configs/config_device.yaml"))
|
||||||
|
config_device_no_entry = load_config(
|
||||||
|
os.path.join(current_path, "test_configs/config_device_no_entry.yaml")
|
||||||
|
)
|
||||||
|
config_scan = load_config(os.path.join(current_path, "test_configs/config_scan.yaml"))
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def config_dialog(qtbot):
|
||||||
|
widget = ConfigDialog()
|
||||||
|
qtbot.addWidget(widget)
|
||||||
|
qtbot.waitExposed(widget)
|
||||||
|
return widget
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("config", [config_device, config_scan])
|
||||||
|
def test_load_config(config_dialog, config):
|
||||||
|
config_dialog.load_config(config)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
config_dialog.comboBox_appearance.currentText()
|
||||||
|
== config["plot_settings"]["background_color"]
|
||||||
|
)
|
||||||
|
assert config_dialog.spinBox_n_column.value() == config["plot_settings"]["num_columns"]
|
||||||
|
assert config_dialog.comboBox_colormap.currentText() == config["plot_settings"]["colormap"]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"config, scan_mode",
|
||||||
|
[
|
||||||
|
(config_device, False),
|
||||||
|
(config_scan, True),
|
||||||
|
(config_device_no_entry, False),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_initialization(config_dialog, config, scan_mode):
|
||||||
|
config_dialog.load_config(config)
|
||||||
|
|
||||||
|
assert isinstance(config_dialog, ConfigDialog)
|
||||||
|
assert (
|
||||||
|
config_dialog.comboBox_appearance.currentText()
|
||||||
|
== config["plot_settings"]["background_color"]
|
||||||
|
)
|
||||||
|
assert config_dialog.spinBox_n_column.value() == config["plot_settings"]["num_columns"]
|
||||||
|
assert (config_dialog.comboBox_scanTypes.currentText() == "Enabled") == scan_mode
|
||||||
|
assert (
|
||||||
|
config_dialog.tabWidget_scan_types.count() > 0
|
||||||
|
) # Ensures there's at least one tab created
|
||||||
|
|
||||||
|
# If there's a need to check the contents of the first tab (there has to be always at least one tab)
|
||||||
|
first_tab = config_dialog.tabWidget_scan_types.widget(0)
|
||||||
|
if scan_mode:
|
||||||
|
assert (
|
||||||
|
first_tab.findChild(QTabWidget, "tabWidget_plots") is not None
|
||||||
|
) # Ensures plot tab widget exists in scan mode
|
||||||
|
else:
|
||||||
|
assert (
|
||||||
|
first_tab.findChild(QTabWidget) is not None
|
||||||
|
) # Ensures plot tab widget exists in default mode
|
||||||
|
|
||||||
|
|
||||||
|
def test_edit_and_apply_config(config_dialog):
|
||||||
|
config_dialog.load_config(config_device)
|
||||||
|
|
||||||
|
config_dialog.comboBox_appearance.setCurrentText("white")
|
||||||
|
config_dialog.spinBox_n_column.setValue(2)
|
||||||
|
config_dialog.comboBox_colormap.setCurrentText("viridis")
|
||||||
|
|
||||||
|
applied_config = config_dialog.apply_config()
|
||||||
|
|
||||||
|
assert applied_config["plot_settings"]["background_color"] == "white"
|
||||||
|
assert applied_config["plot_settings"]["num_columns"] == 2
|
||||||
|
assert applied_config["plot_settings"]["colormap"] == "viridis"
|
||||||
|
|
||||||
|
|
||||||
|
def test_edit_and_apply_config_scan_mode(config_dialog):
|
||||||
|
config_dialog.load_config(config_scan)
|
||||||
|
|
||||||
|
config_dialog.comboBox_appearance.setCurrentText("white")
|
||||||
|
config_dialog.spinBox_n_column.setValue(2)
|
||||||
|
config_dialog.comboBox_colormap.setCurrentText("viridis")
|
||||||
|
config_dialog.comboBox_scanTypes.setCurrentText("Enabled")
|
||||||
|
|
||||||
|
applied_config = config_dialog.apply_config()
|
||||||
|
|
||||||
|
assert applied_config["plot_settings"]["background_color"] == "white"
|
||||||
|
assert applied_config["plot_settings"]["num_columns"] == 2
|
||||||
|
assert applied_config["plot_settings"]["colormap"] == "viridis"
|
||||||
|
assert applied_config["plot_settings"]["scan_types"] is True
|
||||||
|
|
||||||
|
|
||||||
|
def test_add_new_scan(config_dialog):
|
||||||
|
# Ensure the tab count is initially 1 (from the default config)
|
||||||
|
assert config_dialog.tabWidget_scan_types.count() == 1
|
||||||
|
|
||||||
|
# Add a new scan tab
|
||||||
|
config_dialog.add_new_scan(config_dialog.tabWidget_scan_types, "Test Scan Tab")
|
||||||
|
|
||||||
|
# Ensure the tab count is now 2
|
||||||
|
assert config_dialog.tabWidget_scan_types.count() == 2
|
||||||
|
|
||||||
|
# Ensure the new tab has the correct name
|
||||||
|
assert config_dialog.tabWidget_scan_types.tabText(1) == "Test Scan Tab"
|
||||||
|
|
||||||
|
|
||||||
|
def test_add_new_plot_and_modify(config_dialog):
|
||||||
|
# Ensure the tab count is initially 1 and it is called "Default"
|
||||||
|
assert config_dialog.tabWidget_scan_types.count() == 1
|
||||||
|
assert config_dialog.tabWidget_scan_types.tabText(0) == "Default"
|
||||||
|
# Get the first tab (which should be a scan tab)
|
||||||
|
scan_tab = config_dialog.tabWidget_scan_types.widget(0)
|
||||||
|
|
||||||
|
# Ensure the plot tab count is initially 1 and it is called "Plot 1"
|
||||||
|
tabWidget_plots = scan_tab.findChild(QTabWidget)
|
||||||
|
assert tabWidget_plots.count() == 1
|
||||||
|
assert tabWidget_plots.tabText(0) == "Plot 1"
|
||||||
|
|
||||||
|
# Add a new plot tab
|
||||||
|
config_dialog.add_new_plot(scan_tab)
|
||||||
|
|
||||||
|
# Ensure the plot tab count is now 2
|
||||||
|
assert tabWidget_plots.count() == 2
|
||||||
|
|
||||||
|
# Ensure the new tab has the correct name
|
||||||
|
assert tabWidget_plots.tabText(1) == "Plot 2"
|
||||||
|
|
||||||
|
# Access the new plot tab
|
||||||
|
new_plot_tab = tabWidget_plots.widget(1)
|
||||||
|
|
||||||
|
# Modify the line edits within the new plot tab
|
||||||
|
new_plot_tab.ui.lineEdit_plot_title.setText("Modified Plot Title")
|
||||||
|
new_plot_tab.ui.lineEdit_x_label.setText("Modified X Label")
|
||||||
|
new_plot_tab.ui.lineEdit_y_label.setText("Modified Y Label")
|
||||||
|
new_plot_tab.ui.lineEdit_x_name.setText("Modified X Name")
|
||||||
|
new_plot_tab.ui.lineEdit_x_entry.setText("Modified X Entry")
|
||||||
|
|
||||||
|
# Modify the table for signals
|
||||||
|
new_plot_tab.ui.pushButton_y_new.click() # Press button to add a new row
|
||||||
|
table = new_plot_tab.ui.tableWidget_y_signals
|
||||||
|
assert table.rowCount() == 1 # Ensure the new row is added
|
||||||
|
|
||||||
|
row_position = table.rowCount() - 1
|
||||||
|
|
||||||
|
# Modify the first row
|
||||||
|
table.setItem(row_position, 0, QTableWidgetItem("New Signal Name"))
|
||||||
|
table.setItem(row_position, 1, QTableWidgetItem("New Signal Entry"))
|
||||||
|
# Apply the configuration
|
||||||
|
config = config_dialog.apply_config()
|
||||||
|
|
||||||
|
# Check if the modifications are reflected in the configuration
|
||||||
|
modified_plot_config = config["plot_data"][
|
||||||
|
1
|
||||||
|
] # Assuming the new plot is the second item in the plot_data list
|
||||||
|
assert modified_plot_config["plot_name"] == "Modified Plot Title"
|
||||||
|
assert modified_plot_config["x"]["label"] == "Modified X Label"
|
||||||
|
assert modified_plot_config["y"]["label"] == "Modified Y Label"
|
||||||
|
assert modified_plot_config["x"]["signals"][0]["name"] == "Modified X Name"
|
||||||
|
assert modified_plot_config["x"]["signals"][0]["entry"] == "Modified X Entry"
|
||||||
|
assert modified_plot_config["y"]["signals"][0]["name"] == "New Signal Name"
|
||||||
|
assert modified_plot_config["y"]["signals"][0]["entry"] == "New Signal Entry"
|
Reference in New Issue
Block a user