Add auto_result param to dialog items for automated validation

Each dialog test item now accepts an optional auto_result parameter
(ok/cancel/yes/no) and auto_value for text dialogs. When set, the dialog
window opens, stays visible 2 seconds, then closes automatically with the
specified result — allowing the validation suite to run without manual
interaction.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-24 10:07:07 +02:00
parent de143b6cc3
commit d26b60435b
16 changed files with 83 additions and 15 deletions

View File

@@ -5,7 +5,7 @@ from itertools import chain
from PySide6.QtGui import QIcon, QPixmap from PySide6.QtGui import QIcon, QPixmap
from PySide6.QtWidgets import QApplication, QDialog, QDialogButtonBox from PySide6.QtWidgets import QApplication, QDialog, QDialogButtonBox
from PySide6.QtCore import Qt, QSettings, QSize from PySide6.QtCore import Qt, QSettings, QTimer, QSize
from PySide6.QtGui import QFont, QFontInfo from PySide6.QtGui import QFont, QFontInfo
from PySide6.QtWidgets import QTreeWidgetItem from PySide6.QtWidgets import QTreeWidgetItem
@@ -207,6 +207,9 @@ def main(args, conn=None):
d.connect_checked() d.connect_checked()
d.choicesView.setFocus() d.choicesView.setFocus()
auto_result = args[4] if len(args) > 4 else None
if auto_result is not None:
QTimer.singleShot(2000, lambda: d.accept() if auto_result.lower() == 'ok' else d.reject())
dres = d.exec() dres = d.exec()
if dres == QDialog.Rejected: if dres == QDialog.Rejected:

View File

@@ -1,6 +1,6 @@
import sys import sys
from PySide6.QtCore import (Qt) from PySide6.QtCore import Qt, QTimer
from PySide6.QtWidgets import (QApplication, QDialog) from PySide6.QtWidgets import (QApplication, QDialog)
from PySide6 import (QtGui) from PySide6 import (QtGui)
@@ -38,6 +38,10 @@ def main(args, conn):
d.labelImage.setPixmap(QtGui.QPixmap.fromImage(image2)) d.labelImage.setPixmap(QtGui.QPixmap.fromImage(image2))
auto_result = args[3] if len(args) > 3 else None
if auto_result is not None:
QTimer.singleShot(2000, lambda: d.accept() if auto_result.lower() == 'ok' else d.reject())
dres = d.exec() dres = d.exec()
if dres == QDialog.Rejected: if dres == QDialog.Rejected:

View File

@@ -2,7 +2,7 @@ import sys
from multiprocessing import freeze_support from multiprocessing import freeze_support
from PySide6.QtWidgets import (QApplication, QMessageBox) from PySide6.QtWidgets import (QApplication, QMessageBox)
from PySide6.QtCore import Qt from PySide6.QtCore import Qt, QTimer
def main(args): def main(args):
@@ -15,6 +15,8 @@ def main(args):
msg.setText(args[1]) msg.setText(args[1])
msg.setIcon(QMessageBox.Information) msg.setIcon(QMessageBox.Information)
msg.setStandardButtons(QMessageBox.Ok) msg.setStandardButtons(QMessageBox.Ok)
if len(args) > 2:
QTimer.singleShot(2000, lambda: msg.button(QMessageBox.Ok).click())
msg.exec() msg.exec()
if hasattr(sys, "frozen"): if hasattr(sys, "frozen"):

View File

@@ -2,7 +2,7 @@ import sys
import os import os
from PySide6.QtWidgets import (QApplication, QDialog) from PySide6.QtWidgets import (QApplication, QDialog)
from PySide6.QtCore import (Qt) from PySide6.QtCore import Qt, QTimer
from interpreter.test_items.dialog_note_files import dialog_note_win from interpreter.test_items.dialog_note_files import dialog_note_win
from multiprocessing import freeze_support from multiprocessing import freeze_support
@@ -23,6 +23,14 @@ def main(args, conn=None):
d.setWindowTitle(args[0]) d.setWindowTitle(args[0])
d.labelDialog.setText(args[1]) d.labelDialog.setText(args[1])
d.textEdit.setFocus() d.textEdit.setFocus()
auto_result = args[2] if len(args) > 2 else None
if auto_result is not None:
auto_value = args[3] if len(args) > 3 else None
def _auto_close():
if auto_value is not None:
d.textEdit.setPlainText(auto_value)
d.accept() if auto_result.lower() == 'ok' else d.reject()
QTimer.singleShot(2000, _auto_close)
dres = d.exec() dres = d.exec()
if dres == QDialog.Rejected: if dres == QDialog.Rejected:

