最近在用watir作一个自动化脚本。我使用的浏览器是IE8,因为产品需要支持IE8 。由于发现ruby187+watir1.5.5 并不支持IE8的一些功能,所以升级到ruby193+watir 1.6.5。然后在我尝试用浏览器上传文件的时候,watir自带的方法还是没法很好的自动化该步。我用的是@browser.file_field(:name,"file").set($FILE_PATH)方法,会卡在如下的页面没法继续。但是用ruby187+watir1.5.5+IE6的话,用这个方法就能很稳定的通过。
所以我查找了一下watir的代码,最后发现这个file_field的set方法是定义在 D:\Ruby193\lib\ruby\gems\1.9.1\gems\watir-1.6.5\lib\watir\input_elements.rb中的。
class FileField < InputElement
INPUT_TYPES = ["file"]
POPUP_TITLES = ['Choose file', 'Choose File to Upload']
# set the file location in the Choose file dialog in a new process
# will raise a Watir Exception if AutoIt is not correctly installed
def set(path_to_file)
assert_exists
require 'watir/windowhelper'
WindowHelper.check_autoit_installed
begin
Thread.new do
sleep 1 # it takes some time for popup to appear
system %{rubyw -e '
require "win32ole"
@autoit = WIN32OLE.new("AutoItX3.Control")
time = Time.now
while (Time.now - time) < 15 # the loop will wait up to 15 seconds for popup to appear
#{POPUP_TITLES.inspect}.each do |popup_title|
next unless @autoit.WinWait(popup_title, "", 1) == 1
@autoit.ControlSetText(popup_title, "", "Edit1", #{path_to_file.inspect})
@autoit.ControlSend(popup_title, "", "Button2", "{ENTER}")
exit
end # each
end # while
'}
end.join(1)
rescue
raise Watir::Exception::WatirException, "Problem accessing Choose file dialog"
end
click
end
end
上面是watir 1.6.5 的代码,可以看到他是有考虑到IE8窗口title为'Choose File to Upload'的情况,IE6这个窗口的title是'Choose file'。但是运行仍然失败,可能是多线程时间上的一些原因。我尝试着做了一些修改,现在能稳定地支持IE8了,因为我只需要它支持IE8 ,所以没有考虑IE6 窗口title为'Choose file'的情况。我修改的代码如下
class FileField < InputElement
INPUT_TYPES = ["file"]
# set the file location in the Choose file dialog in a new process
# will raise a Watir Exception if AutoIt is not correctly installed
# This method has been restore back to 187 code by Wren. It's not 193 code.
def set(path_to_file)
assert_exists
require 'watir/windowhelper'
WindowHelper.check_autoit_installed
begin
Thread.new do
#sleep 1 # it takes some time for popup to appear
system %{rubyw -e '
require "win32ole"
@autoit = WIN32OLE.new("AutoItX3.Control")
popup_title="Choose File to Upload" # IE 8
if @autoit.WinWait(popup_title, "", 5) == 1
@autoit.ControlSetText(popup_title, "", "Edit1", #{path_to_file.inspect})
@autoit.ControlSend(popup_title, "", "Button2", "{ENTER}")
end # if
'}
end.join(1)
rescue
raise Watir::Exception::WatirException, "Problem accessing Choose file dialog"
end
click
end
end
小结,没有研究出之前watir代码不成功的原因,只是通过尝试,试出了一种比较稳定的代码替换之。以后对线程这块还要多学习。另外,直接修改本地watir的源代码非常不妥,应该把这个方法在我的项目代码里重新定义一遍比较安全。希望能给遇到同样问题的朋友一点帮助,同时也期待专家指点一下,为何原来的那段代码会卡在我截图的页面无法前进。
2013年1月2号,追加:
关于这篇文章后来我又有了新的认识,当时我用的是watir 1.6.5 版本,对IE8的支持还不是特别稳定。现在watir最新的版本是4.0.n了,而且watir库分为watir-classic和watir-webdriver。watir-classic貌似是继承了老的watir模式,其中的这个file_field的set方法已经重构过了,而且非常稳定的支持了IE8。现在准备尝试将过去的测试脚本升级到4.0的watir-classic,目前发现比较棘手的问题是watir-classic非常不稳定,远不如1.6.5,比如点一个按钮导致页面跳转后,它不会自动等待新页面load结束,而直接运行下一句,需要自己手动添加很多等待判断才能稳定执行。还不知道为什么会这样