Skip to content
Snippets Groups Projects
Commit 7678659b authored by tholok97's avatar tholok97
Browse files

la til widget å teste + tester

tatt fra tidligere repo. Strukturen for testene er tatt herfra: https://gist.github.com/tasdikrahman/2bdb3fb31136a3768fac
parent e0066cf9
No related branches found
No related tags found
No related merge requests found
......@@ -32,7 +32,7 @@ job_test_gui_ubuntu_vnc:
- pip install pyside2
# -platform because running with a screen is not supported
# https://stackoverflow.com/questions/17106315/failed-to-load-platform-plugin-xcb-while-launching-qt5-app-on-linux-without
- QT_QPA_PLATFORM=vnc python3 ./soitool/main.py
- QT_QPA_PLATFORM=vnc python3 -m unittest test.test_main
job_test_gui_windows:
stage: test
......@@ -40,7 +40,7 @@ job_test_gui_windows:
- ci-windows
script:
- python --version
- python ./soitool/main.py
- python -m unittest test.test_main
job_test_gui_ubuntu:
stage: test
......@@ -48,5 +48,5 @@ job_test_gui_ubuntu:
- ci-ubuntu
script:
- python3 --version
- DISPLAY=':10.0' python3 ./soitool/main.py
- DISPLAY=':10.0' python3 -m unittest test.test_main
"""Skriver bare hello world
"""Applikasjon basert på popups
Vil i fremtiden inneholde entrypoint til programmet
Bare her for å ha noe å teste mens vi setter opp repo
"""
print("Hello World!")
import unittest
import sys
from PySide2 import QtGui, QtWidgets, QtTest, QtCore
class CoolWidget(QtWidgets.QWidget):
def __init__(self, text="Sample text", *args, **kwargs):
super(CoolWidget, self).__init__(*args, **kwargs)
# settings this to None is only useful for one of the testing methods described in test_main.py
self.dlg_input = None
layout = QtWidgets.QHBoxLayout()
self.qlabel = QtWidgets.QLabel(text)
self.button = QtWidgets.QPushButton("Change text")
self.button.clicked.connect(self.clickfunc)
layout.addWidget(self.qlabel)
layout.addWidget(self.button)
self.setLayout(layout)
def clickfunc(self):
# try-finally to set dialog to None is only useful for one of the testing methods described in test_main.py
try:
self.dlg_input = QtWidgets.QInputDialog(self)
text, ok = self.dlg_input.getText(
self,
"Change text",
"Please type something",
QtWidgets.QLineEdit.Normal
)
if ok:
self.qlabel.setText(text)
else:
self.dlg_msg = QtWidgets.QMessageBox()
self.dlg_msg.setText("Operation cancelled")
self.dlg_msg.exec_()
finally:
self.dlg_input = None
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
widget = CoolWidget("Custom text")
widget.show()
app.exec_()
import unittest
import sys
from soitool import main
from PySide2 import QtGui, QtWidgets, QtTest, QtCore
# references:
# * findChild: https://srinikom.github.io/pyside-docs/PySide/QtCore/QObject.html#PySide.QtCore.PySide.QtCore.QObject.findChild
# * pyside: https://doc.qt.io/qtforpython/PySide2/QtCore/QObject.html#PySide2.QtCore.PySide2.QtCore.QObject.findChild
# * allows to find child of widget based on type (and name)
# * findChild in action (C++): https://code.woboq.org/qt5/qtbase/tests/auto/widgets/dialogs/qinputdialog/tst_qinputdialog.cpp.html
# * look for QInputDialog and QLineEdit
# * thread discussing singleShot: https://github.com/pytest-dev/pytest-qt/issues/256
# * activeModalWidget: https://stackoverflow.com/questions/38596785/how-can-i-get-access-to-a-qmessagebox-by-qtest
# * testing modal dialogs: https://www.qtcentre.org/threads/31239-Testing-modal-dialogs-with-QTestLib
# * keyclick: https://programtalk.com/python-examples/PyQt4.QtTest.QTest.keyClick/
# * isVisible: https://stackoverflow.com/questions/13850240/pyqt-how-to-check-is-qdialog-is-visible
# moved here from setUp to avoid annoying startup messages
app = QtWidgets.QApplication(sys.argv)
def wait(msec):
QtTest.QTest.qWait(msec)
class TestMain(unittest.TestCase):
def setUp(self):
self.test_text1 = "A bad boy"
self.test_text2 = "Hei Anders!"
self.widget = main.CoolWidget(self.test_text1)
self.widget.show()
def test_starts_up(self):
self.assertEqual(
self.widget.qlabel.text(),
self.test_text1,
)
self.assertTrue(self.widget.isVisible())
# This test shows how waiting for a referenced dialog can create more reliable tests. The only downside is having to ensure that the mouseClick after the singleShot is allowed to run. If we put a singleShot delay too short the line is never allowed to execute, and the while-loop of the inner function takes over the whole world
def test_change_text_ok(self):
def change_text_and_ok():
while self.widget.dlg_input is None:
app.processEvents()
child_line_edit = self.widget.dlg_input.findChild(QtWidgets.QLineEdit)
QtTest.QTest.keyClicks(child_line_edit, self.test_text2)
QtTest.QTest.keyClick(child_line_edit, QtCore.Qt.Key_Enter)
# delay of 100 to allow the next line to execute
QtCore.QTimer.singleShot(100, change_text_and_ok)
QtTest.QTest.mouseClick(self.widget.button, QtCore.Qt.LeftButton)
self.assertEqual(
self.widget.qlabel.text(),
self.test_text2,
)
# This test shows how we can use singleShot to trick code to be ran after .exec() of a dialog. The downside is that for slow computers the singleShot could be ran before .exec(). See the above test for an example approach to avoid this. A boon of this method is that we don't need to test against stored references to dialogs, we can instead rely on app.activeModalWidget()
def test_change_text_not_ok(self):
def accept_popup():
QtTest.QTest.keyClick(app.activeModalWidget(), QtCore.Qt.Key_Enter)
def change_text_and_not_ok():
# in PySide2 we need to store a reference to this. If we don't the widget is garbage collected somehow before we get to use child_line_edit (a child of the active widget)
active_widget = app.activeModalWidget()
child_line_edit = active_widget.findChild(QtWidgets.QLineEdit)
QtTest.QTest.keyClicks(child_line_edit, self.test_text2)
QtCore.QTimer.singleShot(0, accept_popup)
QtTest.QTest.keyClick(child_line_edit, QtCore.Qt.Key_Escape)
QtCore.QTimer.singleShot(0, change_text_and_not_ok)
QtTest.QTest.mouseClick(self.widget.button, QtCore.Qt.LeftButton)
self.assertNotEqual(
self.widget.qlabel.text(),
self.test_text2,
)
if __name__ == '__main__':
unittest.main()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment