Extract of a service layer for TestSetController

This commit is contained in:
2026-04-18 13:02:33 +02:00
parent ebb6820a27
commit 93f0fd3ee4
3 changed files with 117 additions and 48 deletions

View File

@@ -0,0 +1,71 @@
from interpreter.utils.test_ctrl import TestSetController
class TestControllerService:
"""Typed interface over TestSetController, decoupling the UI from raw RPC strings."""
def __init__(self, controller: TestSetController) -> None:
self._ctrl = controller
# --- Lifecycle ---
def stop(self) -> None:
self._ctrl.control("stop")
def close(self) -> None:
self._ctrl.control("close")
def execute(self) -> None:
self._ctrl.control("execute")
def loaded(self, timeout: float = None) -> bool:
return self._ctrl.control("loaded", timeout=timeout)
def clear(self) -> None:
self._ctrl.clear()
# --- Execution control ---
def pause(self) -> None:
self._ctrl.control("pause")
def cont(self) -> None:
self._ctrl.control("cont")
# --- Breakpoints ---
def add_breakpoint(self, item_id) -> None:
self._ctrl.control("add_breakpoint", item_id=item_id)
def del_breakpoint(self, item_id) -> None:
self._ctrl.control("del_breakpoint", item_id=item_id)
# --- Tree data ---
def tree(self) -> dict:
return self._ctrl.control("tree")
# --- Item state ---
def get_enabled_state(self, item_id) -> bool:
return self._ctrl.control("enabled_state", item_id=item_id)
def set_enabled_state(self, item_id, state: bool, unitary: bool = False) -> None:
self._ctrl.control("set_enabled_state", item_id=item_id, enabled_state=state, unitary=unitary)
def check_uncheck_all(self, checked: bool) -> None:
self._ctrl.control("check_uncheck_all", checked=checked)
def get_skipped_state(self, item_id) -> bool:
return self._ctrl.control("skipped_state", item_id=item_id)
# --- Configuration ---
def process_param(self, param: str) -> str:
return self._ctrl.control("process_param", param=param)
def set_report(self, rep_path: str, rep_type: str, pattern: list) -> None:
self._ctrl.control("report", rep_path=rep_path, rep_type=rep_type, pattern=pattern)
def set_test_outputs(self, outputs: list) -> None:
self._ctrl.control("set_test_outputs", outputs=outputs)

View File

