WebDriver API剖析----等待时间

当UI自动化页面元素不存在时,常见的发生异常的原因有如下几点:

  • 页面加载时间过慢,需要查找的元素代码已经执行完成,但是页面还未加载成功,从而发生异常;
  • 查到的元素没有在当前的iframe或者frame中,此时需要切换至对应的iframe或者frame中;
  • 代码中对元素的描述错误。

在selenium中,提供的3种常见的等待时间的方式各有有点和缺点,当熟练掌握这些方式后,可以尝试针对不同的情况选择最优的等待方式。

1、强制等待

强制等待时设置等待的最简单的方法,如sleep(3),在之前的案例经常看到。sleep()缺点时不够智能,若设置的时间太短,元素没有加载出来,照样报错;若设置的时间太长,又会浪费时间。不要忽视每次几秒的时间,用例多了,代码量就大了,多几秒就会影响脚本的整体运行速度。

import time
from selenium import webdriver

driver = webdriver.Firefox()
driver.maximize_window()
driver.get("https://www.baidu.com")

driver.maximize_window()
time.sleep(3)
driver.quit()

2、隐式等待

 隐式等待的好处时不用 像sleep()函数那样强制等待指定的时间,而实通过使用implicitly_wait()方法设定等待时间,单位为秒。当页面的全部元素都展现出来后,才会只能怪后续语句。隐式等待也有缺点,隐式等待时设置了一个最长等待时间(implicitly_wait(10),最长等待时间等于10s),若在规定时间内网页很快加载完成,则执行下一步,否则一直等到时间截止,才执行下一步;如果在设定的等待时间依然找不到元素,则抛出异常。

如果页面上有较多的异步刷新和操作,很多页面元素都是动态出现的,很多操作步骤都需要等待,用隐式等待利大于弊。但在其他时间,仍然不建议使用隐式等待。

from time import sleep, ctime
from selenium.common.exceptions import NoSuchElementException
from selenium import webdriver

driver = webdriver.Firefox()
driver.implicitly_wait(10)
driver.get("https://cn.bing.com/")
try:
    print(ctime())
    # 情况1:正确的搜索框元素定义id='sb_form_q;运行情况1需要注释情况2
#   driver.find_element_by_xpath("//*[@id='sb_form_q']").send_keys("selenium")
    # 情况2:将输入的id改为id='sb_form_qq,看看时间是否等待了10s后,才抛出异常;运行情况2需要把情况1注释
    driver.find_element_by_xpath("//*[@id='sb_form_qq']").send_keys("selenium")
    driver.find_element_by_xpath("//*[@id='sb_form_go']").click()
except NoSuchElementException as e:
    print(e)
finally:
    print(ctime())  # 输出第一个时间,观察间隔时间
    driver.quit()

2.1、情况1结果

由于搜索页面整体加载速度很快,搜索框元素代码中定义正确,所以代码运行很快结束,可以看到输出的两个时间几乎一致。

9ca5c0d20b7e4ad1bb0e53f1a1436fd1.png

2.2、情况2结束分析

搜索框元素的id属性改成了sb_form_qq,而Bing搜索页上并不存在该元素,代码运行时肯定会报错。

运行代码时,检测到元素的时间implicitly_wait(10)中的等待时间10s后抛出异常,并且两次输出的时间也间隔了10s。

224f72b0e11b462bb63adf76fa075799.png

 

注:隐式等待对整个Driver的周期都会起作用,只需要设置一次即可,就是在整个程序代码中的最前面设置一次即可。

3、显示等待

显示等待时一种相对智能的等待机制。执行原理是:程序每隔一定时间检测条件是否成立,若条件成立,则执行下一步;否则继续等待,直到超过设置的最大等待时间,然后抛出异常。显示等待也是我们比较推荐使用的方法。

使用显示等待需要用到from selenium.webdriver.support.wait 库中的对象 WebDriverWait。

from selenium.webdriver.support.wait import WebDriverWait

用百度举例一下,在输入框输入【测试】并点击【百度一下】按钮,代码如下:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Firefox()
driver.implicitly_wait(10)
driver.get("https://www.baidu.com/")
ele = WebDriverWait(driver, 10, 0.2).until(EC.visibility_of_element_located((By.ID, 'kw')))
if ele is not None:      # 如果成功捕获对象
    print(type(ele))    # 打印对象类型
    ele.send_keys("测试")
driver.find_element_by_xpath("//*[@id='su']").click()
driver.quit()

运行结果:

f6f50ef54aab471db3b267bf9f74b137.png

下面来一段没有发现指定的页面元素而引起超时的代码。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Firefox()
driver.implicitly_wait(10)
driver.get("https://www.baidu.com/")
ele = WebDriverWait(driver, 10, 0.2).until(EC.visibility_of_element_located((By.ID, 'kww')), '没发现输入搜索文本框')
if ele is not None:      # 如果成功捕获对象
    print(type(ele))    # 打印对象类型
    ele.send_keys("测试")
driver.find_element_by_xpath("//*[@id='su']").click()
driver.quit()

