前言
在 UI 自动化测试中,必然会遇到环境不稳定,网络慢的情况,这时如果不做任何处理的话,代码会由于没有找到元素而报错。还有一种情况就是页面使用 ajax 异步加载机制。这时我们就要用到等待,而在 Selenium 中,可以用到三种等待方式,每一种等待都有自己的优点和缺点。
三种等待方式
time.sleep 固定等待
在开发自动化脚本过程中,不要使用固定等待方式,虽然可以自定义等待时间,但当网络条件良好时,依旧会按照预设的时间继续等待,导致整个项目的自动化时间延长。
固定等待不能用于实际自动化项目中,只适用于脚本调试。
from selenium import webdriver
import time
driver = webdriver.Chrome()
# 打开百度
driver.get("http://www.baidu.com")
driver.find_element_by_id("kw").send_keys("selenium")
# 等待 3 秒才执行下一步
time.sleep(3)
driver.find_element_by_id("su").click()
driver.quit()
implicitly 隐式等待
隐式等待实际是设置了一个最长等待时间,如果在规定时间内页面加载完成,则执行下一步,否则一直等到时间结束,然后执行下一步。隐式等待会有一个坑,Javascript 一般都是放在 body 的最后进行加载,实际页面上的元素都已经加载完毕,我们却还在等待全部页面加载结束。
隐式等待对整个 driver 周期都起作用,在最开始设置一次就可以了。
from selenium import webdriver
driver = webdriver.Chrome()
# 打开百度
driver.get("http://www.baidu.com")
driver.find_element_by_id("kw").send_keys("selenium")
# 等待 3 秒才执行下一步
driver.implicitly_wait(3)
driver.find_element_by_id("su").click()
driver.quit()
WebDriverWait 显式等待
显式等待就是判断某个元素是不是已经出现了,可以根据需要定位的元素来设置显式等待,无需等待页面完全加载。是最常用的等待方式。
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
# 打开百度
driver.get("http://www.baidu.com")
# 显式等待
wait = WebDriverWait(driver, 3, 1)
# 设置等待条件:判断 title 是否出现
wait.until(EC.title_is("百度一下,你就知道"))
driver.find_element_by_id("kw").send_keys("selenium")
driver.find_element_by_id("su").click()
driver.quit()
WebDriverWait 源码
class WebDriverWait(object):
def __init__(self, driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None):
self._driver = driver
self._timeout = timeout
self._poll = poll_frequency
# avoid the divide by zero
if self._poll == 0:
self._poll = POLL_FREQUENCY
exceptions = list(IGNORED_EXCEPTIONS)
if ignored_exceptions is not None:
try:
exceptions.extend(iter(ignored_exceptions))
except TypeError: # ignored_exceptions is not iterable
exceptions.append(ignored_exceptions)
self._ignored_exceptions = tuple(exceptions)
WebDriverWait 参数:
- driver:传入 WebDriver 实例
- timeout:超时时间
- poll_frequency:调用 until 或 until_not 中的方法的间隔时间,默认为 0.5 秒
- ignored_exceptions:忽略的异常
整个 WebDriverWait 模块只有两种方法,until 和 until_not。
until(self, method, message=''):
- method:在等待期间,每隔一段时间调用这个传入的方法,直到返回值不是 False
- message:如果超时,抛出 TimeoutException,将 message 传入异常
until_not(self, method, message=''):
- method:在等待期间,每隔一段时间调用这个传入的方法,直到返回值是 False
- message:如果超时,抛出 TimeoutException,将 message 传入异常
expected_conditions 是 selenium 中的一个模块,包含一系列用于判断的条件类。
简单来说显式等待就是 WebDriverWait(driver实例, 超时时长, 调用频率, 忽略的异常).until(要调用的 方法, 超时时返回的信息)