ハバナ式継続的デリバリー

Python, Ubuntu, JavaScript 色々知らなかった!のメモ

SeleniumでExplicitWaitは何のために使うのか?

SeleniumのWait(待機) -- 暗黙的待機/明示的待機

Seleniumは端末を操作するときに処理が返ってくるまでの待ち時間を設定できる。
その際、ImplicitWait(暗黙的待機)とExplicitWait(明示的待機)の2種類仕組みがあることは本とかブログでよく語られることだ。

ExplicitWait -- 明示的待機

明示的待機はWebDriverのPythonバインディングのコードを例に取ると、

from selenium.webdriver.support.ui import WebDriverWait

WebDriverWait(driver, 8).until(
    lambda x: x.find_elements_by_css_selector('.hello')
)

こんな風にすると、'hello'というcssクラスを持つエレメントがDOMの中に現れるまで最大8秒まで待つ。

単純に、time.sleepで8秒待つんじゃなくて、エレメントが登場すれば8秒以内に処理が戻ってくる点が良い。

ImplicitWait -- 暗黙的待機

対して、ImplicitWaitというやつは何に使うのかというと、そのSeleniumセッションで最低何秒待つかを設定するために使う。

Selenium-WebDriverの仕組みとしては、find_なんちゃらといったDOM要素を探すメソッドを呼ぶと、探そうとしている要素が出現するまで待つ。
デフォルトだと永遠に待つ。だから、絶対に出現しない要素を取り出そうとするとずっと待ちになって処理が終わらない。

だから、だいたい4秒以内にテスト対象のアプリケーションが応答すると見込みをつけて

from selenium import webdriver

driver = webdriver.Firefox()
driver.implicitly_wait(4)
# fooをクリックした後にbarをクリック
driver.find_element_by_css_selector('.foo').click()
driver.find_element_by_css_selector('.bar').click()

こんなコードを書くのである。

こうすると、最初のクリック対象であるfooが画面に出現するまで4秒待って、それでもfooが出現しなければ例外が出て処理が失敗する。
fooが4秒以内に出現すればbarを探しに行く。

そうすると、あまり細かいことを気にしなければ暗黙的待機だけ設定しておけば良いじゃないかということになる。

ExplicitWaitの想定利用ケース

で、結局明示的待機はどういうときに使うべきなのかというと、

通常より遅い処理が走る操作を実行するとき

foo, barのボタンは大抵4秒で処理が終わるけど、bazボタンを押したときの処理は遅くて8秒かかるといった場合に明示的待機と暗黙的待機を使い分ける。

コードを示すと

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait

driver = webdriver.Firefox()
driver.implicitly_wait(4)
# fooをクリックした後にbarをクリック
driver.find_element_by_css_selector('.foo').click()
driver.find_element_by_css_selector('.bar').click()

# bazをクリック(待ち時間が長い)
WebDriverWait(driver, 8).until(
    lambda x: x.find_elements_by_css_selector('.baz')
).click()

こんなかんぎ(カツヒコ風に)。

まずこれが最も一般的な利用ケース。

ある処理を実行して特定の要素がDOMから無くなることを確かめるとき

例えば

  • 添付ファイルをアップロードすると削除用のゴミ箱アイコンが画面に表示される。
  • ごみ箱アイコンを押すと、ファイルが削除されて画面からアイコンも消える。

こういうアプリを検証するときに

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait

driver = webdriver.Firefox()
driver.implicitly_wait(4)

# 添付済みファイルを削除できることを確認
driver.find_element_by_css_selector('.file-del').click()
# ごみ箱アイコンが画面からなくなっていることを確かめる。
WebDriverWait(driver, 8).until(
    lambda x: not x.find_elements_by_css_selector('.file-del')
)

こんなことをする。

参考リンク・引用

調べたら、こんなブログよりもちゃんと説明しているブログが沢山あった。

Selenium 2で非同期処理を待機する5つの方法 - CODESCRIBBLE

5. implicitlyWait() を設定する

implicitlyWait()で待機時間を設定したDriverは、それ以降全ての要素検索で暗黙的に待機を行います。
非常に簡潔に待機処理を実現できるメソッドではありますが、その反面、要素の検索時にしか利用できないという短所もあります。例えば、要素が非表示になるまで待機したり、ページのタイトルが変更されるまで待機するといった場合は、このメソッドでは対応できません。

Selenium WebDriverのwaitを活用しよう│ソフトウェアテストラボ|アプリテスト|スマートフォンテスト|株式会社シフト

明示的な待機(Explicit Wait)

明示的な待機はテストケース内の個別の箇所に対して好きな条件で待機を指定する機能です。この機能を使う場面はおおまかに二種類に分かれます。
 1. 「要素が現れる」以外の条件で待機したい場合
 2. 待機時間を個別に設定したい場合