¿Pruebas unitarias y funcionales de una aplicación basada en PySide?

Estoy creando una aplicación basada en PySide 1.1.0, y he estado buscando buenos ejemplos para ver la unidad y las pruebas funcionales de mi aplicación. Quiero poder realizar pruebas funcionales de la interfaz de usuario (simulando clics, pulsaciones de teclas, etc.), pruebas unitarias de las ranuras de la interfaz de usuario que alteran el diseño de la interfaz de usuario (probablemente utilizando un remitente y un receptor parcialmente simulados), así como una unidad prueba de código que involucra widgets, pero sin requerir ventanas para ser renderizadas.

Como ejemplo, creo dinámicamente los submenús de un menú en la barra de menú cuando se agrega un elemento a un modelo (objeto derivado de QAbstractItstractModel) que proporciona datos a un QTreeView. El modelo y el submenú deben permanecer sincronizados, por lo que quiero poder escribir una prueba unitaria que envíe los datos al controlador que administra el modelo y el submenú, y afirma que tanto el modelo como el submenú se actualizaron correctamente.

Preferiría NO tener que configurar una QApplication en mi código de prueba si puedo evitarlo. También me gustaría no tener que mostrar ventanas cuando solo me interesa validar las estructuras de datos en widgets, no su visualización.

No puedo encontrar nada de valor adecuado en http://www.pyside.org o en mis búsquedas de Google. ¿Alguien tiene alguna experiencia o sabe de un buen código de muestra que debería ver?

He estado jugando un poco ahora con el código de prueba de unidad y llegué a la conclusión de que combinar el módulo unittest de python con el módulo qt’s qt funciona bastante bien.

Deberá tener un objeto QApplication instanciado, pero no necesita ejecutar su método exec_ , ya que no necesita el bucle de eventos para ejecutarse.

Aquí hay un ejemplo de cómo QCheckBox si un QCheckBox en un diálogo hace lo que se supone que debe hacer:

 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(), "") 

Esto funciona completamente fuera de la pantalla, implica hacer clic en los widgets y escribir texto en un QLineEdit .

Aquí es cómo pruebo un QAbstractListModel (bastante simple):

 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 

Espero que esto ayude un poco.

En mi caso, recibí un error ‘QPixmap: debo construir una aplicación de Q antes de un QPaintDevice’.

Si necesita tener una instancia de QApplication para sus pruebas (por ejemplo, usar QPixmap), aquí hay una forma de hacerlo. Simplemente cree un singleton para asegurarse de tener una y solo una instancia de QApplication.

Esto está enterrado como un ayudante para las pruebas en la fuente PySide.

 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() 

y luego la subclase 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) 

espero que esto ayude