(一) 前言
突然的资源受限或网络延迟, 可能导致找不到目标元素, 这时测试报告会显示测试失败这时需要一种延时机制, 来使脚本的运行速度与程序的响应速度相匹配, webDriver 为这种情况提供了隐式等待和显式等待两种机制
(二) 隐式等待
一旦设置隐式等待时间, 就会作用于这个 WebDriver 实例的整个生命周期 (对所有的元素查找都生效), 设置隐式等待时间后, Webdriver 会在一定时间内持续检测和搜寻 DOM, 以便于查找一个或多个不是立即加载成功并可用的元素隐式等待的默认时间是 0. WebDriver 使用 implicitly_wait() 来设置等待时间, 单位秒超过等待时间还没找到, 就报 NoSuchElementException 异常
- # 设置超时时间为 10 秒
- driver.implicitly_wait(10)
(三) 显式等待
WebDriver 提供了 WebDriverWait 类和 expected_conditions 模块来实现显式等待相比隐式等待, 显示等待更加智能显示等待就是设置一个前置条件, 在等待时间内, 每隔一段时间检查一次前置条件是否满足, 满足则执行下一步, 超时则报 TimeoutException 异常
(四) WebDriverWait 类
WebDriverWait(driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None)
driver: 浏览器驱动实例
timeout: 等待时间, 单位秒
poll_frequency: 每隔多长时间检查一次, 默认 0.5 秒
ignored_exceptions: 忽略的异常, 默认只有 NoSuchElementException
until 方法 和 until_not 方法:
until(method, message=):method 指要执行的方法(等待时间内每隔一段时间, 执行一次), 直到返回值为 true, 超时则报 TimeoutException 异常, message 将传入异常(message 参数可不填)
until_not(method, message=): 直到返回值为 false, 其他和 until 相同
(五) expected_conditions 模块
expected_conditions 模块提供了多种定义好的前置条件, 需要配合 WebDriverWait 使用
预期等待条件(前置条件) | 简单说明 |
element_to_be_clickable(locator) 参数:locator,指一组(By,locator) 例如:WebDriverWait(driver,10).until(expected_conditions.element_to_be_clickable((By.NAME,‘11‘))) 下面的都是以这种方式,只是前置条件不同,传的参数也可能不同 WebDriverWait(driver,10).until() | 等待查找的元素可见并且可用,以便可以点击,返回定位到的元素 |
element_to_be_selected(locator) | 等待直到元素被选中 |
invisibility_of_element_located(locator) | 等待一个元素在 DOM 中不可见 或不存在 |
presence_of_all_elements_located(locator) | 等待至少有一个定位器查找的元素出现在网页中,返回一组元素 |
presence_of_element_located(locator) | 等待定位器查找的元素出现在网页中,或者可以在 DOM 中找到,返回一个被定位到的元素 |
text_to_be_present_in_element(locator,text) 参数:text,指定的文本 | 等待元素能被定位,并且带有指定的文本信息 |
title_contains(title) 参数:title,指要校验标题包含的字符串 | 等待网页标题包含指定的字符串,成功时返回 True,否则返回 false |
title_is(title) 参数:title,指要校验的标题 | 等待网页标题与预期一致,成功时返回 True,否则返回 false |
visibility_of(element) 参数:element,指一个元素 | 等待元素出现在 DOM 中,是可见的,并且宽和高都大于 0,变为可见的,将返回一个元素(同一个) |
visibility_of_element_located(locator) | 等待元素出现在 DOM 中,是可见的,并且宽和高都大于 0,变为可见的,将返回一个元素 |
alert_is_present() | 判断是否存在警告窗口 |
(六) expected_conditions 示例
下面的代码, try: 部分, 每一部分都是独立可用的 (我只是验证不同前置条件的用法后就注释掉) 另外这里只对方法的使用方式 (方法的功能) 进行说明, 不对使用场景进行说明(比如有没有必要这么做什么的)
- from selenium import webdriver
- from selenium.webdriver.support.ui import WebDriverWait
- from selenium.webdriver.support import expected_conditions
- from selenium.webdriver.common.by import By
- driver = webdriver.Firefox()
- driver.maximize_window()
- driver.get(https://www.cnblogs.com/)
- # try:
- # #等待博客园首页的找找看按钮可见并可用
- # search_btn = WebDriverWait(driver,10).until(expected_conditions.element_to_be_clickable((By.CLASS_NAME,search_btn)))
- # print(search_btn.get_attribute(value))
- # try:
- # login_area = driver.find_element_by_CSS_selector(#login_area)
- # login = login_area.find_element_by_link_text(登录)
- # login.click()
- # remember_me = driver.find_element_by_id(remember_me)
- # remember_me.click()
- # #等待直到登录页面的复选框被选中
- # WebDriverWait(driver, 10).until(expected_conditions.element_located_to_be_selected((By.ID, remember_me)))
- # try:
- # search_file = driver.find_element_by_id(zzk_q)
- # search_btn = driver.find_element_by_class_name(search_btn)
- # search_file.send_keys(python)
- # search_btn.click()
- # #网页标题是否包含 python
- # WebDriverWait(driver, 10).until(expected_conditions.title_contains(python))
- try:
- search_file = driver.find_element_by_id(zzk_q)
- #检查元素是否出现在 DOM 中, 是可见的, 并且宽和高都大于 0
- search_file = WebDriverWait(driver,10).until(expected_conditions.visibility_of(search_file))
- print(search_file)
- finally:
- driver.quit()
(七) 示例(自定义前置条件)
expected_conditions 类提供了多种定义好的前置条件(预期等待条件), 没有前置条件符合时, 也可以通过 WebDriverWait 自定义前置条件
下面这个是 WebDriverWait 类自带的部分注释
- class WebDriverWait(object):
- def __init__(self, driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None):
- """
- Example:
- from selenium.webdriver.support.ui import WebDriverWait \n
- element = WebDriverWait(driver, 10).until(lambda x: x.find_element_by_id("someId")) \n
- is_disappeared = WebDriverWait(driver, 30, 1, (ElementNotVisibleException)).\ \n
- until_not(lambda x: x.find_element_by_id("someId").is_displayed())
- """
示例:(等待博客园个人主页 (点击首页的园子跳转到的页面) 的下拉菜单有 5 个可选项)
- #lambda 表达式其实就是一个匿名函数, 冒号左边的可以理解为函数名及参数, 右边的可以理解为函数的返回值, 具体可以百度 python lambda
- from selenium import webdriver
- from selenium.webdriver.support.ui import WebDriverWait
- from selenium.webdriver.support.ui import Select
- profile = webdriver.FirefoxProfile (rC:\Users\quanhua\AppData\Roaming\Mozilla\Firefox\Profiles\tnwjkr4m.selenium)
- driver = webdriver.Firefox(profile)
- driver.maximize_window()
- driver.get(https://home.cnblogs.com/)
- try:
- #等待 博客园个人主页中的下拉菜单有 5 个可选项
- WebDriverWait(driver,10).until(lambda l:len(Select(l.find_element_by_id(sel_application)).options) == 5)
- finally:
- driver.quit()
(八) 总结
应用元素等待机制, 对于构建高度稳定可靠的测试是必不可少的在使用过程中, 应该尽量避免隐式等待和显示等待混合使用至于隐式等待和显示等待的优缺点, 看书上和网上一般是比较推荐使用显示等待, 不过我自己试了下, 暂时是没看出在运行速度方面有多大区别(可能等以后有比较丰富的项目经验后, 再回头来说说隐式等待和显示等待的优缺点)
来源: http://www.bubuko.com/infodetail-2503634.html