2012-06-21 11 views
16

Buduję aplikację opartą na PySide 1.1.0 i szukałem dobrych przykładów, aby przyjrzeć się jednostce i testowaniu funkcjonalności mojej aplikacji. Chcę móc przeprowadzić testowanie funkcjonalne interfejsu użytkownika (symulowanie kliknięć, naciśnięć przycisków itp.), Testowanie jednostkowe gniazd interfejsu, które zmieniają układ interfejsu użytkownika (prawdopodobnie przy użyciu częściowo wyśmiewanego nadawcy i odbiorcy), a także jednostkę testowanie kodu zawierającego widżety, ale bez konieczności renderowania jakichkolwiek okien.Jednostkowe i funkcjonalne testowanie aplikacji opartej na PySide?

Jako jeden przykład, dynamicznie utworzyć podmenu jednego menu na pasku menu, gdy element jest dodawany do modelu (obiekt pochodny QAbstractItemModel), który dostarcza dane do QTreeView. Model i podmenu muszą pozostać zsynchronizowane, dlatego chcę mieć możliwość napisania testu jednostkowego, który przesyła dane do kontrolera, który zarządza modelem i podmenu, i zapewnia poprawną aktualizację zarówno modelu, jak i podmenu.

Wolałbym NIE konfigurować QApplication w moim kodzie testowym, jeśli mogę tego uniknąć. Nie chciałbym również wyświetlać okien, gdy zależy mi tylko na sprawdzaniu poprawności struktur danych w widżetach, a nie ich wizualizacji.

Nie mogę znaleźć niczego odpowiedniego o wartości http://www.pyside.org lub w moich wyszukiwaniach w Google. Czy ktoś ma jakieś doświadczenie lub zna dobry kod przykładowy, na który powinienem patrzeć?

+0

Jestem również bardzo intereseted w roztworze do tego, jak jestem stoi dokładnie te same problemy – Chris

+1

widziałeś: http : //johnnado.com/pyqt-qtest-example/ To jest PyQt, ale prawie tak samo. – neuronet

Odpowiedz

29

Grałem trochę teraz z testowym kodem pyside i doszedłem do wniosku, że połączenie modułu Pythona unittest z modułem qt's QTest działa całkiem nieźle.

Należy utworzyć instancję obiektu QApplication, ale nie trzeba uruchamiać jej metody exec_, ponieważ nie jest potrzebna uruchomiona pętla zdarzeń.

Oto przykład, w jaki sposób mogę sprawdzić, czy QCheckBox w oknie robi to, co ma robić:

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

Ten całkowicie działa poza ekranem, polega na kliknięciu widgety i tekst wpisując QLineEdit.

Oto jak ja przetestować (raczej proste) 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 

Mam nadzieję, że to pomaga littlebit.

2

W moim przypadku wystąpił błąd "QPixmap: Konieczne skonstruowanie aplikacji QApplication przed QPaintDevice".

Jeśli potrzebujesz mieć instancję QApplication do swoich testów (np. Użyj QPixmap), oto jeden sposób, aby to zrobić. Po prostu utwórz singleton, aby zapewnić sobie tylko jedną instancję QApplication.

Zostało to zakopane jako pomocnik do testów w źródle 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() 

a następnie podklasa 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) 

nadzieję, że to pomaga

+7

Po prostu robię 'if QtGui.qApp == Brak: QtGui.QApplication ([]) 'na początku każdego modułu testowego, który używa QtGui. – strubbly