如果我们要设计一个
测试某个Web Server的框架,可以想象会经常在不同的页面跳转。在跳转的时候,你会希望只需提供url path而不是完整的url。但Watir::IE的goto方法需要全路径,所以一种方法是这样
ie.goto("http://#{$serverip}:#{$serverport}/addUser"); # 用全局变量的方式
但显然我们希望更好的调用方式是
ie.goto("/addUser"); # 理想的调用方式
二者的易用性差别不言而喻。但这就需要修改Watir::IE的行为,让他能接受url path的方式。在这里也体现了
Ruby的强大之处,它的class定义是open的,你可以在任意一个地方修改它。
module Watir
# 修改Watir::IE就是这么简单
class IE
# 参数url定义了协议,地址,和端口
# for example:
# * 10.10.10.10
# * 10.10.10.10:8080
# * http://10.10.10.10
# * https://10.10.10.10
#
# parameter 'attach' is a boolean, true means that if there is an existing IE browser,
# don't launch a new one, jsut attach the ie object to it.
#
# @exception Watir::Exception::NoMatchingWindowFoundException if attaching failed
def initialize(url, attach=false)
Everbright::Basic.assert_true(!url.nil?, "occUrl shouldn't be nil")
url = url.strip.upcase
# "10.10.10.10" => [[nil, nil, "10.10.10.10"]]
# "https://10.10.10.10" => [["https://", "https", "10.10.10.10"]]
resultAry = url.scan( /^((https?):\/\/)?(.+)$/)
@scheme, @occUrl = resultAry[0][0] || "http", resultAry[0][2]
Everbright::Basic.assert_true(!@occUrl.nil?, "no site ip found from #{@occUrl}")
if attach
attach_init(:url, Regexp.compile(url))
else
create_browser_window
set_defaults
end
end
# 这个方法不应该被访问
def IE.start( url = nil )
raise Everbright::Basic::EverbrightException.new("The method shouldn't be called in Everbright framework")
end
# 这个方法不应该被访问
def IE.attach(how, what)
raise Everbright::Basic::EverbrightException.new("The method shouldn't be called in Everbright framework")
end
alias _goto goto
# 我们需要重写goto方法
#
# URL is like: /gateway/login.jsp?user=.....
# URL shouldn't be like: http://10.10.10.10/gateway/login.jsp.....
def goto(path)
return nil if path.nil?
Everbright::Basic.assert_true(!(path =~ /^https?:\/\//), "URL should be like: /gateway/login....")
log "goto: #{path}"
_goto("#{@scheme}://#{@occUrl}#{path}")
end
end
end
这样,一个在
其他语言里实现起来非常麻烦的功能,在ruby里只是a piece of cake.
在c++里,需要实现一个wrapper,把Watir::IE的每个方法都重写一遍,虽然大多数都是简单的转发。在
java里要容易点,如果在容器里流行的是AOP拦截,应该也可以使用DynamicProxy这个高级功能,但总之没有ruby来的优美漂亮。