From 5f37dc12bb2854ae3bb9010ae392aa00d1c5a239 Mon Sep 17 00:00:00 2001 From: Roman Tolchenov <roman.tolchenov@stfc.ac.uk> Date: Mon, 17 Dec 2018 10:58:15 +0000 Subject: [PATCH] A working workbench gui test. Re #24027 --- buildconfig/CMake/FindPyUnitTest.cmake | 8 +++- qt/applications/workbench/CMakeLists.txt | 15 +++++++ .../workbench/workbench/test/runner.py | 16 ++++++++ .../test/test_fit_interactive_tool.py | 41 +++++++++++++++++++ .../mantidqt/utils/qt/test/gui_test_runner.py | 9 ++-- .../mantidqt/utils/qt/test/gui_window_test.py | 36 ++++++++++++++++ .../mantidqt/widgets/fitpropertybrowser.py | 9 ++-- 7 files changed, 126 insertions(+), 8 deletions(-) create mode 100644 qt/applications/workbench/workbench/test/runner.py create mode 100644 qt/applications/workbench/workbench/test/test_fit_interactive_tool.py diff --git a/buildconfig/CMake/FindPyUnitTest.cmake b/buildconfig/CMake/FindPyUnitTest.cmake index 5ac987e2e62..20725240b3f 100644 --- a/buildconfig/CMake/FindPyUnitTest.cmake +++ b/buildconfig/CMake/FindPyUnitTest.cmake @@ -24,7 +24,13 @@ function ( PYUNITTEST_ADD_TEST _test_src_dir _testname_prefix ) if ( WIN32 ) set ( _test_runner ${_test_runner}.bat ) endif () - set ( _test_runner_module ${CMAKE_SOURCE_DIR}/Framework/PythonInterface/test/testhelpers/testrunner.py ) + + if ( NOT PYUNITTEST_RUNNER ) + set ( _test_runner_module ${CMAKE_SOURCE_DIR}/Framework/PythonInterface/test/testhelpers/testrunner.py ) + else () + set ( _test_runner_module ${PYUNITTEST_RUNNER} ) + endif() + # Environment if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows") diff --git a/qt/applications/workbench/CMakeLists.txt b/qt/applications/workbench/CMakeLists.txt index 323ecee823c..6da9e267956 100644 --- a/qt/applications/workbench/CMakeLists.txt +++ b/qt/applications/workbench/CMakeLists.txt @@ -29,9 +29,24 @@ set ( TEST_FILES workbench/widgets/plotselector/test/test_plotselector_view.py ) +set ( WORKBENCH_TEST_PY_FILES + workbench/test/test_fit_interactive_tool.py +) + set ( PYUNITTEST_RUN_SERIAL ON ) set ( PYUNITTEST_QT_API pyqt5) pyunittest_add_test ( ${CMAKE_CURRENT_SOURCE_DIR} workbench ${TEST_FILES} ) + +if ( CMAKE_GENERATOR MATCHES "Visual Studio" OR CMAKE_GENERATOR MATCHES "Xcode" ) + set ( PYUNITTEST_RUNNER ${CMAKE_BINARY_DIR}/bin/$<CONFIG>/workbench-script.pyw -x) +else() + set ( PYUNITTEST_RUNNER ${CMAKE_BINARY_DIR}/bin/workbench.py -xq) +endif() + +pyunittest_add_test ( ${CMAKE_CURRENT_SOURCE_DIR} + workbench_gui ${WORKBENCH_TEST_PY_FILES} +) + # Not installed yet... diff --git a/qt/applications/workbench/workbench/test/runner.py b/qt/applications/workbench/workbench/test/runner.py new file mode 100644 index 00000000000..b315ffb1b1c --- /dev/null +++ b/qt/applications/workbench/workbench/test/runner.py @@ -0,0 +1,16 @@ +# Mantid Repository : https://github.com/mantidproject/mantid +# +# Copyright © 2017 ISIS Rutherford Appleton Laboratory UKRI, +# NScD Oak Ridge National Laboratory, European Spallation Source +# & Institut Laue - Langevin +# SPDX - License - Identifier: GPL - 3.0 + +# This file is part of the mantid workbench. +# +# +from workbench.plotting.qappthreadcall import QAppThreadCall + + +def run_gui_test(class_name): + def test(): + class_name().run_all_tests() + QAppThreadCall(test)() diff --git a/qt/applications/workbench/workbench/test/test_fit_interactive_tool.py b/qt/applications/workbench/workbench/test/test_fit_interactive_tool.py new file mode 100644 index 00000000000..99cd29126e4 --- /dev/null +++ b/qt/applications/workbench/workbench/test/test_fit_interactive_tool.py @@ -0,0 +1,41 @@ +from __future__ import print_function + +from qtpy.QtCore import QPoint + +from mantid.simpleapi import * +from mantidqt.utils.qt.test.gui_window_test import * + +from workbench.plotting.functions import plot +from workbench.plotting.globalfiguremanager import GlobalFigureManager +from workbench.test.runner import run_gui_test + + +class TestFitPropertyBrowser(WorkbenchGuiTest): + + def test_fit_range(self): + ws = Load(r'irs26176_graphite002_conv_1LFixF_s0_to_9_Result.nxs', OutputWorkspace='ws') + plot([ws], [1]) + manager = GlobalFigureManager.get_active() + w = manager.window + trigger_action(find_action_with_text(w, 'Fit')) + yield 0.1 + fit_browser = manager.fit_browser + start_x = fit_browser.startX() + start_x_pxl = fit_browser.tool.fit_start_x.get_x_in_pixels() + end_x = fit_browser.endX() + end_x_pxl = fit_browser.tool.fit_end_x.get_x_in_pixels() + self.assertAlmostEqual(start_x, 0.5318, 4) + self.assertAlmostEqual(end_x, 1.8186, 4) + pos = w._canvas.geometry().center() + canvas = w.childAt(pos) + pos.setX(fit_browser.tool.fit_start_x.get_x_in_pixels()) + new_pos = pos + QPoint(100, 0) + yield drag_mouse(canvas, pos, new_pos) + self.assertAlmostEqual(fit_browser.startX(), start_x + 100.0 / (end_x_pxl - start_x_pxl) * (end_x - start_x), 2) + pos.setX(fit_browser.tool.fit_end_x.get_x_in_pixels()) + new_pos = pos - QPoint(30, 0) + yield drag_mouse(canvas, pos, new_pos) + self.assertAlmostEqual(fit_browser.endX(), end_x - 30.0 / (end_x_pxl - start_x_pxl) * (end_x - start_x), 2) + + +run_gui_test(TestFitPropertyBrowser) diff --git a/qt/python/mantidqt/utils/qt/test/gui_test_runner.py b/qt/python/mantidqt/utils/qt/test/gui_test_runner.py index 087dd39c39f..1999fc3ab26 100644 --- a/qt/python/mantidqt/utils/qt/test/gui_test_runner.py +++ b/qt/python/mantidqt/utils/qt/test/gui_test_runner.py @@ -80,7 +80,7 @@ class ScriptRunner(object): try: if self.script_iter is None: if self.close_on_finish: - QMetaObject.invokeMethod(self.widget, 'close', Qt.QueuedConnection) + app.exit() return # Run test script until the next 'yield' ret = self.script_iter.next() @@ -99,10 +99,11 @@ class ScriptRunner(object): self.script_iter = None self.script_timer.stop() if self.close_on_finish: - QMetaObject.invokeMethod(self.widget, 'close', Qt.QueuedConnection) + app.exit() except Exception as e: - self.widget.close() traceback.print_exc() + if self.close_on_finish: + app.exit(1) self.error = e @@ -158,7 +159,7 @@ def open_in_window(widget_or_name, script, attach_debugger=True, pause=0, close_ script_runner = None if script is not None: try: - timer = QTimer() + timer = QTimer(app) script_runner = ScriptRunner(script, widget, close_on_finish=close_on_finish, script_timer=timer, is_cli=is_cli) if pause != 0: timer.setInterval(pause * 1000) diff --git a/qt/python/mantidqt/utils/qt/test/gui_window_test.py b/qt/python/mantidqt/utils/qt/test/gui_window_test.py index 16135f5b23f..d1c34c97f9b 100644 --- a/qt/python/mantidqt/utils/qt/test/gui_window_test.py +++ b/qt/python/mantidqt/utils/qt/test/gui_window_test.py @@ -14,6 +14,28 @@ from unittest import TestCase from mantidqt.utils.qt.test.gui_test_runner import open_in_window from qtpy.QtWidgets import QPushButton, QMenu, QAction, QApplication from qtpy.QtCore import Qt, QMetaObject +from qtpy.QtTest import QTest + + +def trigger_action(action): + QMetaObject.invokeMethod(action, 'trigger', Qt.QueuedConnection) + + +def find_action_with_text(widget, text): + for action in widget.findChildren(QAction): + if action.text() == text: + return action + raise RuntimeError("Couldn't find action with text \"{}\"".format(text)) + + +def drag_mouse(widget, from_pos, to_pos): + QTest.mousePress(widget, Qt.LeftButton, Qt.NoModifier, from_pos) + yield + QTest.mouseMove(widget, from_pos) + yield 0.1 + QTest.mouseMove(widget, to_pos) + yield + QTest.mouseRelease(widget, Qt.LeftButton, Qt.NoModifier, to_pos) class GuiTestBase(object): @@ -46,6 +68,10 @@ class GuiTestBase(object): open_in_window(self.create_widget, self._call_test_method, attach_debugger=attach_debugger, pause=pause, close_on_finish=close_on_finish) + def run_all_tests(self): + for test in inspect.getmembers(self, is_test_method): + self.run_test(method=test[0], close_on_finish=True) + def get_child(self, child_class, name): children = self.widget.findChildren(child_class, name) if len(children) == 0: @@ -115,3 +141,13 @@ class GuiWindowTest(TestCase, GuiTestBase): wrapped_name = '_' + name setattr(cls, wrapped_name, test[1]) setattr(cls, name, make_test_wrapper(wrapped_name)) + + def runTest(self): + pass + + +class WorkbenchGuiTest(GuiWindowTest): + + def create_widget(self): + qapp = QApplication.instance() + return qapp.activeWindow() diff --git a/qt/python/mantidqt/widgets/fitpropertybrowser.py b/qt/python/mantidqt/widgets/fitpropertybrowser.py index 7541aa831b0..78e76b6bf78 100644 --- a/qt/python/mantidqt/widgets/fitpropertybrowser.py +++ b/qt/python/mantidqt/widgets/fitpropertybrowser.py @@ -85,9 +85,12 @@ class VerticalMarker(QObject): vertices[1] = self.x, y1 self.ax.draw_artist(self.patch) - def is_above(self, x): + def get_x_in_pixels(self): x_pixels, _ = self.patch.get_transform().transform((self.x, 0)) - return np.abs(x_pixels - x) < 3 + return x_pixels + + def is_above(self, x): + return np.abs(self.get_x_in_pixels() - x) < 3 def on_click(self, x): if self.is_above(x): @@ -116,7 +119,7 @@ class FitInteractiveTool(QObject): ax = canvas.figure.get_axes()[0] self.ax = ax xlim = ax.get_xlim() - dx = (xlim[1] - xlim[0]) / 5. + dx = (xlim[1] - xlim[0]) / 20. start_x = xlim[0] + dx end_x = xlim[1] - dx self.fit_start_x = VerticalMarker(canvas, start_x, 'green') -- GitLab