InfoQ编辑注:本文源自Martin Fowler,文章最初由ThoughtWorks工程师黄博文翻译在自己的博客上,并由译者本人推荐至InfoQ中文站博文共赏专栏。本译文在Martin Fowler本人的许可下,由InfoQ中文站进行修订后,在这里给大家分享。
当你在为Web页面编写测试时,你需要操作该Web页面上的元素来点击链接或验证显示的内容。然而,如果你在测试代码中直接操作HTML元素,那么你的代码是及其脆弱的,因为UI会经常变动。一个page对象可以封装一个HTML页面或部分页面,你可以通过提供的应用程序特定的API来操作页面元素,而不需要在HTML中四处搜寻。
page对象的一个基本经验法则是,凡是人类能做的事,page对象通过软件客户端都能够做到。它也应当提供一个易于编程的接口并隐藏窗口中低层的部件。所以访问一个文本框应该通过一个访问方法(accessor method)来实现字符串的获取与返回,复选框应当使用布尔值,按钮应当被表示为行为导向的方法名。page对象应当将在GUI控件上所有查询和操作数据的行为封装为方法。一个好的经验法则是,即使改变具体的控制,page对象的接口也不应当发生变化。
尽管该术语是”页面“对象,并不意味着针对每个页面建立一个这样的对象,比如页面有重要意义的元素可以独立为一个page对象[1]。所以,一个显示多个相册的页面可以有一个相册列表的page对象,该对象包含了几个相册page对象。也有可能会有一个页眉page对象及一个页脚page对象。也就是说,如果某些复杂UI的层次结构只是用来组织UI,那么它就不应当与page对象扯上关系。经验法则的目的在于通过给页面建模,从而对应用程序的使用者变得有意义。
同样,如果你导航到另一个页面,初始page对象应当返回另一个page对象作为新页面[2]。一般而言,page对象的操作应当返回基本类型(字符串,日期)或另一个page对象。
一个有意见分歧的地方是page对象是否应自身包含断言,或者仅仅提供数据给测试脚本来设置断言。在page对象中包含断言的倡导者认为,这有助于避免在测试脚本中出现重复的断言,可以更容易的提供更好的错误信息,并且提供更接近只做不问风格的API。不在page对象中包含断言的倡导者则认为,包含断言会混合访问页面数据和实现断言逻辑的职责,并且导致page对象过于臃肿。
我赞成在page对象中不包含断言。我认为你可以通过为常用的断言提供断言库的方式来消除重复,这还可以提供更好的诊断。[3]
page对象通常用于测试中,但自身不应包含断言。它们的职责是提供对基本页面状态的访问,实现断言逻辑则是测试客户端的职责。
我所描述的这个模式针对HTML,但同样的模式也同样适用于任何UI技术。我见过这种模式有效的隐藏了Java swing UI的细节,并且我深信它已经被广泛的应用于几乎所有其他的UI框架。
并行问题是另一个page对象可以封装的话题。这可能涉及异步操作中隐藏不作为异步呈现给用户的异步性,也有可能涉及封装UI框架中你不得不担心的UI和工作线程之间分配行为的线程问题。
page对象在测试中的使用非常常见,但是也被用于在应用程序上层提供一个脚本接口。一般而言,我们最好将脚本接口置于UI下层,这样做的复杂底,执行速度快。然而,对于在UI层有太多行为ide应用程序而言,使用page对象可能是在槽糕的工作中最好的选择。(但是尽量将UI操作逻辑移入到page对象中,长期来看会导致更好的脚本以及更健康的UI。)
使用一些领域特定语言来书写测试非常普遍,比如Cucumber或一门内部DSL。如果你尽量在page对象层级之上编写测试DSL,那么你可以通过一个解析器将DSL声明转换为调用page对象。
如果你在测试方法中使用了WebDriver API,那么你做错了 —— Simon Stewart.
对于那些将逻辑从页面元素中剥离的模式(例如Presentation Model,Supervising Controller及Passive View)而言,在UI层面做测试用处不大,所以也不太需要page对象了。
page对象是封装的一个典型示例。它们从其它组件(如测试)部件中隐藏了UI结构的细节。如果你自问“我如何能从软件测试中隐藏细节?”,当你做开发时在这样的情况采用page对象不失于一个好的设计原则。封装体现了两方面的好处。我已经强调,通过将操作UI的逻辑限制到单个地方有助于你修改逻辑而不影响系统的其他组件。一个间接的好处是使测试端代码更容易理解,因为逻辑是关于测试的意图,而不会被UI细节搞乱。
我刚开始将这种模式命名为窗口驱动(Window Driver)。然而自从Selenium web测试框架使用“page object”这个名称,page对象变成了常用的名称。
Selenium的维基强烈推荐使用page对象,并提供了如何使用它们的建议。它也赞成page对象不包含断言。
Perryn Fowler、Pete Hodgson及Simon Stewart为这篇博客的草稿提供了非常有用的意见。同样像往常一样我非常感激ThoughtWorks软件开发列表中的形形色色的参与者提供的建议和修正意见。
本文出处:http://martinfowler.com/bliki/PageObject.html