I have a parent widget that in some cases calls a custom QDialog to get user input. How do I write a unit test to ensure the dialog is called, and that it will handle correct input correctly?
Here's a mini example:
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()
So in this case, I'd want to write a unit test that inserts different values into self.field and then tests that it works without PopupDialog for integers but that the PopupDialog is called when inserting a string.
(I know I could just test the functionality without the dialog, and that for this problem, the QDialog is not actually needed. I just tried to keep the example simple. Baseline is: I can get the unit test through the steps until the popup dialog is created, but how can I then test that it is indeed created, and then interact with it to test the result?)
#!/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()
(I'm using PyQt5 in Python3.6 on Windows.)