修改Ruby WATIR库方法,使其稳定支持IE8浏览器的upload功能

最近在用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的话,用这个方法就能很稳定的通过。

 
修改Ruby WATIR库方法,使其稳定支持IE8浏览器的upload功能_第1张图片
 

所以我查找了一下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结束,而直接运行下一句,需要自己手动添加很多等待判断才能稳定执行。还不知道为什么会这样

你可能感兴趣的:(upload)