大多数现代web应用都使用了AJAX技术。当浏览器加载一个页面的时候,该页面内的元素可能在不用的时间间隔内进行加载。这使得元素定位变得比较困难:如果一个元素还没有出现在DOM中,定位函数将会抛出一个ElementNotVisibleException
异常。使用waits
等待可以解决这个问题。等待将会给定位一个元素或者对元素进行一些其他的操作提供一个缓冲的时间。
Selenium WebDriver提供了两种类型的等待——显式等待和隐式等待。显式等待会给WebDriver一个确定的条件,如果条件满足的话就进行下一步的处理动作。隐式等待的话,WebDriver在定位一个元素时,会对DOM进行一个确定时长的轮询。
5.1.显式等待
显式等待就是你需要定义一个确定的条件,在这个条件满足之后才进行代码中的后续处理动作。一个极端的样例是使用time.sleep()
,这将会将条件设置为等待一个特定的时间段。有一些简便的方法可以帮助你编写与等待相关的代码。WebDriverWait
结合ExpectedCondition
就是一种很好的处理办法。
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Firefox()
driver.get("http://somedomain/url_that_delays_loading")
try:
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "myDynamicElement"))
)
finally:
driver.quit()
这将会让WebDriver等待十秒,如果十秒内未能定位到目标元素就会抛出一个TimeOut
超时异常。WebDriverWait
默认状态下将会每500毫秒调用一次ExpectedCondition
,直到它成功返回。ExpectedCondition
的成功返回是一个布尔类型值True
。
预期条件
在进行浏览器进行Web自动化测试的时候有一些经常用到的判断条件,下面列出的就是它们每一个的名字。Selenium Python为这些判断条件提供了一些便捷的方法,你不必自己去编写代码实现一个expected_condition
类或者为他们创建你自己的工具包。
- title_is(标题是什么)
- title_contains(标题包含什么)
- presence_of_element_located(要定位的元素是否出现)
- visibility_of_element_located(要定位的元素是否能看到)
- visibility_of(元素是否可视)
- presence_of_all_elements_located(要定位的多个元素是否出现)
- text_to_be_present_in_element()
- text_to_be_present_in_element_value
- frame_to_be_available_and_switch_to_it
- invisibility_of_element_located
- element_to_be_clickable
- staleness_of
- element_to_be_selected
- element_located_to_be_selected
- element_selection_state_to_be
- element_located_selection_state_to_be
- alert_is_present
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 10)
element = wait.until(EC.element_to_be_clickable((By.ID, 'someid')))
expected_condition
(预期条件)模块包含一个WebDriverWait
可以使用的预定义条件集合。
5.2.隐式等待
一个隐式等待告诉WebDriver,当尝试要定位的任意元素不是立即可用的情形下,在确定的时间段内不断的轮训DOM。默认设置是0.一旦设置,隐式等待便在WebDriver 对象的整个生命周期中有效。
from selenium import webdriver
driver = webdriver.Firefox()
driver.implicitly_wait(10) # seconds
driver.get("http://somedomain/url_that_delays_loading")
myDynamicElement = driver.find_element_by_id("myDynamicElement")