单元测试Python GUI应用程序的推荐方法是什么?

时间:2011-08-26 15:09:26

标签: python unit-testing user-interface pygtk pygobject

我目前很愚蠢,试图为Python桌面应用程序维护两个并行代码库,一个使用PyGObject内省GTK 3,另一个使用PyGTK for GTK 2.我主要使用PyGObject分支,然后我端口更改到PyGTK分支。由于这些实现之间的所有细微差别,我经常忽略事情并导致我想念和意外释放的破损,只是被用户抓住。

我正试图找出一种设计一些单元测试的好方法,这些单元测试最好适合在两个代码库上运行。这不是一个过于复杂的程序,(它本质上是一个图书馆管理工具,想像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模块做到这一点的好方法,所以我愿意接受建议。

4 个答案:

答案 0 :(得分:6)

您确定要单元测试GUI吗?您的复杂性示例涉及超过1个单元,因此是集成测试。

如果你真的想进行单元测试,那么你应该能够实例化一个为其依赖项提供模拟或存根的类,然后调用它上面的方法就像GUI框架那样。用户点击。这可能很乏味,您必须确切知道GUI框架如何将用户输入分派给您的类。

我的建议是在模型中添加更多东西。对于您给出的示例,您可以创建一个FilterManager,它抽象出单个方法后面的所有过滤器/选择/显示内容。然后进行单元测试。

答案 1 :(得分:5)

有一种很好的方法可以直接测试PyGTK函数和小部件,而无需通过接受/功能/集成测试框架,这些框架可能会被遗忘。我在this post中了解到这一点,这是相当自我解释的。但基本思想是将小部件视为函数/类,并且可以直接测试它们。如果你需要处理回调等等,我会在这里重现一个巧妙的技巧:

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()来自己模拟按钮和交互式小部件上的交互。再次查看Ali Afshar's excellent post about unit testing in PyGTK

答案 2 :(得分:2)

坚持Jürgen正确的主题,因为我对 unit 测试不感兴趣,但实际上对集成测试感兴趣,我也从freedesktop.org找到了这个框架: http://ldtp.freedesktop.org/wiki/

它允许为启用辅助功能的GUI应用程序(包括GTK,Qt,Swing等)自动执行各种测试。

答案 3 :(得分:0)

您可以使用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您无法看到自己的应用程序,但可以测试回调。