ruby не смотрит дальше первого спасательного кода?

Насколько я понимаю документы, этот общий подход должен работать:

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

Однако всякий раз, когда я пытаюсь открыть браузер Watir-Webdriver, кажется, что он никогда не пытается дальше второго $browser = Watir::Browser.new, заканчивая скрипт в строке 189 с отказом в соединении - подключить(2) (Errno::ECONREFUSED)

Код.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 + ": #{[email protected]_s}"
end

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

Чтобы строка 186 не работала, я намеренно заранее установил DISPLAY=:88 на несуществующий X-сервер, так что эта ошибка в порядке: 186: невозможно установить стабильное соединение Firefox за 60 секунд (127.0.0.1:7055)< /эм>

Где я ошибаюсь, или есть лучший способ сделать это? Это что-то особенное для Selenium или Watir?


person Marcos    schedule 21.03.2012    source источник


Ответы (3)


Ваше предположение неверно, это не работает так, как вы ожидаете:

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 не печатается. Несколько rescue предназначены для разных типов исключений, вы не можете поймать ошибки в других подобных блоках 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)

Это выберет первый метод, который не даст сбой. Однако я не понимаю, как последний может быть успешным, если второй потерпит неудачу, вы можете переосмыслить свои варианты здесь.

person Niklas B.    schedule 21.03.2012
comment
Спасибо! Я широко использую этот повторный аварийный переход в своих сценариях, и обычно блоки кода имеют длину в несколько строк. Добавил get_first_successful в мою личную библиотеку. Последний/четвертый метод здесь использует другой хост, который, как я подтвердил, работает в irb - person Marcos; 21.03.2012

Первый rescue поймает любой StandardError. То же самое и с другими, но поскольку эти ошибки уже обнаружены первым rescue, у них никогда не будет шанса столкнуться с StandardError.

person sawa    schedule 21.03.2012

Множественные спасения предназначены для спасения от разных типов исключений; то, что у вас есть, — это один блок с кучей неквалифицированных спасательных операций, поэтому сработает только одно. Вам нужны вложенные начало/спасение/концы или вообще другой подход.

person Dave Newton    schedule 21.03.2012
comment
Я написал вложенный, и он работает, но очень быстро стал очень грязным, когда все, что мне нужно было, это продолжать пробовать блоки кода, пока один не сработает. Я не знаю других экономичных подходов, если только не существует способа сбросить обработку типов исключений после каждого rescue? - person Marcos; 21.03.2012
comment
@Marcos См. ответ Никласа, хотя я мог бы просто сохранить параметры на карте или что-то в этом роде, а не использовать лямбда-выражения - не имеет большого значения. - person Dave Newton; 21.03.2012