Функциональный тест для QMessageBox... почему не работает?

Я бы разработал несколько функциональных тестов для приложения pyqt, которое использует PyQt (или PySide) в качестве библиотеки GUI. В тестах используются библиотеки Unittest и Qttest, о которых сообщалось во многих ресурсах, например, этот вопрос о стековом потоке: модульное и функциональное тестирование приложения на основе PySide? Для главного окна все работает нормально, и код прекрасно имитирует типы клавиатуры и щелчки и движения мыши, но "дьявол кроется в деталях"... и этот метод не работает для QMessageBox.

В классе главного окна, для управления IOError при открытии файла я инициализирую QMessageBox:

self.IOErrMsgBox = QtGui.QMessageBox()
self.IOErrMsgBox.setText("<b>Error</b>")
self.IOErrMsgBox.setInformativeText("""
                                    <p>There was an error opening
                                    the project file:
                                    %s.</p>"""%(path,))
self.IOErrMsgBox.setStandardButtons(QtGui.QMessageBox.Ok)
self.IOErrMsgBox.setDefaultButton(QtGui.QMessageBox.Ok)
self.IOErrMsgBox.exec_()

Чтобы проверить, как это работает, в функциональном тесте у меня есть:

def test__open_project(self):
    self.MainWin._project_open(wrong_path, flag='c') 
    # the function that handles the exception 
    # and initializes the QMessageBox.
    IOErrMsgBox = self.MainWin.IOErrMsgBox
    # Reference to the initialized QMessageBox.
    self.assertIsInstance(IOErrMsgBox, QMessageBox)
    okWidget = self.MainWin.IOErrMsgBox.button(IOErrMsgBox.Ok)
    QTest.mouseClick(okWidget, Qt.LeftButton)

или, в качестве альтернативы:

def test__open_project(self):
     #... some code, exactly like previous example except for last row...
     QTest.keyClick(okWidget, 'o', Qt.AltModifier)

но никто не работает... и кнопка Ok не нажата, и я могу сделать это с помощью моего указателя мыши:(

Какие-либо предложения?

1 ответ

Решение

Вопрос в общем о том, как тестировать модальные диалоги.

Любой модальный диалог, включая QMessageBox, не вернется из exec_() пока он не будет закрыт, поэтому тестовый код в вашем втором блоке кода, вероятно, никогда не будет выполнен.

Вы могли бы просто show() это (делает его немодальным), а затем следуйте вашему коду, но не забудьте закрыть и удалить диалоговое окно впоследствии.

Или вы используете Timer и планируете щелкнуть по кнопке OK (аналогично диалоговому окну Test modeal с Qt Test). Вот пример:

from PySide import QtGui, QtCore

app = QtGui.QApplication([])

box = QtGui.QMessageBox()
box.setStandardButtons(QtGui.QMessageBox.Ok)
button = box.button(QtGui.QMessageBox.Ok)
QtCore.QTimer.singleShot(0, button.clicked)
box.exec_()
Другие вопросы по тегам