创建 QDialog 的 PyQt 单元测试
PyQt unit test that QDialog is created
我有一个父小部件,它在某些情况下会调用自定义 QDialog 来获取用户输入。我如何编写单元测试以确保对话框被调用,并且它将正确处理正确的输入?
这是一个小例子:
from PyQt5.QtWidgets import QDialog, QVBoxLayout, QWidget, QLabel, QApplication
from PyQt5.Qt import pyqtSignal, QPushButton, pyqtSlot, QLineEdit
import sys
class PopupDialog(QDialog):
result = pyqtSignal(str)
def __init__(self):
super().__init__()
layout = QVBoxLayout(self)
self.setLayout(layout)
lbl = QLabel("That's not a full number! Try again?")
layout.addWidget(lbl)
self.field = QLineEdit(self)
layout.addWidget(self.field)
self.btn = QPushButton("Ok")
self.btn.clicked.connect(self.on_clicked)
layout.addWidget(self.btn)
def on_clicked(self):
value = self.field.text().strip()
self.result.emit(value)
self.close()
class Example(QWidget):
def __init__(self):
super().__init__()
self.init_UI()
def init_UI(self):
layout = QVBoxLayout()
self.setLayout(layout)
lbl = QLabel("Please provide a full number")
layout.addWidget(lbl)
self.counter_fld = QLineEdit(self)
self.counter_fld.setText("1")
layout.addWidget(self.counter_fld)
self.btn = QPushButton("start")
layout.addWidget(self.btn)
self.btn.clicked.connect(self.on_clicked)
self.field = QLabel()
layout.addWidget(self.field)
self.show()
@pyqtSlot()
def on_clicked(self):
txt = self.counter_fld.text()
self.dialog = None
try:
result = int(txt) * 100
self.field.setText(str(result))
except ValueError:
self.dialog = PopupDialog()
self.dialog.result.connect(self.catch_dialog_output)
self.dialog.exec_()
@pyqtSlot(str)
def catch_dialog_output(self, value):
self.counter_fld.setText(value)
self.on_clicked()
def main():
app = QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
所以在这种情况下,我想编写一个单元测试,将不同的值插入到 self.field 中,然后测试它是否在没有 PopupDialog 的情况下对整数有效,但在插入字符串时调用 PopupDialog。
(我知道我可以在没有对话框的情况下测试功能,并且对于这个问题,实际上不需要 QDialog。我只是试图使示例保持简单。基线是:我可以通过单元测试创建弹出对话框之前的步骤,但我如何才能测试它确实已创建,然后与它交互以测试结果?)
#!/usr/bin/env Python3
import unittest
import temp2
class Test1(unittest.TestCase):
@classmethod
def setUpClass(self):
self.w = temp2.Example()
def testHappy(self):
for i in [0,1,5]:
self.w.counter_fld.setText(str(i))
self.w.btn.click()
value = self.w.field.text()
self.assertEqual(value, str(i * 100))
def testSad(self):
for i in ["A", "foo"]:
self.w.counter_fld.setText(str(i))
self.w.btn.click()
# now what?
if __name__ == "__main__":
unittest.main()
(我在 Python3.6 在 Windows 上使用 PyQt5。)
好吧,有几种方法可以检查 QDialog
是否已创建,
1) 修补 PopupDialog
并验证它是否被调用。
from unittest.mock import patch
@patch("temp2.PopupDialog")
def testPopupDialog(self, mock_dialog):
self.w.counter_fld.setText(str("A"))
self.w.btn.click()
mock_dialog.assert_called_once()
2) 要与 PopupDialog
互动,您可能需要做更多的事情。
def testPopupDialogInteraction(self):
self.w.counter_fld.setText(str("A"))
self.w.btn.click()
if hasattr(self.w.dialog, "field"):
self.w.dialog.field.setText(str(1))
self.w.dialog.btn.click()
value = self.w.field.text()
self.assertEqual(value, str(1 * 100))
raise Exception("dialog not created")
另一方面,有一种更好的方法来验证用户输入,即 QRegExpValidator
。检查这个
在目前的方法中,每当用户输入不正确的值时,它都会继续创建弹出窗口,这会造成糟糕的用户体验 (UX)。甚至网站也使用验证器而不是弹出窗口。
我有一个父小部件,它在某些情况下会调用自定义 QDialog 来获取用户输入。我如何编写单元测试以确保对话框被调用,并且它将正确处理正确的输入?
这是一个小例子:
from PyQt5.QtWidgets import QDialog, QVBoxLayout, QWidget, QLabel, QApplication
from PyQt5.Qt import pyqtSignal, QPushButton, pyqtSlot, QLineEdit
import sys
class PopupDialog(QDialog):
result = pyqtSignal(str)
def __init__(self):
super().__init__()
layout = QVBoxLayout(self)
self.setLayout(layout)
lbl = QLabel("That's not a full number! Try again?")
layout.addWidget(lbl)
self.field = QLineEdit(self)
layout.addWidget(self.field)
self.btn = QPushButton("Ok")
self.btn.clicked.connect(self.on_clicked)
layout.addWidget(self.btn)
def on_clicked(self):
value = self.field.text().strip()
self.result.emit(value)
self.close()
class Example(QWidget):
def __init__(self):
super().__init__()
self.init_UI()
def init_UI(self):
layout = QVBoxLayout()
self.setLayout(layout)
lbl = QLabel("Please provide a full number")
layout.addWidget(lbl)
self.counter_fld = QLineEdit(self)
self.counter_fld.setText("1")
layout.addWidget(self.counter_fld)
self.btn = QPushButton("start")
layout.addWidget(self.btn)
self.btn.clicked.connect(self.on_clicked)
self.field = QLabel()
layout.addWidget(self.field)
self.show()
@pyqtSlot()
def on_clicked(self):
txt = self.counter_fld.text()
self.dialog = None
try:
result = int(txt) * 100
self.field.setText(str(result))
except ValueError:
self.dialog = PopupDialog()
self.dialog.result.connect(self.catch_dialog_output)
self.dialog.exec_()
@pyqtSlot(str)
def catch_dialog_output(self, value):
self.counter_fld.setText(value)
self.on_clicked()
def main():
app = QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
所以在这种情况下,我想编写一个单元测试,将不同的值插入到 self.field 中,然后测试它是否在没有 PopupDialog 的情况下对整数有效,但在插入字符串时调用 PopupDialog。
(我知道我可以在没有对话框的情况下测试功能,并且对于这个问题,实际上不需要 QDialog。我只是试图使示例保持简单。基线是:我可以通过单元测试创建弹出对话框之前的步骤,但我如何才能测试它确实已创建,然后与它交互以测试结果?)
#!/usr/bin/env Python3
import unittest
import temp2
class Test1(unittest.TestCase):
@classmethod
def setUpClass(self):
self.w = temp2.Example()
def testHappy(self):
for i in [0,1,5]:
self.w.counter_fld.setText(str(i))
self.w.btn.click()
value = self.w.field.text()
self.assertEqual(value, str(i * 100))
def testSad(self):
for i in ["A", "foo"]:
self.w.counter_fld.setText(str(i))
self.w.btn.click()
# now what?
if __name__ == "__main__":
unittest.main()
(我在 Python3.6 在 Windows 上使用 PyQt5。)
好吧,有几种方法可以检查 QDialog
是否已创建,
1) 修补 PopupDialog
并验证它是否被调用。
from unittest.mock import patch
@patch("temp2.PopupDialog")
def testPopupDialog(self, mock_dialog):
self.w.counter_fld.setText(str("A"))
self.w.btn.click()
mock_dialog.assert_called_once()
2) 要与 PopupDialog
互动,您可能需要做更多的事情。
def testPopupDialogInteraction(self):
self.w.counter_fld.setText(str("A"))
self.w.btn.click()
if hasattr(self.w.dialog, "field"):
self.w.dialog.field.setText(str(1))
self.w.dialog.btn.click()
value = self.w.field.text()
self.assertEqual(value, str(1 * 100))
raise Exception("dialog not created")
另一方面,有一种更好的方法来验证用户输入,即 QRegExpValidator
。检查这个
在目前的方法中,每当用户输入不正确的值时,它都会继续创建弹出窗口,这会造成糟糕的用户体验 (UX)。甚至网站也使用验证器而不是弹出窗口。