@@ -11,7 +11,7 @@ from time import (time)
from main_win.test_tree_items.common import (TEST_COLS, TEST_COLS_WITH_TIME)
from lib.tum_except import (ETUMFileError, ETUMSyntaxError)
from interpreter.utils.test_ctrl import TestSetController
from main_win.test_controller_service import TestControllerService
from main_win.test_tree_items.test_tree_git import QTestTreeItemGit
# to be removed in the future and replaced by a more "sexy" mechanism
@@ -122,11 +122,11 @@ class QTestTree(QTreeWidget):
self.header().sectionResized.connect(self.resized)
def updateTestSetItemState(self, tree_item, tst_ctrl: TestSetController, state, unitary=False):
def updateTestSetItemState(self, tree_item, tst_ctrl: TestControllerService, state, unitary=False):
id = tree_item.id
tst_ctrl.control("set_enabled_state", item_id=id, enabled_state=state, unitary=unitary)
tst_ctrl.set_enabled_state(id, state, unitary=unitary)
def updateTreeCheckState(self, tree_item, tst_ctrl: TestSetController):
def updateTreeCheckState(self, tree_item, tst_ctrl: TestControllerService):
# treat the case of the invisible root
if tree_item is self.root:
for i in range(self.root.childCount()):
@@ -137,9 +137,9 @@ class QTestTree(QTreeWidget):
self.updateTestSetItemState(tree_item, tst_ctrl, state)
self.synchronizeEnabledState(tst_ctrl)
def checkUncheckAll(self, tst_ctrl: TestSetController, isChecked):
def checkUncheckAll(self, tst_ctrl: TestControllerService, isChecked):
# test_set.enableDisableAll(test_set.rootItem(), isChecked)
tst_ctrl.control("check_uncheck_all", checked=isChecked)
tst_ctrl.check_uncheck_all(isChecked)
self.synchronizeEnabledState(tst_ctrl)
def __foldRecursively(self, tree_item, is_fold):
@@ -158,10 +158,10 @@ class QTestTree(QTreeWidget):
def foldAll(self, is_fold):
self.__foldRecursively(self.root, is_fold)
def __synchronizeEnabledStateRecursively(self, tree_item, tst_ctrl: TestSetController):
def __synchronizeEnabledStateRecursively(self, tree_item, tst_ctrl: TestControllerService):
for i in range(tree_item.childCount()):
id = tree_item.child(i).id
checked = tst_ctrl.control("enabled_state", item_id=id)
checked = tst_ctrl.get_enabled_state(id)
if checked:
tree_item.child(i).setCheckState(self.cols['name']['index'],
Qt.Checked)
@@ -171,14 +171,14 @@ class QTestTree(QTreeWidget):
self.__synchronizeEnabledStateRecursively(
tree_item.child(i), tst_ctrl)
def updateTreeSkipState(self, tst_ctrl: TestSetController):
def updateTreeSkipState(self, tst_ctrl: TestControllerService):
self.__updateTreeSkipStateRecursively(self.root, tst_ctrl)
def __updateTreeSkipStateRecursively(self, tree_item, tst_ctrl: TestSetController):
def __updateTreeSkipStateRecursively(self, tree_item, tst_ctrl: TestControllerService):
for i in range(tree_item.childCount()):
id = tree_item.child(i).id
# skipped = test_set.getSkippedState(id)
skipped = tst_ctrl.control("skipped_state", item_id=id)
skipped = tst_ctrl.get_skipped_state(id)
if skipped:
tree_item.child(i).setDisabled(True)
tree_item.child(i).setExpanded(False)
@@ -195,7 +195,7 @@ class QTestTree(QTreeWidget):
tree_item.child(i)._is_skipped = True
self.__skipRecursively(tree_item.child(i))
def synchronizeEnabledState(self, tst_ctrl: TestSetController):
def synchronizeEnabledState(self, tst_ctrl: TestControllerService):
self.__synchronizeEnabledStateRecursively(self.root, tst_ctrl)
def __enableRecursively(self, tree_item):
@@ -347,7 +347,7 @@ class QTestTree(QTreeWidget):
if root.child(i).childCount() > 0:
self.addCheckBoxes(root.child(i))
def showCheckBoxes(self, checklist, tst_ctrl: TestSetController):
def showCheckBoxes(self, checklist, tst_ctrl: TestControllerService):
self.addCheckBoxes()
self.restoreCheckList(checklist, tst_ctrl)
@@ -382,12 +382,12 @@ class QTestTree(QTreeWidget):
checklist.append((i.checkState(0) == Qt.Checked))
return checklist
def restoreCheckList(self, checklist, tst_ctrl: TestSetController):
def restoreCheckList(self, checklist, tst_ctrl: TestControllerService):
itemlist = reversed(list(self.root))
for item in itemlist:
state = checklist.pop(len(checklist)-1)
if item is not self.root:
skipped = tst_ctrl.control("skipped_state", item_id=item.id)
skipped = tst_ctrl.get_skipped_state(item.id)
if skipped:
item.setDisabled(True)
for i in range(item.childCount()):

View File

