Единичное и функциональное тестирование приложения на основе PySide? - программирование
Подтвердить что ты не робот

Единичное и функциональное тестирование приложения на основе PySide?

Я создаю приложение на основе PySide 1.1.0 и ищу хорошие примеры, чтобы посмотреть на модульное и функциональное тестирование моего приложения. Я хочу иметь возможность выполнять функциональное тестирование пользовательского интерфейса (имитирующие клики, нажатия клавиш и т.д.), Модульное тестирование слотов пользовательского интерфейса, которые изменяют компоновку пользовательского интерфейса (предположительно, с использованием частично изделенного отправителя и получателя), а также блок тестирование кода, который включает в себя виджеты, но не требующие визуализации окон.

В качестве одного примера я динамически создаю подменю одного меню в строке меню, когда элемент добавляется к модели (объект, созданный QAbstractItemModel), который предоставляет данные в QTreeView. Модель и подменю должны оставаться в синхронизации, поэтому я хочу написать unit test, который передает данные контроллеру, который управляет моделью и подменю, и утверждает, что и модель, и подменю были надлежащим образом обновлены.

Я бы предпочел НЕ настраивать QApplication в моем тестовом коде, если я могу его избежать. Я также хотел бы не показывать какие-либо окна, когда мне нужно только проверять структуры данных в виджетах, а не их визуализацию.

Я не могу найти что-либо подходящее значение в http://www.pyside.org или в моих поисковых системах Google. Есть ли у кого-нибудь опыт или хороший код примера, на который я должен смотреть?

4b9b3361

Ответ 1

Я немного поиграл с модулем pyside с модулем тестирования и пришел к выводу, что объединение модуля python unittest с модулем qt QTest работает очень хорошо.

У вас должен быть экземпляр объекта QApplication, но вам не нужно запускать его метод exec_, потому что вам не нужен цикл событий, который будет запущен.

Вот пример того, как я тестирую, если QCheckBox в диалоговом окне выполняет то, что он должен делать:

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

Это полностью работает вне экрана, включает в себя щелчок виджетами и ввод текста в QLineEdit.

Вот как я тестирую (довольно простой) 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

Надеюсь, это поможет немного.

Ответ 2

В моем случае я получал сообщение об ошибке "QPixmap: должен построить QApplication перед QPaintDevice".

Если вам нужен экземпляр QApplication для ваших тестов (например, используйте QPixmap), здесь один из способов сделать это. Просто создайте синглтон, чтобы обеспечить один и только один экземпляр QApplication.

Это похоронен как помощник для тестов в источнике 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()

а затем подкласс 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)

надеюсь, что это поможет