generated from ImperialCollegeLondon/poetry_template_2
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add tests for DeviceControl and associated classes
Closes #398.
- Loading branch information
Showing
3 changed files
with
444 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
106
tests/gui/hardware_set/test_device_parameters_widget.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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} |
Oops, something went wrong.