Seleniumで明示的に要素検索の待ち時間を設定する
この記事は よちよち.rb Advent Calendar 2014 10日目の記事です。 9日目は5t111111さんによる審判の雷 Lightning Pickerでした。
自分の妄想を思わずアプリにしてしまうような人に私も成りたいです!
今回書くこと
社内でSeleniumおじさんになることを目指して日々格闘していますので、その内容を記録したいと思います。
テーマとしては、「要素を探しにいく待ち時間について」です。
具体的には、データの入力を繰り返す処理をしている中で、データによって確認アラートが出るときと出ないときがあり、出るときは閉じたいのですが、出ているかの確認で要素(確認アラート)を探している時間がいちいち長かったので短くしたい、という内容になります。伝わりますかね・・・
ただ、短くしたいというのは、イレギュラーケースな気がしていまして(というかその目的の実現はあまり綺麗には出来ていないと反省中なので)、特定の処理だけ長く待ちたいとかに使うのが多いみたいです。そういう例が多かったです。画像重たいので、長めに待ちたい、とかですね。
ちなみに、Rubyはcapybaraを使うことが多いためなのか、selenium webdriverを使っているサンプルがあまり見つけられない気がします。Javaとかの例が多い気がします。私もcapybaraを使えば良い、ということかもしれません。
参考にしたもの
実践 Selenium WebDriver
- 作者: Satya Avasarala,Sky株式会社玉川竜司
- 出版社/メーカー: オライリージャパン
- 発売日: 2014/09/18
- メディア: 大型本
- この商品を含むブログ (3件) を見る
動作環境
やり方
Selenium::WebDriver::Waitというクラスがあり、このクラスが持つuntilメソッドを使いました。 untilメソッドは引数にブロックを取り、ブロックの返り値がtrueになるまでブロックの処理を繰り返すようです。
Selenium::WebDriver::Waitのnewで待ち時間を設定出来るので、この待ち時間だけブロック処理を繰り返して、falseが続く場合には最後はタイムアウトエラーが発生します。
例えば、
wait = Selenium::WebDriver::Wait.new({timeout: 10}) wait.until do false end
上記例では、ずっとfalseが返るので、10秒経過するとタイムアウトエラーになります。
APIリファレンスで、untilのソースを見てみると、
# File 'rb/lib/selenium/webdriver/common/wait.rb', line 33 def until(&blk) end_time = Time.now + @timeout last_error = nil until Time.now > end_time begin result = yield return result if result rescue *@ignored => last_error # swallowed end sleep @interval end # 以下略
となってました。return result if result
とありますので、とにかくブロックの結果がtrue(truthy)ならそのまま結果を返してしまうみたいですね。逆に、繰り返すためには、ブロックの結果がfalseにならないといけないみたいです。
なので、私は、
wait = Selenium::WebDriver::Wait.new({timeout: 0.5}) begin wait.until do begin # 要素があったら実行するよという処理 rescue false end end rescue # タイムアウトは揉み消す end
のような形で、処理短縮を目指しました。(この場合、最初の処理の時間が長かったら意味がないと思いますが) ちょっとゴリゴリ感が否めないので、きっともっと良い書き方があるのではと模索中です。
明日のよちよち.rb Advent Calendar 2014は、waterlow さんの「私のよちよち.rb活用法」です!気になるタイトルですね~