使用 Ruby 实现业务驱动的 Web 应用程序测试(2)

来源:developerWorks 中国 作者:刘 欣
  execute, 当把 bookshop.txt 作为参数来调用它时,会有什么情况发生呢 ? 聪明的读者可能已经猜到了,那就是 user 和 pwd 的值会被打印出来。这段代码展示了 Ruby 语言的两个重要特点 :

  1. instance_eval 方法会把一段文本当做代码来执行。执行的上下文就是对象 BookshopDSLBuilder。 所以当它碰到文本 "login" 时,会自动调用真正的方法 login
  2. 在调用一个方法时,可以不加括号。这就是为什么 Ruby 会把文本 login "andy","pass4you" 当做一个方法调用的原因。

这两个特点就给我们搭了一座“桥”,使得我们可以把那个面向业务测试的文本诸如“login”,“add_to_cart”,“search_book”等转化为对特定方法的调用了。我们就可以在这些方法中实现某些逻辑。

Watir

我们现在已经能够把业务测试的脚本和 Ruby 的对象 / 方法连接起来,可是还需要第二座桥把 Ruby 和 Web 应用程序连接起来,这样才能使业务测试的脚本驱动 Web 页面进行测试。我们希望能有一个软件或工具可以像人一样来驱动浏览器的操作,例如点击链接,填充表单,点击按钮等等。当然它也可以检查页面的结果,例如期待的文本是否出现等。

开源工具 Watir 就是这样一个工具,除了具备上述功能外,它和 Ruby 语言还能进行无缝的集成,并且对浏览器尤其是 IE 有超强的控制能力。所以我们选取它作为第二座桥。

下面是一个使用 watir 的简单例子,它进入 Google 的首页,在搜索框中键入 "bookshop", 然后点击"搜索"按钮。 Watir 充分继承了 Ruby 语言简单明了的特点,读者可以看到使用 Watir 的脚本是相当直观,相当容易的。


清单 2. Watir 例子
				 
require "watir"
ie = Watir::IE.new 
ie.goto "http://www.google.com"       
ie.text_field(:name, "q").set "bookshop"
ie.button(:name, "btnG").click 
       

实现 Login


有了上面的两座“桥”,具体的实现就简单多了,对于每一个业务操作,我们需要做的是 :
(1) 在一个 Ruby 对象中 (BookshopDSLBuilder) 实现一个同名的方法
(2) 在方法实现中,利用 watir 来操作界面元素。当然前提是我们需要知道界面上有哪些元素。
先来看一看 Login 的实现:
清单 3. Login
				 
class BookshopDSLBuilder 
  include Test::Unit::Assertions  #include ruby unit 的 Assertion 
  def self.execute( dsl) 
    builder=new 
    builder.instance_eval(File.read(dsl), dsl) 
    builder 
  end  
  def initialize 
    @login_url = 'http://localhost:3000/bookshop/login'   #51Book 的入口
    #creat a ie instance 
    @ie= Watir::IE.new                             # 创建一个 Watir 的实例
  end 
  def login(user=nil,pwd=nil) 
    @ie.goto  @login_url 
    @ie.text_field(:id,"user_name").set(user)      # 设置用户名
    @ie.text_field(:id,"user_password").set(pwd)   # 设置密码
    @ie.button(:type,"submit").click               # 点击提交按钮
  end 
end 
     

实现 add_to_shop_cart

把书籍添加的购物车中这个操作相对复杂,因为它接收的参数是一个书籍的标题,而在界面上"Add to Cart"却是一个只包含 book id, 不包含标题的链接,所以无法直接定位。


清单 4. Add to Cart
				 
 <table width='100%' class='book'> 
    <tr> 
        <td>title:</td> 
        <td>Agile development</td> # 标题在这里
    </tr> 
    <tr> 
        <td>description:</td> 
        <td>The book of agile development</td> 
    </tr> 
    <tr> 
        <td>price:</td> 
        <td>30.0</td> 
    </tr> 
    <tr> 
        <td colspan="2"> #Add_To_Cart Link 却在这里
            <a href='/bookshop/add_to_cart/1' >Add to Cart</a> 
        </td> 
    </tr>    
 </table> 
     

这种情况下就可以利用 Watir 对 xpath 强大的支持,先找到标题,在从标题找到链接,最后点击链接即可。


清单 5. 使用 XPath
				 
def add_to_cart(title)        
    table = @ie.table(:xpath, 
          "//table[@class='book']/tbody/tr/td[text()='"+title+"']/../../../") 
    if  table[1][2].text  == title 
        href =  table[4][1].links[1].href 
        @ie.link(:href,href).click 
    end 
end     

对于其他的业务操作,具体的实现方式也是大同小异,这里不再一一介绍,有兴趣的读者可以参见 附件 中的代码,最后我们来看一个面向业务的 Web 页面测试例子:


清单 6. 一个完整的例子
				 
 login 'andy','pass4you' 

 add_to_cart 'Agile development'
 add_to_cart 'Savor Blue'
 add_to_cart 'Programming Ruby' 

 change_quantity 'Agile development',10 
 change_quantity 'Savor Blue',10 
 change_quantity 'Programming Ruby',10 

 recalculate_cart 
 assert_total_price_is 900 

 search_book 'Ant cookbook'
 add_to_cart 'Ant cookbook'
 assert_total_price_is 910 
     

总结

到目前为止,我们已经通过 Ruby 完整的实现了“业务驱动” 的 Web 应用测试,实际上我们通过 Ruby 实现了一个面向业务的抽象层,利用 Watir 把业务操作映射到了对 Html 页面的操作。这样当 Html 页面发生了变化的时候,只需要调整映射,而不需要更改业务层的操作。同时由于它们是完全面向业务的,就使得开发人员或测试人员能把精力集中到业务逻辑的测试上,而不用陷入实现的细节。

掌握了该方法以后,读者可以应用到自己的程序中,可以使得自己的测试编写简单,容易理解,易于维护。将会极大的提供 Web 应用的测试效率。(责任编辑:A6)


时间:2009-08-04 09:38 来源:developerWorks 中国 作者:刘 欣 原文链接

好文,顶一下
(1)
100%
文章真差,踩一下
(0)
0%
------分隔线----------------------------


把开源带在你的身边-精美linux小纪念品
无觅相关文章插件,快速提升流量