Reload test without restarting testium (closes #18)

Replace os.execv restart in actionRefresh with file_manager.reload(),
leveraging the subprocess architecture so py_func modules are freshly
imported on each reload. Add a modal progress dialog with step labels
during loading. Fix checkbox reappearing on breakpoint with
show_checkboxes OFF.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-18 15:23:53 +02:00
parent 67c879ab10
commit 7383820aba
2 changed files with 34 additions and 18 deletions

View File

@@ -3,7 +3,8 @@ import sys
import traceback import traceback
from queue import Empty from queue import Empty
from PySide6.QtWidgets import QApplication, QFileDialog from PySide6.QtCore import Qt
from PySide6.QtWidgets import QApplication, QFileDialog, QProgressDialog
from interpreter.process import TestProcess from interpreter.process import TestProcess
from interpreter.utils.test_ctrl import TestSetController from interpreter.utils.test_ctrl import TestSetController
@@ -44,9 +45,25 @@ class TestFileManager:
self.load(file_name) self.load(file_name)
w.reconnect_signals() w.reconnect_signals()
def _make_progress(self, w):
progress = QProgressDialog("Starting test process…", None, 0, 0, w)
progress.setWindowTitle("Loading")
progress.setWindowFlags(Qt.Dialog | Qt.CustomizeWindowHint | Qt.WindowTitleHint)
progress.setWindowModality(Qt.WindowModal)
progress.setMinimumDuration(0)
progress.setMinimumWidth(320)
progress._force_close = False
progress.closeEvent = lambda e: e.accept() if progress._force_close else e.ignore()
return progress
def _close_progress(self, progress):
progress._force_close = True
progress.close()
def load(self, file_name: str) -> bool: def load(self, file_name: str) -> bool:
"""Load a test file. Returns True on success, False otherwise.""" """Load a test file. Returns True on success, False otherwise."""
w = self._win w = self._win
progress = None
try: try:
if not file_name: if not file_name:
raise ETUMFileError("No file to load") raise ETUMFileError("No file to load")
@@ -59,6 +76,10 @@ class TestFileManager:
if not os.path.isfile(file_name): if not os.path.isfile(file_name):
raise ETUMFileError("Could not find %s file" % file_name) raise ETUMFileError("Could not find %s file" % file_name)
progress = self._make_progress(w)
progress.show()
QApplication.processEvents()
w.testFile = None w.testFile = None
w.ts_controller = TestSetController() w.ts_controller = TestSetController()
w.test_service = TestControllerService(w.ts_controller) w.test_service = TestControllerService(w.ts_controller)
@@ -71,12 +92,14 @@ class TestFileManager:
self._defaults_for_process(), self._defaults_for_process(),
) )
w.test_proc.start() w.test_proc.start()
progress.setLabelText("Loading test file…")
while w.test_proc.is_alive(): while w.test_proc.is_alive():
try: try:
if w.test_service.loaded(timeout=1.0): if w.test_service.loaded(timeout=0.05):
break break
except Empty: except Empty:
w.test_service.clear() w.test_service.clear()
QApplication.processEvents()
if not w.test_proc.is_alive(): if not w.test_proc.is_alive():
del w.test_proc del w.test_proc
@@ -89,9 +112,14 @@ class TestFileManager:
"Test could not be loaded (test process crashed for any reason)" "Test could not be loaded (test process crashed for any reason)"
) )
progress.setLabelText("Building test tree…")
QApplication.processEvents()
test_data = w.test_service.tree() test_data = w.test_service.tree()
w.treeTests.clear() w.treeTests.clear()
QApplication.processEvents()
w.treeTests.loadTestRecursively(w.treeTests.invisibleRootItem(), test_data) w.treeTests.loadTestRecursively(w.treeTests.invisibleRootItem(), test_data)
self._close_progress(progress)
progress = None
w.treeTests.setFoldDefault() w.treeTests.setFoldDefault()
w.treeTests.updateTreeSkipState(w.test_service) w.treeTests.updateTreeSkipState(w.test_service)
@@ -109,6 +137,8 @@ class TestFileManager:
w.show_checkboxes() w.show_checkboxes()
return True return True
except: except:
if progress is not None:
self._close_progress(progress)
w.statusBar().showMessage("No test file could be loaded", 10000) w.statusBar().showMessage("No test file could be loaded", 10000)
w.treeTests.clear() w.treeTests.clear()
print(traceback.format_exc()) print(traceback.format_exc())

View File

@@ -8,7 +8,6 @@ from multiprocessing import Queue
from queue import Empty from queue import Empty
from threading import Thread from threading import Thread
import shutil import shutil
import ast
# Qt # Qt
from PySide6 import QtGui, QtWidgets from PySide6 import QtGui, QtWidgets
@@ -471,21 +470,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
@Slot() @Slot()
def on_actionRefresh_test_triggered(self): def on_actionRefresh_test_triggered(self):
self.on_exiting() if self.testFile:
args = [] self.file_manager.reload(self.testFile)
if not hasattr(sys, "frozen"):
args += [sys.executable]
args += [sys.argv[0]]
if len(self.defines) > 0:
for k, v in self.defines.items():
try:
val = ast.literal_eval(v)
except:
val = v
args += ["-d", f"{k}={val}"]
if (self.testFile is not None) and (isinstance(self.testFile, str)):
args += [self.testFile]
os.execv(sys.executable, args)
@Slot() @Slot()
def on_actionSave_report_triggered(self): def on_actionSave_report_triggered(self):