【问题标题】:ruby does not look beyond the first rescue code?ruby 没有超越第一个救援代码?
【发布时间】:2012-04-06 06:31:59
【问题描述】:

根据我对文档的理解,这个一般的approach 应该可以工作:

begin
 try1
rescue
 try2
rescue
 try3
.
.
.
rescue
 puts "Everybody failed, sorry man!"
end

但是,每当我尝试打开 Watir-Webdriver 浏览器时,它似乎永远不会尝试超过第二个 $browser = Watir::Browser.new,在第 189 行以 连接被拒绝 - connect(2) (Errno::ECONNREFUSED)

代码.rb:

begin
 $browser = Watir::Browser.new(:firefox, :profile => "botmode") # **line 186**

rescue
 $browser = Watir::Browser.new(:remote, :url => "http://127.0.0.1:4444/wd/hub", :desired_capabilities => :firefox)   # **line 189**

rescue  # local selenium htmlunit
  puts __LINE__.to_s + ": #{$!}"    
#  $browser = Watir::Browser.new(:remote, :url => "http://127.0.0.1:4444/wd/hub", :desired_capabilities => :htmlunit)  # but needs Javascript for AJAX support...
  $browser = Watir::Browser.new(:remote, :url => "http://127.0.0.1:4444/wd/hub", :desired_capabilities => Selenium::WebDriver::Remote::Capabilities.htmlunit(:javascript_enabled => true, :cssSelectorsEnabled=>true, :nativeEvents=>false) ) 

rescue # Try to use VentanaPC if still failing..  
 $browser = Watir::Browser.new(:remote, :url => "http://5.19.111.226:4444/wd/hub", :desired_capabilities => :firefox)  

rescue  # no browser left to failover to
  puts __LINE__.to_s + ": #{$@.to_s}"
end

# ruby -v
ruby 1.9.2p290 (2011-07-09 revision 32553) [i686-linux]

为了让第186行失败,我特意将DISPLAY=:88提前设置为一个不存在的Xserver,所以这个错误是可以的:186: unable to get stable firefox connection in 60 seconds (127.0.0.1:第7055章)

我在哪里出错了,或者有更好的方法吗?这是 Selenium 或 Watir 特有的东西吗?

【问题讨论】:

    标签: ruby exception-handling selenium watir-webdriver rescue


    【解决方案1】:

    你的假设是错误的,这并不像你期望的那样工作:

    irb(main):062:0> begin
    irb(main):063:1*   raise StandardError
    irb(main):064:1> rescue
    irb(main):065:1>   puts "test1"
    irb(main):066:1>   raise StandardError
    irb(main):067:1> rescue
    irb(main):068:1>   puts "test2"
    irb(main):069:1> end
    test1
    StandardError: StandardError
        from (irb):66:in `rescue in irb_binding'
        from (irb):62
        from /usr/bin/irb:12:in `<main>'
    

    test2 不打印。多个rescues 用于不同的异常类型,您无法在其他rescue 块中捕获错误。您可以改为使用嵌套的begin/rescue 块,但这种情况似乎足够复杂,可以使用更通用的方法:

    methods = [
      lambda { Watir::Browser.new(:firefox, :profile => "botmode") },
      lambda { Watir::Browser.new(:remote, :url => "http://127.0.0.1:4444/wd/hub", :desired_capabilities => :firefox) },
      lambda { Watir::Browser.new(:remote, :url => "http://127.0.0.1:4444/wd/hub", :desired_capabilities => Selenium::WebDriver::Remote::Capabilities.htmlunit(:javascript_enabled => true, :cssSelectorsEnabled=>true, :nativeEvents=>false) ) },
      lambda { Watir::Browser.new(:remote, :url => "http://5.19.111.226:4444/wd/hub", :desired_capabilities => :firefox) },
    ]
    
    def get_first_successful(methods)
      methods.each do |m|
        begin
          return m.call
        rescue
        end
      end
      nil
    end
    
    $browser = get_first_successful(methods)
    

    这将选择第一个不会失败的方法。但是,如果第二个失败,我看不出最后一个如何成功,您可以在这里重新考虑您的选择。

    【讨论】:

    • 谢谢!我在我的脚本中广泛使用这种重试故障转移,通常代码块有几行长。将get_first_successful 添加到我的个人库中。这里的最后/第四种方法使用了不同的主机,我在irb 中确认了它的工作原理@
    【解决方案2】:

    多个救援是为了从不同的异常类型中救援;您所拥有的是一个带有一堆不合格救援的单个块,因此只有一个会触发。您想要嵌套开始/救援/结束,或完全不同的方法。

    【讨论】:

    • 我已经编写了嵌套代码,它可以工作,但很快就变得非常混乱,而我所需要的只是不断尝试代码块,直到一个代码块工作为止。我不知道有哪些不同的精简方法——除非有一种方法可以在每个 rescue 之后重置异常类型处理?
    • @Marcos 请参阅 Niklas 的回答,尽管我可能只是将参数保存在地图或其他东西中,而不是使用 lambdas——这并不重要。
    【解决方案3】:

    第一个rescue 将捕获任何StandardError。其他人也是如此,但由于这些错误已经被第一个rescue 捕获,他们将永远没有机会真正遇到任何StandardError

    【讨论】:

      猜你喜欢
      • 2013-07-13
      • 1970-01-01
      • 1970-01-01
      • 2012-02-26
      • 1970-01-01
      • 1970-01-01
      • 2023-01-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多