使用Sahi测试Dojo应用(3)

发表于:2012-04-13来源:InfoQ作者:沈锐点击数: 标签:Sahi
下面以DojoWidget和Textbox两个类为例讲解Widget的封装。 function DojoWidget($self) { this.getLabel = function () { var $widId = getAttribute($self, widgetid) _set($labelText, getLabelText

  下面以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不支持这样的语句,或许将来会支持。

  findByLabel的实现

  function findByLabel($labelText, $className) {

  var $label = _label($labelText)

  var $wid = getAttribute($label, "for")

  _set($id, findIdByWID($wid))

  var $div = _byId($id)

  return new $className($div)

  }

  

  function findIdByWID($wid) {

  var $widget = dojo.query("[widgetid='" + $wid + "']")[0]

  return $widget.getAttribute("id")

  }

  

  通过元素label标识元素的原则通过findByLabel函数实现。它有两个参数,第一个是label的文本内容,第二个是目标widget的实现类。实现原理很简单。label元素的for属性值就是widget的widgetid的值。因此,我们通过widgetid就可以找到widget元素。但事实上,从下面大家看出来我们是先利用的dojo.query找到了元素对应的id,然后通过_byId获得widget元素。为什么用这种迂回的方法呢?根据Sahi的文档,理论上我们是可以通过修改concat.js文件增加widgetid查找属性(具体参见http://sahi.co.in/w/tweaking-sahi-apis)可以实现利用_div,_table或者_span等函数直接获得widget元素。不幸的是,当前版本中存在的一个bug导致自定义属性不能被识别。所以,目前只能先通过widgetid找id的方法迂回解决。另外,值得一提的是因为findIdByWID函数用到了dojo的库函数,因此它被定义在browser tag中。

  数据驱动

  Sahi自带对CSV,Excel以及数据库访问的函数。示例代码示范了如何使用CSV进行数据驱动测试。让我们一起来看看JobAppFormTests.sah中的testSimple函数。被注释掉的部分是一般的定义测试数据的方法。_readCSVFile函数加载testdata.csv到$data变量,它事实上一个两维数组。_dataDrive函数能够自动遍历数组数据调用fillForm函数。

  function testSimple() {

  /*

  var $eduValue="masters"

  var $nameValue="my name"

  var $addressValue="Shanghai"

  var $stateValue="California"

  fillForm($nameValue,$eduValue,$addressValue,$stateValue)

  */

  var $data = _readCSVFile("./testdata.csv")

  _dataDrive(fillForm, $data)

  }

  testdata.csv内容:

  Tom, high school, Address1, Alaska

  Mike, masters, Address2, Florida

  John, PhD, Address3, Hawaii

  其他

  另外,Sahi提供了类似于JUnit的测试框架。所有以test开头的函数都被认为是测试用例,如果有setUp和tearDown函数,它们会分别在每个测试用例运行前后执行。并且所有测试文件还是可以组织到一个.suite文件中作为一套测试用例运行。更详细的介绍,请大家参考Sahi的官方文档。Sahi也能支持拖放,大家可以参考示例代码中Slider widget的实现。文件上传是很多Web自动化测试的局限,不过,Sahi得益于它Proxy的架构也实现了文件上传功能。

  三.结束语

  总的来说,Sahi是一款不错的Web自动化测试工具,尤其是它对元素关联查找的支持以及页面隐式等待的机制对Web2.0应用的测试是很有帮助的。希望读者阅读完本文能有所收获。如果,想了解更多关于Sahi的信息,请访问Sahi的官方网站(http://sahi.co.in/w/) 并且可以通过访问http://www.slideshare.net/narayanraman 观看Sahi的推广演示文档。如果对Sahi与Selenium的比较感兴趣,可以访问http://blog.sahi.co.in/2010/04/sahi-vs-selenium.html 。

原文转自:http://www.ltesting.net