View File

@@ -2,7 +2,7 @@ import sys
from multiprocessing import freeze_support from multiprocessing import freeze_support
from PySide6.QtWidgets import (QApplication, QMessageBox) from PySide6.QtWidgets import (QApplication, QMessageBox)
from PySide6.QtCore import Qt from PySide6.QtCore import Qt, QTimer
def main(args, conn): def main(args, conn):
@@ -16,6 +16,10 @@ def main(args, conn):
msg.setText(args[1]) msg.setText(args[1])
msg.setIcon(QMessageBox.Question) msg.setIcon(QMessageBox.Question)
msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No) msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
auto_result = args[2] if len(args) > 2 else None
if auto_result is not None:
btn = QMessageBox.Yes if auto_result.lower() == 'yes' else QMessageBox.No
QTimer.singleShot(2000, lambda: msg.button(btn).click())
reply = msg.exec() reply = msg.exec()
conn.send(reply) conn.send(reply)
except Exception as e: except Exception as e:

View File

@@ -2,7 +2,7 @@ import sys
import os import os
from PySide6.QtWidgets import (QApplication, QDialog) from PySide6.QtWidgets import (QApplication, QDialog)
from PySide6.QtCore import (Qt) from PySide6.QtCore import Qt, QTimer
from interpreter.test_items.dialog_value_files import dialog_value_win from interpreter.test_items.dialog_value_files import dialog_value_win
from multiprocessing import freeze_support from multiprocessing import freeze_support
@@ -25,6 +25,14 @@ def main(args, conn=None):
d.labelDialog.setText(args[1]) d.labelDialog.setText(args[1])
d.lineEdit.setText(args[2]) d.lineEdit.setText(args[2])
d.lineEdit.setFocus() d.lineEdit.setFocus()
auto_result = args[3] if len(args) > 3 else None
if auto_result is not None:
auto_value = args[4] if len(args) > 4 else None
def _auto_close():
if auto_value is not None:
d.lineEdit.setText(auto_value)
d.accept() if auto_result.lower() == 'ok' else d.reject()
QTimer.singleShot(2000, _auto_close)
dres = d.exec() dres = d.exec()
if dres == QDialog.Rejected: if dres == QDialog.Rejected:

View File

@@ -17,13 +17,16 @@ class TestItemChoicesDialog(TestItemDialogBase):
self._question = self._prms.getParam("question", required=True) self._question = self._prms.getParam("question", required=True)
self._choices = self._prms.getParam("choices", required=True) self._choices = self._prms.getParam("choices", required=True)
self._default_icon = self._prms.getParam("icon", required=False, default=None) self._default_icon = self._prms.getParam("icon", required=False, default=None)
self._auto_result = self._prms.getParam("auto_result", required=False, default=None)
@test_run @test_run
def execute(self): def execute(self):
q = self._prms.expanse(self._question) q = self._prms.expanse(self._question)
choices = self._prms.expanse(self._choices) choices = self._prms.expanse(self._choices)
icon = self._prms.expanse(self._default_icon) icon = self._prms.expanse(self._default_icon)
result = self._run_dialog_with_result(choices_dialog.main, [self.name(), q, choices, icon]) ar = self._prms.expanse(self._auto_result) if self._auto_result is not None else None
args = [self.name(), q, choices, icon] + ([ar] if ar is not None else [])
result = self._run_dialog_with_result(choices_dialog.main, args)
if result is None: if result is None:
self.result.set(TestValue.FAILURE, "Dialog subprocess exited without returning a result") self.result.set(TestValue.FAILURE, "Dialog subprocess exited without returning a result")
return return

