2. 设计原则
接下来介绍一下我用Sahi测试Dojo应用时遵循的几个原则。
1. 面向对象
面向对象早已不是什么新鲜事物。其实,UI自动化测试程序直觉上来讲可以采用过程式的编程模式,因为它本身就是将很多行为串接起来。为什么在测试Dojo应用时要使用面向对象的理念?原因很简单,因为Dojo Widget本身就采用了面向对象的思想。因此,在我的自动化测试框架中,每个Dojo Widget都对应于一个Javascript的“类”,不仅封装了DOM结构而且更便于代码重用。
2. 采用IBM框架(之前叫ITCL - IBM Test Community Leadership)
从事Web自动化测试的读者恐怕对IBM框架不会感到陌生。IBM框架由三层组成:应用对象、任务和测试用例。潜在于应用对象、任务和测试用例包之下的基本原理是:
层次化的体系架构
将“做什么”与“如何做”分离开来
代码重用
一致和清晰的组织结构
快速增强的能力
迅速的调试
有效地组织文件
启用协作
学习他人
下面是对应用对象、任务和测试用例的解释说明:
应用对象:储存有关你的应用程序中的GUI元素信息。同时在这里也可以编写你的Getter 方法,这些 Getter 方法可以返回对象,使 调用者能够对这些GUI元素进行查询和操作。一般情况下,这些方法在Task层中进行调用。
任务:在这里你将编写可重用的方法,这些方法在你的应用程序中执行通用功能。同时在这里,你将编写可以处理和查询复杂的特定应用程序控件的方法。在任务中的方法可以被测试用例调用。
测试用例:导航一个应用程序,验证其状态,并记录其结果的方法。
3. 借助Label识别元素
通常页面上每个元素都会有一个label并且它是“可见”的。所谓“可见”,是指label的值是不需要借助于工具直接能看到的。例如id、name等,必须通过查看源码或者一定的工具,如Firebug查看其属性值。因此通过借助label的元素识别方法可以提高开发效率(因为你不在需要去用工具查看元素属性值了)。
3. 代码详解
三个目录appobjs,tasks以及testcases即是IBM框架中的三层架构,其中的 JobAppFormPage.sah,JobAppFormTasks.sah以及JobAppFormTests.sah分别是应用对象、任务和测试用例程序文件(Sahi脚本)。
Dojo Widget的封装
下面以DojoWidget和Textbox两个类为例讲解Widget的封装。
function DojoWidget($self) {
this.getLabel = function () {
var $widId = getAttribute($self, "widgetid")
_set($labelText, getLabelTextByFor($widId))
return $labelText
}
this.hasError = function () {
var $class = getAttribute($self, "class")
return $class.indexOf("dijitError") == -1 ? false : true
}
}
var $DojoTextbox = function Textbox($elem) {
var $self = findEnclosingWidget($elem, "dijitValidationTextBox")
DojoWidget.call(this, $self)
var $textbox = _textbox("dijitReset dijitInputInner", _in($self))
this.setValue = function ($value) {
_setValue($textbox, $value)
var $current = this.getValue()
_assertEqual($value, $current)
}
this.getValue = function () {
return _getValue($textbox)
}
this.blur = function () {
_blur($textbox)
}
}
core.sah中定义了所有的Dojo widget类。所有的Dojo widget类都继承DojoWidget。DojoWidget定义了一些widget通用的函数,例如getLabel和 hasError。$self变量通过函数findEnclosingWidget获得,这个变量代表了Dojo widget最外层的元素。此函数通过检查父节点中是否有widgetid属性,并且检查class属性的值是否包含指定的标示widget类型的字符串(例如,DojoTextbox的类型字符串是dijitValidationTextBox)来识别widget的最外层元素。Widget的继承通过 call函数实现,它将$self传给DojoWidget类的构造器。$textbox的识别使用了_in函数,这种方法保证了元素识别的准确性。事实上,无论一个widget本身有多复杂,通过_in函数就可以将内部元素查找与外界隔离。大家或许注意到this.setValue函数中有个比较奇怪的地方,this.getValue()的返回值是先赋值给$current变量然后进行断言判断的。为什么不写成 “_assertEqual($value,this.getValue())”呢?这是因为目前Sahi不支持这样的语句,或许将来会支持。
原文转自:http://www.uml.org.cn/Test/201204265.asp