@@ -39,6 +39,7 @@ from main_win.test_run.thread_output import ThreadTestOutput
from lib.string_queue import StringQueue
from interpreter.process import TestProcess
from interpreter.utils.test_ctrl import TestSetController
from main_win.test_controller_service import TestControllerService
from interpreter.utils.icons import icon_prefix
from main_win.test_run.outlog import OutLog
@@ -181,6 +182,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.debug = debug
self.test_proc = None
self.ts_controller = None
self.test_service = None
self.threadTestStatus = None
self._test_started = False
self._test_paused = False
@@ -380,7 +382,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
checkList = prefs.settings.value(prefs.SettingsItem("checkList", list), [])
if checkList is not None:
if len(checkList) == self.treeTests.getItemCount():
self.treeTests.restoreCheckList(checkList, self.ts_controller)
self.treeTests.restoreCheckList(checkList, self.test_service)
else:
tm.print_info(
@@ -436,11 +438,13 @@ class MainWindow(QMainWindow, Ui_MainWindow):
and self.test_proc.is_alive()
and (self.ts_controller is not None)
):
self.ts_controller.control("stop")
self.ts_controller.control("close")
self.test_service.stop()
self.test_service.close()
self.test_proc.join()
del self.test_proc
self.test_proc = None
del self.test_service
self.test_service = None
del self.ts_controller
self.ts_controller = None
@@ -466,12 +470,12 @@ class MainWindow(QMainWindow, Ui_MainWindow):
# Test to be paused
if self._test_started:
if not self._test_paused:
self.ts_controller.control("pause")
self.test_service.pause()
self.startPauseTimer()
else:
# Test to be continued
self.ts_controller.control("cont")
self.test_service.cont()
self.timerPause.stop()
self.timerPause.state = False
self.on_timerPause()
@@ -488,9 +492,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
try:
if not os.path.isabs(log_file):
default_path = prefs.settings.log_path
default_path = self.ts_controller.control(
"process_param", param=default_path
)
default_path = self.test_service.process_param(default_path)
log_file = os.path.join(default_path, log_file)
# if the directory does not exist
if not os.path.exists(os.path.dirname(log_file)):
@@ -521,15 +523,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.logFileName = self.logFileHandler.name
# Report file definition
rep_file = self.ts_controller.control(
"process_param", param=self.reportFileName
)
self.ts_controller.control(
"report",
rep_path=rep_file,
rep_type=self.report_type,
pattern=self.report_pattern,
)
rep_file = self.test_service.process_param(self.reportFileName)
self.test_service.set_report(rep_file, self.report_type, self.report_pattern)
self.adaptInterfaceDuringTest()
self.treeTests.clearAllStatus()
try:
@@ -539,9 +534,9 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.timer.setInterval(100)
self.timer.start()
# Add the log file to the std test_outputs
self.ts_controller.control("set_test_outputs", outputs=[self.logFileName])
self.test_service.set_test_outputs([self.logFileName])
# Launch the test
self.ts_controller.control("execute")
self.test_service.execute()
except:
print(traceback.format_exc())
self.restoreInterfaceAfterTest()
@@ -566,7 +561,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
@Slot()
def on_actionStop_test_triggered(self):
self.ts_controller.control("stop")
self.test_service.stop()
def save_settings(self):
prefs.settings.set_value(
@@ -709,9 +704,9 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.disconnect_signals()
try:
if state == Qt.Checked:
self.treeTests.checkUncheckAll(self.ts_controller, True)
self.treeTests.checkUncheckAll(self.test_service, True)
elif state == Qt.Unchecked:
self.treeTests.checkUncheckAll(self.ts_controller, False)
self.treeTests.checkUncheckAll(self.test_service, False)
finally:
self.reconnect_signals()
@@ -719,7 +714,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.checkSelect.setCheckState(Qt.PartiallyChecked)
self.disconnect_signals()
try:
self.treeTests.updateTreeCheckState(item, self.ts_controller)
self.treeTests.updateTreeCheckState(item, self.test_service)
finally:
self.reconnect_signals()
@@ -772,9 +767,9 @@ class MainWindow(QMainWindow, Ui_MainWindow):
isBrkpointCol = item.setBreakpointIfCol(col)
if isBrkpointCol:
if item.isBreakpoint():
self.ts_controller.control("add_breakpoint", item_id=item.id)
self.test_service.add_breakpoint(item.id)
else:
self.ts_controller.control("del_breakpoint", item_id=item.id)
self.test_service.del_breakpoint(item.id)
return
s = sys.platform
@@ -789,9 +784,9 @@ class MainWindow(QMainWindow, Ui_MainWindow):
item = self.treeTests.currentItem()
add_breakpoint = item.setBreakpoint()
if add_breakpoint:
self.ts_controller.control("add_breakpoint", item_id=item.id)
self.test_service.add_breakpoint(item.id)
else:
self.ts_controller.control("del_breakpoint", item_id=item.id)
self.test_service.del_breakpoint(item.id)
def on_F1Pressed(self):
item = self.treeTests.currentItem()
@@ -919,7 +914,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
else:
# production mode
if hasattr(self, "treeTests"):
self.treeTests.checkUncheckAll(self.ts_controller, True)
self.treeTests.checkUncheckAll(self.test_service, True)
self.disconnect_signals()
self.treeTests.removeCheckBoxes()
self.reconnect_signals()
@@ -1005,6 +1000,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.testFile = None
self.ts_controller = TestSetController()
self.test_service = TestControllerService(self.ts_controller)
self.test_proc = TestProcess(
file_name,
self.status_queue,
@@ -1016,14 +1012,16 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.test_proc.start()
while self.test_proc.is_alive():
try:
if self.ts_controller.control("loaded", timeout=1.0):
if self.test_service.loaded(timeout=1.0):
break
except Empty:
self.ts_controller.clear()
self.test_service.clear()
if not self.test_proc.is_alive():
del self.test_proc
self.test_proc = None
del self.test_service
self.test_service = None
del self.ts_controller
self.ts_controller = None
@@ -1031,13 +1029,13 @@ class MainWindow(QMainWindow, Ui_MainWindow):
"Test could not be loaded (test process crashed for any reason)"
)
test_data = self.ts_controller.control("tree")
test_data = self.test_service.tree()
self.treeTests.clear()
self.treeTests.loadTestRecursively(
self.treeTests.invisibleRootItem(), test_data
)
self.treeTests.setFoldDefault()
self.treeTests.updateTreeSkipState(self.ts_controller)
self.treeTests.updateTreeSkipState(self.test_service)
self.checkSelect.setChecked(True)
self.testFile = file_name
@@ -1115,7 +1113,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.logSettingsBox.setEnabled(True)
if prefs.settings.show_checkboxes:
self.checkSelect.setEnabled(True)
self.treeTests.showCheckBoxes(self._checklist, self.ts_controller)
self.treeTests.showCheckBoxes(self._checklist, self.test_service)
self.checkFold.setEnabled(True)
self.treeTests.setChildrenEnabled()
self.reconnect_signals()