I'm building a PySide 1.1.0-based application, and have been looking for good examples to look at for unit and functional testing my application. I want to be able to do functional testing of the UI (simulating clicks, key presses, etc), unit testing of UI slots that alter the layout of the UI (presumably using a partially-mocked sender and receiver), as well as unit testing of code that involves widgets, but without requiring any windows to be rendered.
As one example, I dynamically create submenus of one menu in the menubar when an item is added to a model (QAbstractItemModel-derived object) that provides data to a QTreeView. The model and submenu must stay in sync, so I want to be able to write a unit test that submits data to the controller that manages the model and submenu, and asserts that both the model and submenu were properly updated.
I would prefer to NOT have to set up a QApplication in my test code if I can avoid it. I also would like to not have to display any windows when I only care about validating data structures in widgets, not their visualization.
I can't find anything of suitable value at http://www.pyside.org or in my Google searches. Does anyone have any experience or know of good sample code that I should look at?
Unit testing helps isolate specific code and determine if the unit works as intended. The goal is to facilitate early detection of code flaws that may be difficult to find and fix in later testing stages. Functional testing helps verify that each application feature works as intended.
Unit testing It analyzes individual components and functions to ensure they're working as expected. This is crucial for any frontend application, testing your components and features against how you expect them to behave in production, leading to a stable codebase and a reliable app for your customers.
Unit testing is a technique in which particular module is tested to check by developer himself whether there are any errors. The primary focus of unit testing is test an individual unit of system to analyze, detect, and fix the errors. Python provides the unittest module to test the unit of source code.
I've been playing around a bit now with unit-testing pyside code and came to the conclusion that combining python's unittest
module with qt's QTest
module works pretty good.
You will have to have a QApplication
object instantiated, but you do not need to run its exec_
method, because you don't need the event loop to be running.
Here is an example on how I test if a QCheckBox
in a dialog does what it is supposed to do:
class Test_PwsAddEntryDialog(TestCase):
"""Tests the class PwsAddEntryDialog."""
def test_password_strength_checking_works(self):
"""Tests if password strength checking works, if the corresponding check
box is checked.
"""
d = PwsAddEntryDialog()
# test default of internal flag
self.assertFalse(d.testPasswordStrength)
# type something
QTest.keyClicks(d.editSecret, "weak", 0, 10)
# make sure that entered text is not treated as a password
self.assertEqual(d.labelPasswordStrength.text(), "")
# click 'is password' checkbox
QTest.mouseClick(d.checkIsPassword, Qt.LeftButton)
# test internal flag changed
self.assertTrue(d.testPasswordStrength)
# test that label now contains a warning
self.assertTrue(d.labelPasswordStrength.text().find("too short") > 0)
# click checkbox again
QTest.mouseClick(d.checkIsPassword, Qt.LeftButton)
# check that internal flag once again changed
self.assertFalse(d.testPasswordStrength)
# make sure warning disappeared again
self.assertEqual(d.labelPasswordStrength.text(), "")
This completely works off-screen, involves clicking widgets and typing text in a QLineEdit
.
Here is how I test a (rather simple) QAbstractListModel
:
class Test_SectionListModel(TestCase):
"""Tests the class SectionListModel."""
def test_model_works_as_expected(self):
"""Tests if the expected rows are generated from a sample pws file
content.
"""
model = SectionListModel(SAMPLE_PASSWORDS_DICT)
l = len(SAMPLE_PASSWORDS_DICT)
self.assertEqual(model.rowCount(None), l)
i = 0
for section in SAMPLE_PASSWORDS_DICT.iterkeys():
self.assertEqual(model.data(model.index(i)), section)
i += 1
I hope this helps a littlebit.
In my case, I was getting an error 'QPixmap: Must construct a QApplication before a QPaintDevice'.
If you need to have a QApplication instance for your tests (eg use QPixmap), here's one way to do it. Just create a singleton so that you are ensured one and only one QApplication instance.
This is buried as a helper for tests in the PySide source.
import unittest
from PySide.QtGui import QApplication
_instance = None
class UsesQApplication(unittest.TestCase):
'''Helper class to provide QApplication instances'''
qapplication = True
def setUp(self):
'''Creates the QApplication instance'''
# Simple way of making instance a singleton
super(UsesQApplication, self).setUp()
global _instance
if _instance is None:
_instance = QApplication([])
self.app = _instance
def tearDown(self):
'''Deletes the reference owned by self'''
del self.app
super(UsesQApplication, self).tearDown()
and then subclass UsesQApplication
from PySide import QtGui
class Test(UsesQApplication):
def setUp(self):
#If you override setup, tearDown, make sure
#to have a super call
super(TestFilterListItem, self).setUp()
def tearDown(self):
super(TestFilterListItem, self).tearDown()
def testName(self):
pix = QtGui.QPixmap(20,20)
self.assertTrue(True)
hope this helps
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With