Search code examples
rubyexceptionseleniumwatir-webdriverrescue

ruby does not look beyond the first rescue code?


From my understanding of the docs this general approach should work:

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

However whenever I try to open up a Watir-Webdriver browser, it never seems to try beyond the second $browser = Watir::Browser.new, ending the script in line 189 with Connection refused - connect(2) (Errno::ECONNREFUSED)

Code.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]

To make line 186 fail, I deliberately set DISPLAY=:88 in advance to a non-existent Xserver, so this error is okay: 186: unable to obtain stable firefox connection in 60 seconds (127.0.0.1:7055)

Where am I going wrong here, or is there a better way to do this? Is this something particular to Selenium or Watir?


Solution

  • Your assumption is wrong, this does not work as you expect:

    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 is not printed. Multiple rescues are for different exception types, you can't catch errors in other rescue blocks like that. You could instead use nested begin/rescue blocks, but this case seems complex enough to use a more general approach:

    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)
    

    This will select the first method which doesn't fail. However, I don't see how the last one could be successful if the second one failed, you might rethink your options here.