Подтвердить что ты не робот

Какой рекомендуемый способ унифицировать приложения GUI Python?

В настоящее время я достаточно глуп, чтобы попытаться сохранить две параллельные базы кода для настольного приложения Python, используя интроспекцию PyGObject для GTK 3 и один с использованием PyGTK для GTK 2. Я работаю в основном на ветке PyGObject, а затем меняю изменения порта к филиалу PyGTK. Из-за всех незначительных различий между этими реализациями я часто упускаю из виду вещи и выхожу из-за поломки, которую я пропускаю и случайно освобождаю, только чтобы быть пойманным пользователями.

Я пытаюсь найти хороший способ разработки некоторых unittests, которые, желательно, будут пригодны для работы на обеих базовых кодах. Это не слишком сложная программа (это, по сути, инструмент управления библиотекой, представить себе как iTunes):

- Main Window
  |- Toolbar with some buttons (add/edit/remove items, configure the program)
  |
  |- VPaned
  |--- Top HPaned
  |------ ListView (listing values by which a library of items can be filtered)
  |------ ListView (listing the contents of the library
  |--- Bottom HPaned
  |------ Image (displaying cover art for the currently selected item in the library)
  |------ TextView (displaying formatted text describing the currently selected item)
 - Edit dialog
 - Configuration dialog
 - About dialog 

Я попытался как можно больше отделить взгляды от моделей. Каждый из этих элементов реализуется в своем собственном классе (ну, в классах, которые наследуются от перечисленных классов GTK). ListViews связаны с другими классами, которые наследуются от ListStores. Сама библиотека обрабатывается другим классом. Тем не менее, есть взаимодействия между виджетами, которые необходимо протестировать. Например, если пользователь выбирает конкретный элемент в представлении фильтра, фильтруя библиотеку, а затем выбирает элемент из отфильтрованных результатов, текстовое представление должно отображать информацию для правильной записи в библиотеке, которая является полусложной из-за перевода итераторы между TreeModelFilter и исходным ListStore и т.д. и т.д.

Итак, я спрашиваю, каков рекомендуемый способ написания надежных модульных тестов для такого приложения GUI? Я видел, что для этого есть несколько библиотек, но основные для pygtk не обновлялись годами, и поэтому они почти наверняка потерпят неудачу с самоанализом PyGObject. Возможно, я недостаточно творческий, чтобы понять, как это сделать, используя модуль Python unittest, поэтому я открыт для предложений.

4b9b3361

Ответ 1

Вы действительно хотите unit test графический интерфейс? Ваш пример сложности включает в себя более 1 единицы и, следовательно, является интеграционным тестом.

Если вы действительно хотите unit test, вы должны создать экземпляр одного класса, предоставляющего mocks или stubs для своих зависимостей, а затем вызвать на нем методы, например, для GUI-структуры. щелчок пользователя. Это может быть утомительным, и вы должны точно знать, как инфраструктура GUI отправляет пользовательский ввод в ваши классы.

Мой совет - добавить еще больше вещей в модели. В данном примере вы можете создать FilterManager, который будет абстрагировать все элементы filter/select/display за единственным методом. Затем unit test it.

Ответ 2

Существует отличный способ непосредственно проверить функции и виджеты PyGTK, не проходя через платформы принятия/функционального/интеграционного тестирования, которые заклинивают свой путь в забвении. Об этом я узнал в этот пост, который достаточно понятен себе. Но основная идея заключается в том, что вы рассматриваете свои виджеты как функции/классы, и вы можете тестировать их напрямую. Если вам нужно обработать обратные вызовы и т.д., Там будет аккуратный трюк, который я воспроизведу здесь:

import time
import gtk

# Stolen from Kiwi
def refresh_gui(delay=0):
  while gtk.events_pending():
      gtk.main_iteration_do(block=False)
  time.sleep(delay)

Как упоминалось в блоге, этот код LGPL. В противном случае, если вы думаете об этом, если вы не видите окна или виджеты show(), вы можете проверить их все, что хотите, и они должны вести себя так, как если бы они были реальными, потому что они в некотором роде. Они просто не отображаются.

Конечно, вам нужно имитировать взаимодействие на кнопках и интерактивных виджетах, вызывая, например, clicked() на кнопке. См. Снова Али Афшар превосходный пост об модульном тестировании в PyGTK.

Ответ 3

Придерживаясь темы, в которой Юрген был прав, я не заинтересован в модульном тестировании, но фактически заинтересован в тестировании интеграции, я также нашел эту фреймворку с freedesktop.org: http://ldtp.freedesktop.org/wiki/

Он позволяет автоматизировать множество тестов для графических приложений с поддержкой доступа (включая GTK, Qt, Swing и т.д.).

Ответ 4

Вы можете использовать фреймбуфер X11:

Xvfb :119 -screen 0 1024x768x16 &
export DISPLAY=:119
... run your tests

Убедитесь, что не вводите gtk.main(), так как это будет ждать ввода мыши или клавиатуры. Вы можете использовать этот шаблон, чтобы позволить gtk обрабатывать все события:

def refresh_gui():
  while gtk.events_pending():
      gtk.main_iteration_do(block=False)

AFAIK вы не можете видеть свое приложение, но вы можете проверить свои обратные вызовы.