View File

@@ -21,6 +21,7 @@ class TestItemImageDialog(TestItemDialogBase):
with item_load_context(self.cmd(), self.name(), self.seqFilename()): with item_load_context(self.cmd(), self.name(), self.seqFilename()):
self._question = self._prms.getParam("question", required=True) self._question = self._prms.getParam("question", required=True)
self._filename = self._prms.getParam("filename", required=True) self._filename = self._prms.getParam("filename", required=True)
self._auto_result = self._prms.getParam("auto_result", required=False, default=None)
@test_run @test_run
def execute(self): def execute(self):
@@ -31,7 +32,9 @@ class TestItemImageDialog(TestItemDialogBase):
image_path = os.path.normpath( image_path = os.path.normpath(
os.path.join(tm.gd("test_directory"), image_path) os.path.join(tm.gd("test_directory"), image_path)
) )
succ = self._run_dialog_with_result(dialog_image.main, [self.name(), q, image_path]) ar = self._prms.expanse(self._auto_result) if self._auto_result is not None else None
args = [self.name(), q, image_path] + ([ar] if ar is not None else [])
succ = self._run_dialog_with_result(dialog_image.main, args)
if succ is None: if succ is None:
self.result.set(TestValue.FAILURE, "Dialog subprocess exited without returning a result") self.result.set(TestValue.FAILURE, "Dialog subprocess exited without returning a result")
elif succ: elif succ:

View File

@@ -20,12 +20,15 @@ class TestItemMsgDialog(TestItemDialogBase):
self.is_container = False self.is_container = False
with item_load_context(self.cmd(), self.name(), self.seqFilename()): with item_load_context(self.cmd(), self.name(), self.seqFilename()):
self._question = self._prms.getParam('question', required=True) self._question = self._prms.getParam('question', required=True)
self._auto_result = self._prms.getParam('auto_result', required=False, default=None)
@test_run @test_run
def execute(self): def execute(self):
q = self._prms.expanse(self._question) q = self._prms.expanse(self._question)
print("Message Displayed:\n" + q) print("Message Displayed:\n" + q)
exitcode = self._run_dialog(msg_dialog.main, [self.name(), q]) ar = self._prms.expanse(self._auto_result) if self._auto_result is not None else None
args = [self.name(), q] + ([ar] if ar is not None else [])
exitcode = self._run_dialog(msg_dialog.main, args)
if exitcode == 0: if exitcode == 0:
self.result.set(TestValue.SUCCESS) self.result.set(TestValue.SUCCESS)
else: else:

View File

@@ -15,12 +15,17 @@ class TestItemNoteDialog(TestItemDialogBase):
self.is_container = False self.is_container = False
with item_load_context(self.cmd(), self.name(), self.seqFilename()): with item_load_context(self.cmd(), self.name(), self.seqFilename()):
self._question = self._prms.getParam('question', required=True) self._question = self._prms.getParam('question', required=True)
self._auto_result = self._prms.getParam('auto_result', required=False, default=None)
self._auto_value = self._prms.getParam('auto_value', required=False, default=None)
@test_run @test_run
def execute(self): def execute(self):
q = self._prms.expanse(self._question) q = self._prms.expanse(self._question)
print("Question:\n" + q) print("Question:\n" + q)
result = self._run_dialog_with_result(test_dialog.main, [self.name(), q]) ar = self._prms.expanse(self._auto_result) if self._auto_result is not None else None
av = self._prms.expanse(self._auto_value) if self._auto_value is not None else None
args = [self.name(), q] + ([ar, av] if ar is not None else [])
result = self._run_dialog_with_result(test_dialog.main, args)
if result is None: if result is None:
self.result.set(TestValue.FAILURE, "Dialog subprocess exited without returning a result") self.result.set(TestValue.FAILURE, "Dialog subprocess exited without returning a result")
return return

View File

