38 votes

Quelle est la méthode recommandée pour décompresser les applications Python GUI?

Je suis actuellement assez fou pour essayer de maintaintain en parallèle les deux bases de code pour un Python application de bureau, en utilisant un PyGObject introspection pour GTK 3 et une à l'aide de PyGTK pour GTK 2. Je travaille principalement sur la PyGObject branche et puis j'port de changements au cours de la PyGTK branche. En raison de toutes les différences mineures entre ces implémentations, je négligent souvent les choses et de provoquer des ruptures qui me manque et accidentellement de presse, que d'être pris par les utilisateurs.

Je suis à essayer de comprendre une bonne façon de concevoir certains unittests qui serait, de préférence, être adapté pour fonctionner sur les deux bases de code. Il n'est pas trop compliqué programme, (il s'agit essentiellement d'une bibliothèque de gestion de l'outil, imaginez comme 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 

J'ai essayé de séparer les points de vue à partir de modèles autant que possible. Chacun de ces éléments est mis en œuvre dans sa propre classe (ainsi, dans les classes qui héritent de la GTK classes inscrites). Les ListViews sont couplés avec d'autres classes qui héritent de ListStores. La bibliothèque est gérée par une classe différente. Néanmoins, il existe des interactions entre les widgets qui doivent être testés. Par exemple, si l'utilisateur sélectionne un élément particulier dans la vue filtre, filtrage de la bibliothèque, puis sélectionne un élément dans les résultats filtrés, l'affichage de texte doit afficher les informations pour la bonne entrée de la bibliothèque, qui est semi-complexe en raison de la traduction que ces dossiers entre TreeModelFilter et l'original ListStore, etc etc.

Donc, je le demande, quelle est la méthode recommandée pour l'écriture robuste unité de tests pour une application GUI? J'ai vu qu'il existe des bibliothèques pour cela, mais les principaux d'entre eux pour pygtk n'ont pas été mis à jour dans années, et ils seront presque certainement un échec avec PyGObject introspection. Peut-être que je ne suis pas assez créatifs pour trouver une bonne façon de le faire à l'aide de Python unittest module, donc je suis ouvert aux suggestions.

6voto

Jürgen Strobel Points 1365

Êtes-vous sûr que vous voulez de l'unité de test de l'interface? Votre exemple de la complexité implique plus de 1 unité et est donc un test d'intégration.

Si vous voulez vraiment de test de l'unité, vous devriez être en mesure d'instancier une classe unique de fournir des simulacres ou des talons de ses dépendances, puis d'appeler des méthodes sur elle, comme le GUI cadre, par exemple, un clic de l'utilisateur. Cela peut être fastidieux et vous devez savoir exactement comment le GUI cadre, les dépêches de l'entrée d'utilisateur pour vos classes.

Mon conseil est de mettre encore plus de choses dans les modèles. Pour votre exemple, vous pourriez créer un FilterManager qui les résumés de tous les filtre/sélectionner/afficher des trucs derrière une seule méthode. L'unité de test.

5voto

anarcat Points 403

Il est un excellent moyen de tester PyGTK fonctions et des widgets directement, sans passer par l'acceptation/fonctionnel/tests d'intégration des cadres clikety leur chemin dans l'oubli. J'ai appris à ce sujet dans ce post qui est assez explicite. Mais l'idée de base est que vous devez traiter vos widgets comme des fonctions/classes, et vous pouvez les tester directement. Si vous avez besoin de traiter les rappels et ainsi de suite, il y a une astuce que je vais reproduire ici:

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)

Comme mentionné dans le billet de blog, ce code est LGPL. Sinon, quand vous pensez à ce sujet, aussi longtemps que vous n'avez pas show() windows ou des widgets, vous pouvez tester tout ce que vous voulez et ils doivent se comporter comme s'ils étaient réels parce que, en un sens, elles sont. Ils sont tout simplement pas affiché.

Bien sûr, vous avez besoin de simuler l'interaction sur des boutons et des widgets interactifs-vous en appelant clicked() sur un bouton par exemple. Voir à nouveau Ali Afshar excellent post sur les tests unitaires dans PyGTK.

2voto

Brandon Invergo Points 2104

En restant fidèle au thème selon lequel Jürgen avait raison, dans la mesure où je ne suis pas intéressé par les tests unitaires , mais plutôt par les tests d'intégration, j'ai également trouvé ce cadre sur freedesktop.org: http://ldtp.freedesktop.org/wiki/

Il permet d'automatiser une variété de tests pour les applications d'interface graphique activées pour l'accessibilité (notamment GTK, Qt, Swing, etc.).

0voto

guettli Points 3284

Vous pouvez utiliser un framebuffer X11:

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

Veillez à ne pas entrer gtk.main() , car cela attendrait une entrée au clavier ou à la souris. Vous pouvez utiliser ce modèle pour laisser gtk gérer tous les événements:

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

Autant que je sache, vous ne pouvez pas voir votre application, mais vous pouvez tester vos rappels.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X