【问题标题】:How do I test-drive GWT development?如何试驾 GWT 开发?
【发布时间】:2009-03-23 15:27:32
【问题描述】:
只需在谷歌上搜索“TDD”和“GWT”即可轻松找到this article,作者解释了他如何在没有容器的情况下测试 GWT 应用程序。但是,我认为他的示例不是测试驱动的,因为他先完成所有设计,然后再编写测试,而不是“测试优先”。
这让我想到:是否可以在像 GWT 这样的 UI 上进行“测试优先”开发?有人说 UI 代码不适合 TDD。但是我认为通过采用MVC模式,也许我们至少可以试驾MC部分? (所以 V 是 UI 部分,不能进行测试驱动开发)。
我们将在文章示例中编写的第一个失败的测试是什么?
【问题讨论】:
标签:
gwt
user-interface
tdd
【解决方案1】:
试驾 UI 是有问题的,因为您通常不知道自己想要在屏幕上显示什么,直到您在屏幕上看到它。出于这个原因,GUI 开发往往是大规模迭代的,因此很难通过测试来驱动。
这并不意味着我们只是放弃了 GUI 的 TDD。相反,我们将尽可能多的代码从 GUI 中推出,只留下简单的接线代码。这种布线使我们能够进行所需的大规模迭代更改,而不会影响问题的本质。
几年前,Michael Feathers 在一篇题为"The Humble Dialog Box" 的文章中对这种技术进行了最好的描述。这也是四年前引起如此轰动的Model-View-Presenter模式背后的基本思想;现在已经分为被动视图和监督控制器模式。这个问题中的文章链接利用了这些想法,但是以测试后而不是测试驱动的方式。
我们的想法是测试除视图之外的所有内容。事实上,我们甚至不需要长时间编写视图。事实上,View 非常简单,以至于它可能根本不需要任何类型的单元测试。或者,如果确实如此,它们实际上可以最后写入。
要试驾监督控制器,您只需确保了解数据在屏幕上的显示方式即可。您不需要知道数据在哪里,或者字体是什么,或者它是什么颜色,或者导致 GUI 大量迭代的任何其他外观问题。相反,您知道一个数据项将是某种文本字段。另一个是菜单,另一个是按钮或复选框。然后确保 View 可以提出它需要提出的所有问题,以正确呈现这些项目。
例如,文本框可能有一个默认值。视图应该能够要求它。菜单中的某些项目可能是灰色的。视图应该能够询问此信息。视图提出的问题都是关于表示的,并且没有业务规则。
同样的道理,当有任何变化时,视图会告诉监督控制器。控制器将适当地修改数据,包括任何类型的验证和错误恢复,然后视图可以询问应该如何呈现数据。
所有这些都可以进行测试驱动,因为它们都与视觉显示分离。这完全是关于如何数据被操纵和呈现,而不是关于它的样子。所以不需要大规模迭代。
【解决方案2】:
我已经通过 GUI 成功地测试驱动了 Swing 和 GWT 应用程序的开发。
“仅在 GUI 后面”进行测试会忽略模型代码和 GUI 组件之间的集成。当模型更改并从 GUI 接收输入并更新模型时,应用程序需要连接事件处理程序以在 GUI 中显示数据。如果手动完成,测试所有这些事件处理程序是否已正确连接是非常乏味的。
通过 GUI 进行测试时要克服的大问题是如何应对开发过程中对 GUI 的更改。
GWT 有帮助解决这个问题的钩子。您需要在 GWT 小部件上设置调试 ID,并将 DebugID 模块导入您的应用程序。然后,您的测试可以通过控制 Web 浏览器、通过 id 查找元素并单击它们或在其中输入文本来与应用程序交互。 Web Driver 是一个非常好的 API。
然而,这仅仅是开始。您还需要将测试与 GUI 的结构分离:用户如何在 UI 中导航以完成工作。无论您是通过 GUI 还是在 GUI 后面针对控制器进行测试,情况都是如此。如果您针对控制器进行测试,则控制器决定了用户在应用程序的不同视图中导航的方式,因此您的测试与该导航结构耦合,因为它与控制器耦合。
为了解决这个问题,我们的测试通过“驱动程序”的层次结构控制应用程序。测试与驱动程序交互,使其能够执行以用户为中心的活动,例如登录、输入订单和付款。驱动程序通过四处导航并将数据输入到 GUI 中来获取有关这些任务如何执行的知识。它通过使用较低级别的驱动程序来实现这一点,这些驱动程序捕获“手势”如何执行导航和数据输入,例如单击按钮或在输入字段中输入文本。您最终会得到如下层次结构:
- 用户目标:测试验证用户可以通过系统实现他们的目标,并演示如何通过一系列...
- 用户活动:用户通过 GUI 执行的操作,表示为执行...的驱动程序...
- 手势:用于控制 GUI 的低级鼠标和键盘输入。
这种层次结构经常在以用户为中心的设计文献中使用(尽管使用不同的术语)。