@@ -19,12 +19,15 @@ class TestItemQuestionDialog(TestItemDialogBase):
self.is_container = False self.is_container = False
with item_load_context(self.cmd(), self.name(), self.seqFilename()): with item_load_context(self.cmd(), self.name(), self.seqFilename()):
self._question = self._prms.getParam('question', required=True) self._question = self._prms.getParam('question', required=True)
self._auto_result = self._prms.getParam('auto_result', required=False, default=None)
@test_run @test_run
def execute(self): def execute(self):
q = self._prms.expanse(self._question) q = self._prms.expanse(self._question)
print('Question asked:\n' + q + '\n') print('Question asked:\n' + q + '\n')
succ = self._run_dialog_with_result(question_dialog.main, [self.name(), q]) ar = self._prms.expanse(self._auto_result) if self._auto_result is not None else None
args = [self.name(), q] + ([ar] if ar is not None else [])
succ = self._run_dialog_with_result(question_dialog.main, args)
if succ is None: if succ is None:
self.result.set(TestValue.FAILURE, "Dialog subprocess exited without returning a result") self.result.set(TestValue.FAILURE, "Dialog subprocess exited without returning a result")
return return

View File

@@ -16,12 +16,15 @@ class TestItemTestedRefsDialog(TestItemDialogBase):
with item_load_context(self.cmd(), self.name(), self.seqFilename()): with item_load_context(self.cmd(), self.name(), self.seqFilename()):
self._question = self._prms.getParam('question', required=True) self._question = self._prms.getParam('question', required=True)
self._init_values = self._prms.getParamAll('reference', required=False, processed=True) self._init_values = self._prms.getParamAll('reference', required=False, processed=True)
self._auto_result = self._prms.getParam('auto_result', required=False, default=None)
@test_run @test_run
def execute(self): def execute(self):
q = self._prms.expanse(self._question) q = self._prms.expanse(self._question)
init_values = ','.join(self._init_values) init_values = ','.join(self._init_values)
result = self._run_dialog_with_result(tested_refs_dialog.main, [self.name(), q, init_values]) ar = self._prms.expanse(self._auto_result) if self._auto_result is not None else None
args = [self.name(), q, init_values] + ([ar] if ar is not None else [])
result = self._run_dialog_with_result(tested_refs_dialog.main, args)
if result is None: if result is None:
self.result.set(TestValue.FAILURE, "Dialog subprocess exited without returning a result") self.result.set(TestValue.FAILURE, "Dialog subprocess exited without returning a result")
return return

View File

@@ -19,13 +19,18 @@ class TestItemValueDialog(TestItemDialogBase):
with item_load_context(self.cmd(), self.name(), self.seqFilename()): with item_load_context(self.cmd(), self.name(), self.seqFilename()):
self._question = self._prms.getParam('question', required=True) self._question = self._prms.getParam('question', required=True)
self._default = self._prms.getParam('default', '') self._default = self._prms.getParam('default', '')
self._auto_result = self._prms.getParam('auto_result', required=False, default=None)
self._auto_value = self._prms.getParam('auto_value', required=False, default=None)
@test_run @test_run
def execute(self): def execute(self):
q = self._prms.expanse(self._question) q = self._prms.expanse(self._question)
d = self._prms.expanse(self._default) d = self._prms.expanse(self._default)
print("Question:\n" + q) print("Question:\n" + q)
result = self._run_dialog_with_result(test_dialog.main, [self.name(), q, d]) ar = self._prms.expanse(self._auto_result) if self._auto_result is not None else None
av = self._prms.expanse(self._auto_value) if self._auto_value is not None else None
args = [self.name(), q, d] + ([ar, av] if ar is not None else [])
result = self._run_dialog_with_result(test_dialog.main, args)
if result is None: if result is None:
self.result.set(TestValue.FAILURE, "Dialog subprocess exited without returning a result") self.result.set(TestValue.FAILURE, "Dialog subprocess exited without returning a result")
return return

View File