在上面的脚本中,我们故意设定 不存在的名为kww的元素,因此在等待了10s后,发现还是定位不到该元素,于是抛出超时异常,对应的异常消息就是“没发现输入搜索文本框” ,运行结果如下图:

f915017de2c64a5ba57b62153e7ceffd.png

 WebDriverWait方法中的参数说明如下:

  • driver:传入webdriver实例,即代码中的driver。
  • timeout:超时时间,即等待的最长时间(同时要考虑隐式等待时间)。
  • pll_frequency:调用until或until_not中的方法的间隔时间,默认是0.5s。
  • ignored_exceptions:忽略的异常。若在调用until或until_not的过程中抛出这个元组中的异常,则不中断代码,继续等待;若抛出的是这个元组外的异常,则终端代码,抛出异常。默认只有NoSuchElementException。

 WebDriverWait需要与until()或until_not()方法结合使用。例如:

WebDriverWait(driver, 10, 0.2).until(method, message = "")

调用该方法提供的驱动程序作为参数,直接返回值为True。

  • method:在等待期间,每隔一段时间调用这个传入的方法,直接返回值不是False。
  • message:如果超时,抛出Timeout Exception,将message传入异常。例如:
WebDriverWait(driver, 10, 0.2).until_not(method, message = "")

调用该方法提供的驱动程序作为参数,直到返回值为False。

  • until_not与until相反,until是当某元素或某个条件成立则继续执行,until_not是当某个元素消失或某个条件不成立则继续执行,两者参数一样。 

expectd_conditions是Selenium的一个模块,其中包含一系列用于判断的条件。

Selenium中预定义的条件等待函数
类别函数名称参数功能
判断元素的可见性visibility_of_element_locatedlocater(目标元素定位)根据定位判断目标元素是否已显示,如果已显示,则返回该WebElement对象
visibility_ofwebElement(目标元素)判断目标是否已显示,如果已显示,则返回该WebElement对象
visibility_of_all_element_locatedlocater(目标元素定位)根据定位判断页面上是否存在一个或多个符合定位的元素,且是否已全部显示,如果是,则返回该WebElement集合
visibility_of_any_element_locatedlocater(目标元素定位)根据定位判断页面上是否存在一个或多个符合定位的元素,这些元素是都至少有一个已显示,如果是,则返回其中已显示的WebElement集合
invisibility_of_element_locatedlocater(目标元素定位)根据定位判断目元素是否未显示
invisibility_of_elementwebElement(目标元素)判断目标元素是否未显示
判断元素的状态、文本、值element_to_be_clickablelocater(目标元素定位)根据定位判断目标元素是否处于可单击状态(已显示且未被禁用)
element_located_to_be_selectedlocater(目标元素定位)根据定位判断目标元素是否处于已选中状态
element_to_be_selectedwebElement(目标元素)判断目标元素是否处于已选中状态
element_located_selection_state_to_belocater(目标元素定位),is_selected(期望的状态),可以传入True(选中)或是Flase(未选中)根据定位判断目标元素的选中状态是否符合预期
element_selection_state_to_bewebElement(目标元素),is_selected(期望的状态),可以传入True(选中)或是Flase(未选中)判断目标元素的选中状态是否符合预期
text_to_be_present_in_elementlocater(目标元素定位),text(期望包含的文本)判断目标元素的文本是否已包含期望的文本
text_to_be_present_in_element_valuelocater(目标元素定位),text(期望包含的文本)判断目标元素的Value属性是否已包含期望的文本
判断元素是否存在presence_of_element_locatedlocater(目标元素定位)根据定位判断页面上是都存在某个符合定位的元素,如果有(但未必可见),则返回WebElement
presence_of_all_element_locatedlocater(目标元素定位)根据定位判断页面上是否存在一个或多个符合定位的元素,如果有(但未必可见),则返回WebElement集合
staleness_ofwebElement(目标元素)判断目标元素是否已经从DOM结构上完全消失
判断浏览器窗口、弹窗及内嵌网页new_window_is_openedcurrent_handles(当前窗口句柄集合)判断是否有新窗口打开,句柄数量是否会在当前句柄集合的基础上有所增加
number_of_windows_to_benum_windows(预期窗口数量)判断当前窗口数量是否等于预期窗口数量
frame_to_be_available_and_switch_to_itlocater(目标元素(IFrame/Frame)定位)根据定位判断答复可以切换到目标元素,如果可以切换,则会直接切换到指定元素IFrame/Frame上
alert_is_present 判断是否已出现浏览器弹出框
判断网页标题或URLtitle_containstitle(期望包含的标题)判断网页标题是否已包含期望的标题(即是否模糊判断)
title_istitle(期望包含的标题)判断网页标题是否完全等于期望的标题(即是否完全匹配)
url_changesurl(当前的URL)判断URL是否发生变化,即与当前的URL不相同
url_contains     url(期望包含的URL)判断URL是否已包含期望的URL(即是否完全匹配)
url_matchespattern(格式表达式)判断URL是都匹配格式表达式(例如正则表达式)
url_to_beurl(期望相等的URL)判断URL是否已包含期望的URL(即是否完全匹配)

 合理使用这些函数,可以达到事半功倍的效果。

 

 

 

 

 

  • 14
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值