Skip to content

Commit

Permalink
Add tests for DeviceControl and associated classes
Browse files Browse the repository at this point in the history
Closes #398.
  • Loading branch information
alexdewar committed Nov 14, 2023
1 parent 1f41b9c commit 0fdf4c6
Show file tree
Hide file tree
Showing 3 changed files with 444 additions and 0 deletions.
75 changes: 75 additions & 0 deletions tests/gui/hardware_set/test_device_control.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
"""Test the DeviceControl class."""

from unittest.mock import MagicMock, Mock, patch

import pytest

from finesse.device_info import DeviceBaseTypeInfo, DeviceInstanceRef, DeviceTypeInfo
from finesse.gui.hardware_set.device_view import DeviceControl
from finesse.gui.hardware_set.hardware_set import OpenDeviceArgs

CONNECTED_DEVICES = (
OpenDeviceArgs.create("stepper_motor", "MyStepperMotor"),
OpenDeviceArgs.create(
"temperature_monitor",
"MyTemperatureMonitor",
{"param1": "value1"},
),
)


@pytest.fixture
def widget(qtbot) -> DeviceControl:
"""Return a DeviceControl fixture."""
return DeviceControl(set(CONNECTED_DEVICES))


def test_init(sendmsg_mock: MagicMock, subscribe_mock: MagicMock, qtbot) -> None:
"""Test the constructor."""
devices = MagicMock()
widget = DeviceControl(devices)
assert widget._connected_devices is devices

# Check that the list of devices was requested and the response is listened for
subscribe_mock.assert_called_once_with(
widget._on_device_list, "device.list.response"
)
sendmsg_mock.assert_called_once_with("device.list.request")


@pytest.mark.parametrize(
"instance,expected",
(
(DeviceInstanceRef("stepper_motor"), CONNECTED_DEVICES[0].class_name),
(DeviceInstanceRef("made_up"), None),
),
)
def test_get_connected_device(
instance: DeviceInstanceRef, expected: str | None, widget: DeviceControl, qtbot
) -> None:
"""Test the _get_connected_device() method."""
assert widget._get_connected_device(instance) == expected


@patch("finesse.gui.hardware_set.device_view.DeviceTypeControl")
def test_on_device_list(widget_mock: Mock, widget: DeviceControl, qtbot) -> None:
"""Test the _on_device_list() method."""
base_type = DeviceBaseTypeInfo("base_type", "Base type", (), ())
device_types = [
DeviceTypeInfo("my_class1", "Device 1", []),
DeviceTypeInfo("my_class2", "Device 2", []),
]

with patch.object(widget, "layout"):
with patch.object(widget, "_get_connected_device") as connected_mock:
connected_mock.return_value = "connected_device"
widget._on_device_list({base_type: device_types})

# In practice, there will be more than one base type, but let's just test
# that the code creates this one widget for ease
widget_mock.assert_called_once_with(
"Base type",
DeviceInstanceRef("base_type"),
device_types,
"connected_device",
)
106 changes: 106 additions & 0 deletions tests/gui/hardware_set/test_device_parameters_widget.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
"""Tests for the DeviceParametersWidget class."""
from collections.abc import Sequence
from unittest.mock import Mock, patch

import pytest

from finesse.device_info import DeviceParameter, DeviceTypeInfo
from finesse.gui.hardware_set.device_view import DeviceParametersWidget


@pytest.fixture
def widget(qtbot) -> DeviceParametersWidget:
"""A fixture providing a DeviceParametersWidget."""
return DeviceParametersWidget(
DeviceTypeInfo("my_class", "My Device", [DeviceParameter("my_param", range(2))])
)


@pytest.mark.parametrize(
"params",
(
# no params
(),
# one param
(DeviceParameter("my_param", ("value1", "value2")),),
# two params
(
DeviceParameter("my_param", ("value1", "value2")),
DeviceParameter("param2", range(3), 1),
),
),
)
def test_init(params: Sequence[DeviceParameter], qtbot) -> None:
"""Test the constructor."""
device_type = DeviceTypeInfo("my_class", "My Device", params)

with patch.object(
DeviceParametersWidget, "load_saved_parameter_values"
) as load_params_mock:
widget = DeviceParametersWidget(device_type)
assert widget.device_type is device_type
assert list(widget._combos.keys()) == [p.name for p in params]
load_params_mock.assert_called_once_with()

for param in params:
combo = widget._combos[param.name]
items = [combo.itemText(i) for i in range(combo.count())]
assert items == list(map(str, param.possible_values))
assert (
combo.currentData() == param.default_value
if param.default_value
else param.possible_values[0]
)


def test_set_parameter_value(widget: DeviceParametersWidget) -> None:
"""Test the set_parameter_value() method."""
combo = widget._combos["my_param"]
assert combo.currentText() == "0"

widget.set_parameter_value("my_param", 1)
assert combo.currentText() == "1"

widget.set_parameter_value("my_param", 5) # invalid
assert combo.currentText() == "1"


@patch("finesse.gui.hardware_set.device_view.settings")
def test_load_saved_parameter_values(
settings_mock: Mock, widget: DeviceParametersWidget, qtbot
) -> None:
"""Test the load_saved_parameter_values() method."""
settings_mock.value.return_value = {"my_param": 1}
with patch.object(widget, "set_parameter_value") as set_param_mock:
widget.load_saved_parameter_values()
set_param_mock.assert_called_once_with("my_param", 1)


@patch("finesse.gui.hardware_set.device_view.settings")
def test_load_saved_parameter_values_none_saved(
settings_mock: Mock, widget: DeviceParametersWidget, qtbot
) -> None:
"""Test the load_saved_parameter_values() method if there are no values saved."""
settings_mock.value.return_value = None
with patch.object(widget, "set_parameter_value") as set_param_mock:
widget.load_saved_parameter_values()
set_param_mock.assert_not_called()


@patch("finesse.gui.hardware_set.device_view.settings")
@patch("finesse.gui.hardware_set.device_view.logging.warn")
def test_load_saved_parameter_values_error(
warn_mock: Mock, settings_mock: Mock, widget: DeviceParametersWidget, qtbot
) -> None:
"""Test the load_saved_parameter_values() method ignores errors."""
settings_mock.value.return_value = {"my_param": 1}
with patch.object(widget, "set_parameter_value") as set_param_mock:
set_param_mock.side_effect = KeyError
widget.load_saved_parameter_values()
set_param_mock.assert_called_once_with("my_param", 1)
warn_mock.assert_called_once()


def test_current_parameter_values(widget: DeviceParametersWidget, qtbot) -> None:
"""Test the current_parameter_values property."""
assert widget.current_parameter_values == {"my_param": 0}
Loading

0 comments on commit 0fdf4c6

Please sign in to comment.