前言

在 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(要调用的 方法, 超时时返回的信息)