@@ -2,7 +2,7 @@ import sys
from multiprocessing import freeze_support from multiprocessing import freeze_support
from PySide6.QtWidgets import (QApplication, QDialog, QTableWidgetItem) from PySide6.QtWidgets import (QApplication, QDialog, QTableWidgetItem)
from PySide6.QtCore import (Qt, QSettings) from PySide6.QtCore import Qt, QSettings, QTimer
try: try:
from interpreter.test_items.tested_references_files import tested_refs_win from interpreter.test_items.tested_references_files import tested_refs_win
@@ -52,6 +52,9 @@ def main(args, conn=None):
i += 1 i += 1
d.tableReferences.setFocus() d.tableReferences.setFocus()
auto_result = args[3] if len(args) > 3 else None
if auto_result is not None:
QTimer.singleShot(2000, lambda: d.accept() if auto_result.lower() == 'ok' else d.reject())
dres = d.exec() dres = d.exec()
if dres == QDialog.Rejected: if dres == QDialog.Rejected:

View File

@@ -2,6 +2,7 @@
name: dialog image PASS name: dialog image PASS
condition: $(validation_dialogs) condition: $(validation_dialogs)
question: click ok if you see the image question: click ok if you see the image
auto_result: "ok"
key: $(test)_PASS key: $(test)_PASS
filename: $(test_path)$(psep)IMG_20140213_171455.jpg filename: $(test_path)$(psep)IMG_20140213_171455.jpg
@@ -9,6 +10,7 @@
name: dialog image FAIL name: dialog image FAIL
condition: $(validation_dialogs) condition: $(validation_dialogs)
question: click cancel question: click cancel
auto_result: "cancel"
key: $(test)_FAIL key: $(test)_FAIL
filename: $(test_path)$(psep)IMG_20140213_171455.jpg filename: $(test_path)$(psep)IMG_20140213_171455.jpg
@@ -17,45 +19,54 @@
condition: $(validation_dialogs) condition: $(validation_dialogs)
key: $(test)_PASS key: $(test)_PASS
question: click ok question: click ok
auto_result: "ok"
- dialog_references: - dialog_references:
name: dialog_reference FAIL name: dialog_reference FAIL
condition: $(validation_dialogs) condition: $(validation_dialogs)
key: $(test)_FAIL key: $(test)_FAIL
question: click cancel question: click cancel
auto_result: "cancel"
- dialog_value: - dialog_value:
name: dialog_value PASS name: dialog_value PASS
condition: $(validation_dialogs) condition: $(validation_dialogs)
key: $(test)_PASS key: $(test)_PASS
question: enter 123 and click ok question: enter 123 and click ok
auto_result: "ok"
auto_value: "123"
- dialog_value: - dialog_value:
name: dialog_value empty FAIL name: dialog_value empty FAIL
condition: $(validation_dialogs) condition: $(validation_dialogs)
key: $(test)_FAIL key: $(test)_FAIL
question: enter nothing and click ok question: enter nothing and click ok
auto_result: "ok"
- dialog_value: - dialog_value:
name: dialog_value canceled FAIL name: dialog_value canceled FAIL
condition: $(validation_dialogs) condition: $(validation_dialogs)
key: $(test)_FAIL key: $(test)_FAIL
question: enter nothing and click cancel question: enter nothing and click cancel
auto_result: "cancel"
- dialog_message: - dialog_message:
name: dialog_message PASS name: dialog_message PASS
condition: $(validation_dialogs) condition: $(validation_dialogs)
key: $(test)_PASS key: $(test)_PASS
question: click ok question: click ok
auto_result: "ok"
- dialog_question: - dialog_question:
name: dialog_question PASS name: dialog_question PASS
condition: $(validation_dialogs) condition: $(validation_dialogs)
key: $(test)_PASS key: $(test)_PASS
question: click yes question: click yes
auto_result: "yes"
- dialog_question: - dialog_question:
name: dialog_question FAIL name: dialog_question FAIL
condition: $(validation_dialogs) condition: $(validation_dialogs)
key: $(test)_FAIL key: $(test)_FAIL
question: click no question: click no
auto_result: "no"

View File

@@ -71,4 +71,4 @@
steps: steps:
- close: - close:
wait_dialog_exit: True wait_dialog_exit: True
timeout: 60 timeout: 2