From 6a5e0adfb29b4caf5e6b5c15869390370c623af5 Mon Sep 17 00:00:00 2001
From: wyzula-jan <133381102+wyzula-jan@users.noreply.github.com>
Date: Sat, 28 Oct 2023 20:22:22 +0200
Subject: [PATCH] test: test_config_dialog.py added
---
bec_widgets/widgets/__init__.py | 2 +-
bec_widgets/widgets/monitor/config_dialog.py | 6 +-
bec_widgets/widgets/monitor/config_dialog.ui | 5 +
.../example_configs/config_device.yaml | 2 +-
tests/test_bec_monitor.py | 162 ++--------------
tests/test_config_dialog.py | 179 ++++++++++++++++++
6 files changed, 208 insertions(+), 148 deletions(-)
create mode 100644 tests/test_config_dialog.py
diff --git a/bec_widgets/widgets/__init__.py b/bec_widgets/widgets/__init__.py
index 23ec8073..0e72a61b 100644
--- a/bec_widgets/widgets/__init__.py
+++ b/bec_widgets/widgets/__init__.py
@@ -1 +1 @@
-from .monitor import BECDeviceMonitor, ConfigDialog
+from .monitor import BECMonitor, ConfigDialog
diff --git a/bec_widgets/widgets/monitor/config_dialog.py b/bec_widgets/widgets/monitor/config_dialog.py
index 8f87919a..dbee083f 100644
--- a/bec_widgets/widgets/monitor/config_dialog.py
+++ b/bec_widgets/widgets/monitor/config_dialog.py
@@ -17,8 +17,8 @@ from bec_widgets.qt_utils.yaml_dialog import load_yaml, save_yaml
current_path = os.path.dirname(__file__)
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"))
-# test configs #TODO delete after loading works
+# test configs for demonstration purpose
config_default = {
"plot_settings": {
"background_color": "black",
@@ -408,7 +408,9 @@ class ConfigDialog(QWidget, Ui_Form):
self.comboBox_appearance.setCurrentText(plot_settings.get("background_color", "black"))
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(
"Enabled" if plot_settings.get("scan_types", False) else "Disabled"
)
diff --git a/bec_widgets/widgets/monitor/config_dialog.ui b/bec_widgets/widgets/monitor/config_dialog.ui
index 09e403d6..58464f84 100644
--- a/bec_widgets/widgets/monitor/config_dialog.ui
+++ b/bec_widgets/widgets/monitor/config_dialog.ui
@@ -118,6 +118,11 @@
magma
+ -
+
+ plasma
+
+
-
viridis
diff --git a/bec_widgets/widgets/monitor/example_configs/config_device.yaml b/bec_widgets/widgets/monitor/example_configs/config_device.yaml
index 0ee15b92..2cce78a4 100644
--- a/bec_widgets/widgets/monitor/example_configs/config_device.yaml
+++ b/bec_widgets/widgets/monitor/example_configs/config_device.yaml
@@ -1,7 +1,7 @@
plot_settings:
background_color: "black"
num_columns: 2
- colormap: "plasma"
+ colormap: "viridis"
scan_types: False
plot_data:
diff --git a/tests/test_bec_monitor.py b/tests/test_bec_monitor.py
index 7c6f258b..284ffd0d 100644
--- a/tests/test_bec_monitor.py
+++ b/tests/test_bec_monitor.py
@@ -1,155 +1,30 @@
-from unittest.mock import MagicMock
+import os
+import yaml
import pytest
+from unittest.mock import MagicMock
from PyQt5.QtWidgets import QApplication
from bec_widgets.widgets import BECMonitor
-config_device = {
- "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"},
- ],
- },
- },
- ],
-}
+current_path = os.path.dirname(__file__)
-config_device_no_entry = {
- "plot_settings": {
- "background_color": "white",
- "num_columns": 5, # Number of columns higher than the actual number of plots
- "colormap": "plasma",
- "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 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
-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."""
client = MagicMock()
widget = BECMonitor(config=config, client=client)
@@ -246,7 +121,7 @@ def mock_getitem(dev_name):
return mock_instance
-# mocked messages and metadatas
+# mocked messages and metadata
msg_1 = {
"data": {
"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)
# Initialize and run test
- # plot_app.init_curves = MagicMock()
plot_app.data = {}
plot_app.scanID = 0
diff --git a/tests/test_config_dialog.py b/tests/test_config_dialog.py
new file mode 100644
index 00000000..93d4bbf2
--- /dev/null
+++ b/tests/test_config_dialog.py
@@ -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"