Source code for tests.test_gui

"""
test objects
* main
* components
* control
* monitor
* plot
* status_bar

test types
* user interaction
* flooding


"""

from copy import copy
import pdb

import pytest
from time import sleep


from pytestqt import qt_compat
from pytestqt.qt_compat import qt_api

# mock before importing


from vent import gui
from vent.gui import styles
from vent.gui import widgets
from vent.common import message, values
from vent.coordinator.coordinator import get_coordinator


from PySide2 import QtCore, QtGui, QtWidgets

import numpy as np

##################################




# turn off gui limiting
gui.limit_gui(False)

n_samples = 100
decimals = 5
global_minmax_range = (0, 100)
global_safe_range = (25, 75)

[docs]@pytest.fixture def generic_minmax(): """ Make a (min, max) range of values that has some safe space in between. ie. min can be between 0 and 0.25*(minmax_range[1]-minmax_range[0]) and max can similarly be above the 75% mark of the range Returns: """ def _generic_minmax(): abs_min = np.random.rand() * (global_minmax_range[1]-global_minmax_range[0]) * 0.25 + \ global_minmax_range[0] abs_max = np.random.rand() * (global_minmax_range[1]-global_minmax_range[0]) * 0.25 + \ global_minmax_range[0] + (global_minmax_range[1]-global_minmax_range[0]) * 0.75 abs_min, abs_max = np.round(abs_min, decimals), np.round(abs_max, decimals) return abs_min, abs_max return _generic_minmax
[docs]@pytest.fixture def generic_saferange(): """ Make a (min, max) range of values that has some safe space in between. ie. min can be between 0 and 0.25*(minmax_range[1]-minmax_range[0]) and max can similarly be above the 75% mark of the range Returns: """ def _generic_saferange(): abs_min = np.random.rand() * (global_safe_range[1]-global_safe_range[0]) * 0.25 + \ global_safe_range[0] abs_max = np.random.rand() * (global_safe_range[1]-global_safe_range[0]) * 0.25 + \ global_safe_range[0] + (global_safe_range[1]-global_safe_range[0]) * 0.75 abs_min, abs_max = np.round(abs_min, decimals), np.round(abs_max, decimals) return abs_min, abs_max return _generic_saferange
[docs]@pytest.fixture(params=[True, False]) def spawn_gui(qtbot, request): assert qt_api.QApplication.instance() is not None app = qt_api.QApplication.instance() app.setStyle('Fusion') app.setStyleSheet(styles.DARK_THEME) app = styles.set_dark_palette(app) coordinator = get_coordinator(sim_mode=True, single_process=request.param) vent_gui = gui.Vent_Gui(coordinator) #app, vent_gui = launch_gui(coordinator) qtbot.addWidget(vent_gui) return app, vent_gui
[docs]def test_gui_launch(qtbot): assert qt_api.QApplication.instance() is not None app = qt_api.QApplication.instance() app.setStyle('Fusion') app.setStyleSheet(styles.DARK_THEME) app = styles.set_dark_palette(app) coordinator = get_coordinator(sim_mode=True, single_process=True) vent_gui = gui.Vent_Gui(coordinator) #app, vent_gui = launch_gui(coordinator) qtbot.addWidget(vent_gui) vent_gui.status_bar.start_button.click() # wait for a second to let the simulation spin up and start spitting values qtbot.wait(5000) assert vent_gui.isVisible()
[docs]@pytest.mark.timeout(15) def test_gui_launch_mp(qtbot): assert qt_api.QApplication.instance() is not None coordinator = get_coordinator(sim_mode=True, single_process=False) coordinator.start() vent_gui = gui.Vent_Gui(coordinator) qtbot.addWidget(vent_gui) vent_gui.status_bar.start_button.click() # wait for a second to let the simulation spin up and start spitting values qtbot.wait(5000) assert vent_gui.isVisible()
################################ # test user interaction
[docs]@pytest.mark.parametrize("test_value", [(k, v) for k, v in values.CONTROL.items()]) def test_gui_controls(qtbot, spawn_gui, test_value): """ test setting controls in all the ways available to the GUI from the :class:`~vent.gui.widgets.control.Control` widget: * :class:`~vent.gui.widgets.components.EditableLabel` - setting label text * setting slider value * using :meth:`~vent.gui.main.Vent_Gui.set_value` Args: qtbot: spawn_gui: test_value: """ app, vent_gui = spawn_gui vent_gui.start() vent_gui.timer.stop() value_name = test_value[0] value_params = test_value[1] abs_range = value_params.abs_range # generate target value def gen_test_value(): test_value = np.random.rand()*(abs_range[1]-abs_range[0]) + abs_range[0] test_value = np.round(test_value, value_params.decimals) return test_value #### # test setting controls from control widget # from editablelabel control_widget = vent_gui.controls[value_name.name] for i in range(n_samples): test_value = gen_test_value() control_widget.value_label.setLabelEditableAction() control_widget.value_label.lineEdit.setText(str(test_value)) control_widget.value_label.returnPressedAction() # should call labelUpdatedAction and send to controller control_value = vent_gui.coordinator.get_control(value_name) assert(control_value.value == test_value) # from slider # toggle it open assert(control_widget.slider_frame.isVisible() == False) control_widget.toggle_button.click() assert(control_widget.slider_frame.isVisible() == True) for i in range(n_samples): test_value = gen_test_value() control_widget.slider.setValue(test_value) control_value = vent_gui.coordinator.get_control(value_name) assert(control_value.value == test_value) # from set_value for i in range(n_samples): test_value = gen_test_value() vent_gui.set_value(test_value, value_name = value_name) control_value = vent_gui.coordinator.get_control(value_name) assert(control_value.value == test_value)
[docs]@pytest.mark.parametrize("test_value", [(k, v) for k, v in values.SENSOR.items()]) def test_gui_monitor(qtbot, spawn_gui, test_value): app, vent_gui = spawn_gui vent_gui.start() vent_gui.timer.stop() value_name = test_value[0] value_params = test_value[1] abs_range = value_params.abs_range # generate target value def gen_test_values(): test_value = np.random.rand(2)*(abs_range[1]-abs_range[0]) + abs_range[0] test_value = np.round(test_value, value_params.decimals) return np.min(test_value), np.max(test_value) monitor_widget = vent_gui.monitor[value_name.name] # open the control assert(monitor_widget.slider_frame.isVisible() == False) monitor_widget.toggle_button.click() assert (monitor_widget.slider_frame.isVisible() == True) # set handles to abs_min and max so are on absolute right and left sides monitor_widget.range_slider.setValue(abs_range) assert(monitor_widget.range_slider.low == monitor_widget.range_slider.minimum()) assert (monitor_widget.range_slider.high == monitor_widget.range_slider.maximum())
# # # move left a quarter of the way to the right # widget_size = monitor_widget.range_slider.size() # # # get low box position # low_pos = monitor_widget.range_slider.get_handle_rect(0) # click_pos = low_pos.center() # move_pos = copy(click_pos) # move_pos.setX(move_pos.x() + (widget_size.width()/4)) # # qtbot.mouseMove(monitor_widget.range_slider, click_pos, delay=100) # qtbot.mousePress(monitor_widget.range_slider, QtCore.Qt.LeftButton, delay=200) # qtbot.mouseMove(monitor_widget.range_slider, move_pos) # qtbot.mouseRelease(monitor_widget.range_slider, QtCore.Qt.LeftButton, pos=move_pos, delay=200) # set with range_slider # for i in range(n_samples): # test_min, test_max = gen_test_values() # # # with qtbot.waitSignal(monitor_widget.limits_changed, timeout=1000) as blocker: # monitor_widget.range_slider.setLow(test_min) # sleep(0.01) # assert(blocker.args[0][0]==test_min) # # with qtbot.waitSignal(monitor_widget.limits_changed, timeout=1000) as blocker: # monitor_widget.range_slider.setHigh(test_max) # sleep(0.01) # assert(blocker.args[0][1]==test_max) ################################### # Test base components ##### # doubleslider
[docs]def test_doubleslider(qtbot): """ test that the doubleslider accurately represents floats """ doubleslider = widgets.components.DoubleSlider(decimals=decimals) doubleslider.show() qtbot.addWidget(doubleslider) doubleslider.setMinimum(0) doubleslider.setMaximum(1) for i in np.random.rand(n_samples): test_val = np.round(i, decimals) # set value inside of signal catcher to test both value and signal with qtbot.waitSignal(doubleslider.doubleValueChanged, timeout=1000) as blocker: doubleslider.setValue(test_val) assert(doubleslider.value() == test_val) assert(blocker.args == test_val)
[docs]def test_doubleslider_minmax(qtbot, generic_minmax): doubleslider = widgets.components.DoubleSlider(decimals=decimals) doubleslider.show() qtbot.addWidget(doubleslider) multiplier = 100 for i in range(n_samples): min, max = generic_minmax() doubleslider.setMinimum(min) doubleslider.setMaximum(max) # test that values were set correctly assert(doubleslider.minimum() == min) assert(doubleslider.maximum() == max) # test below min and above max test_min = min - np.random.rand()*multiplier test_max = max + np.random.rand()*multiplier doubleslider.setValue(test_min) assert(doubleslider.value() == doubleslider.minimum()) doubleslider.setValue(test_max) assert(doubleslider.value() == doubleslider.maximum())
################# # RangeSlider
[docs]def test_rangeslider(qtbot, generic_minmax, generic_saferange): abs_range = generic_minmax() safe_range = generic_saferange() print(safe_range) orientation = QtCore.Qt.Orientation.Horizontal rangeslider = widgets.components.RangeSlider( abs_range, safe_range, decimals=decimals, orientation=orientation) rangeslider.show() qtbot.addWidget(rangeslider) # test ranges & values assert(rangeslider.minimum() == abs_range[0]) assert(rangeslider.maximum() == abs_range[1]) assert(rangeslider.low == safe_range[0]) assert(rangeslider.high == safe_range[1]) for i in range(n_samples): min, max = generic_saferange() print(min, max) with qtbot.waitSignal(rangeslider.valueChanged, timeout=1000) as blocker: rangeslider.setHigh(max) assert(rangeslider.high == max) rangeslider.setLow(min) assert(rangeslider.low == min)
[docs]def test_rangeslider_minmax(qtbot, generic_minmax, generic_saferange): abs_range = generic_minmax() safe_range = generic_saferange() decimals = 5 orientation = QtCore.Qt.Orientation.Horizontal rangeslider = widgets.components.RangeSlider( abs_range, safe_range, decimals=decimals, orientation=orientation) rangeslider.show() qtbot.addWidget(rangeslider) for i in range(n_samples): abs_min, abs_max = generic_minmax() safe_min, safe_max = generic_saferange() #pdb.set_trace() # Set min and max and test they were set correctly rangeslider.setMinimum(abs_min) assert(rangeslider.minimum() == abs_min) rangeslider.setMaximum(abs_max) assert(rangeslider.maximum() == abs_max) # set low and high and test they were set correctly rangeslider.setHigh(safe_max) assert(rangeslider.high == safe_max) rangeslider.setLow(safe_min) assert(rangeslider.low == safe_min) # try to set low and high outside of max rangeslider.setHigh(abs_max + 1) assert(rangeslider.high == rangeslider.maximum()) rangeslider.setLow(abs_min - 1) assert(rangeslider.low == rangeslider.minimum()) # try to set low higher and high and vice versa midpoint = np.round(np.mean([abs_min, abs_max]), decimals) highpoint = np.round(midpoint-1, decimals) lowpoint = np.round(midpoint-1-(10**-decimals), decimals) rangeslider.setLow(midpoint) rangeslider.setHigh(highpoint) assert(rangeslider.high == highpoint) assert(rangeslider.low == lowpoint) highpoint = np.round(midpoint+1+(10**-decimals), decimals) lowpoint = np.round(midpoint + 1, decimals) rangeslider.setHigh(midpoint) rangeslider.setLow(lowpoint) assert(rangeslider.low == lowpoint) assert(rangeslider.high == highpoint)