Selenium 等待方式详解

一、为什么要使用等待?

在自动化测试脚本的运行过程中,webdriver操作浏览器的时候,对于元素的定位是有一定的超时

时间,大致在1-3秒

如果这个时间内仍然定位不到元素,就会抛出异常,中止脚本执行

我们可以通过在脚本中设置等待的方式来避免由于网络延迟或浏览器卡顿导致的偶然失败

二、常用的三种等待方式

  • 强制等待
  • 隐式等待
  • 显示等待

三、隐式等待

  • 隐式等待是一种全局性的等待方式,在整个测试期间都有效。
  • 设置隐式等待后,Selenium将在查找元素时等待一定的时间,如果元素没有立即出现,则继续等待一段时间。
  • 隐式等待的超时时间可以通过 driver.implicitly_wait() 方法设置。
  • 如果在隐式等待超时时间之内找到了元素,则会立即执行下一步操作;否则,将抛出 NoSuchElementException 异常。
  • 与强制等待相比,隐式等待更加智能,可以根据页面加载情况和元素出现时间自动调整等待时间。

注意:

  • 隐式等待只对 find_element()find_elements() 方法有效;
  • 在使用显式等待时,隐式等待会被覆盖掉。

隐式等待的缺点:

  1. 隐式等待只对 find_element()find_elements() 方法有效,其他方法不受影响,因此可能会导致一些操作失败。
  2. 如果设置的隐式等待时间过长,会增加测试执行的总时间,从而降低测试效率。
  3. 在高并发环境下,多个线程使用同一个驱动器对象时,隐式等待可能会相互干扰,从而导致测试失败。

隐式等待的使用场景:

虽然隐式等待也有一些缺点,但它仍然是Selenium中比较常用的等待方式之一。以下是一些可能需要使用隐式等待的场景:

  1. 在测试过程中,页面元素的加载时间比较稳定,且需要等待的时间比较长时,可以使用隐式等待来避免重复编写等待代码;
  2. 当需要查找的元素在不同的测试用例中都需要使用时,可以将隐式等待放到 setUp() 方法中,这样所有的测试用例都可以共享隐式等待的设置;
  3. 在进行基本的功能验证时,可以使用隐式等待来保证元素可见性,以确保测试结果的正确性。

示例

# 导入selenium库中的webdriver模块
from selenium import webdriver

# 导入By类,用于定位元素
from selenium.webdriver.common.by import By

# 创建一个Chrome浏览器对象
browser = webdriver.Chrome()

# 设置隐式等待时间为10秒
browser.implicitly_wait(10)

# 访问百度首页
browser.get('https://www.baidu.com/')

# 使用CSS选择器定位搜索框元素
search_box = browser.find_element(By.CSS_SELECTOR, '#kw')

# 在搜索框输入关键词
search_box.send_keys('隐式等待')

# 使用CSS选择器定位搜索按钮元素
search_button = browser.find_element(By.CSS_SELECTOR, '#su')

# 点击搜索按钮
search_button.click()

# 打印搜索结果页标题
print(browser.title)

# 关闭浏览器
browser.quit()


四、显式等待

  • 显示等待:设置一个等待时间和一个条件,在规定时间内,每隔一段时间查看下条件是否成立,如果成立那么程序就继续执行,否则就提示一个超时异常(TimeoutException)。
  • 通常情况下WebDriverWait类会结合ExpectedCondition类一起使用。
需要引入包:
from selenium.webdriver.support.wait 
import WebDriverWait
参数 描述
driver WebDriver实例,用于等待。
timeout 最长等待时间,超时将抛出TimeoutException异常。
poll_frequency 调用until或until_not中的方法之前的休眠秒数,默认为500毫秒。
ignored_exceptions 忽略某些异常并不抛出异常。
message 超时异常描述信息。

WebDriverWait参数说明:

WebDriverWait(driver, timeout=3).until(some_condition)

WebDriverWait(driver, timeout=3).until(some_condition) 是一个使用Selenium中的显式等待实现的代码片段。它的作用是等待某个特定条件在指定时间内满足,一旦满足了条件,则继续执行后续代码。

这个语句的具体含义是:

  • WebDriverWait(driver, timeout=3) 创建一个WebDriverWait对象,将传递给它的driver参数作为被等待的WebDriver实例,并设置最长等待时间为3秒钟。
  • .until(some_condition) 调用until()方法并传递一个特定的条件some_condition。该方法将等待直到条件满足或超时时间达到。

例如,以下代码使用显式等待来等待页面标题包含“CSDN”文本,并且最长等待时间为5秒钟:

# 导入selenium模块中的webdriver模块,用于实例化浏览器对象并控制浏览器的操作
from selenium import webdriver

# 导入selenium模块中的WebDriverWait类,用于等待特定条件出现后再执行下一步操作
from selenium.webdriver.support.ui import WebDriverWait

# 导入selenium模块中的expected_conditions模块的EC别名,用于定义预期条件
from selenium.webdriver.support import expected_conditions as EC


# 创建WebDriver实例
driver = webdriver.Chrome()

# 导航到网页
driver.get("https://www.csdn.net")

# 等待页面标题包含"CSDN"
wait = WebDriverWait(driver, 5)
title_contains_csdn = EC.title_contains("CSDN")
wait.until(title_contains_csdn)

# 输出页面标题
print(driver.title)

# 关闭浏览器
driver.quit()

在上面的示例中,我们创建了一个WebDriver实例,并使用显式等待来等待页面标题包含“CSDN”文本。 如果满足条件,则打印页面标题。 否则,将抛出TimeoutException异常。

两种方法:untilutil_not

方法名 描述 参数
until() 等待直到条件为真。 - method: 一个预期条件,可以是一个内置条件或自定义条件对象。
- message (可选): 超时时要显示的错误消息。
until_not() 等待直到条件不再为真。 - method: 一个预期条件,可以是一个内置条件或自定义条件对象。
- message (可选): 超时时要显示的错误消息。

这两种方法都接受一个预期条件作为参数,并等待最长时间,直到该条件成立或者超时。其中,until()方法等待条件为真,而until_not()方法则等待条件为假。如果超时,则抛出TimeoutException异常,否则返回一个值。

这里是一个使用until()方法的例子,它等待页面标题包含特定文本:

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# 创建WebDriver实例,并指定使用Chrome浏览器驱动
driver = webdriver.Chrome()

# 导航到菜鸟教程网页
driver.get("https://www.runoob.com/")

# 显式等待直到页面标题包含“菜鸟教程”
wait = WebDriverWait(driver, 10)
title_contains_runoob = EC.title_contains("菜鸟教程")
title = wait.until(title_contains_runoob)

# 输出页面标题
print(title)

# 关闭浏览器
driver.quit()

这里是一个使用until_not()方法的例子,它等待文本框中的值被清除:

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# 创建WebDriver实例,并指定使用Chrome浏览器驱动
driver = webdriver.Chrome()

# 导航到百度网页
driver.get("https://www.baidu.com")

# 获取文本框元素并输入文本
input_elem = driver.find_element("css selector", "input[name='wd']")
input_elem.send_keys("python")

# 显式等待直到文本框中的值被清除
wait = WebDriverWait(driver, 10)
value_cleared = EC.text_to_be_present_in_element_value(("css selector", "input[name='wd']"), "")
input_elem.clear()
wait.until_not(value_cleared)

# 关闭浏览器
driver.quit()

在上面的示例中,我们使用显式等待等待文本框中的值被清除。 until_not()方法等待文本框的文本值为空,并继续执行后续代码。 如果超时,则抛出TimeoutException异常。

显式等待的缺点与使用场景

显式等待是一种在测试自动化中常用的等待方式,它可以让脚本在执行过程中等待某个特定条件变为真时再继续执行。显式等待适用于需要等待某些特定条件才能继续执行测试的情况,例如等待页面元素加载完成、等待异步操作完成等。

显式等待的主要缺点

  1. 容易出现异常:如果设置的超时时间太短或者条件不正确,就有可能导致脚本抛出异常而终止执行。
  2. 可读性较差:显式等待往往需要编写复杂的代码来处理,这样容易导致代码可读性较差。
  3. 对测试环境有依赖性:显式等待往往需要依赖网络状态、服务器响应速度等因素,这些因素可能会影响测试结果。

使用场景

  1. 等待页面元素加载完成:当页面需要加载一些异步资源(如图片、视频等)时,我们可能需要使用显式等待等待页面元素加载完成后再进行下一步操作。
  2. 等待异步操作完成:在执行一些需要耗费时间的异步操作时,例如上传文件、发送请求等,我们可能需要使用显式等待等待操作完成后再进行下一步操作。
  3. 等待某些特定条件:有些测试场景需要等待某些特定条件才能继续执行测试,例如等待某个元素出现、等待某个值被更新等。这时我们可以使用显式等待来实现等待条件变为真后再继续执行测试。

五、强制等待

强制等待是一种不建议使用的等待方式。它使用 time.sleep() 方法在代码中强制让程序等待固定的时间,而不管网页是否已经加载完成或元素是否已经出现。

强制等待的缺点

尽管强制等待是一种简单的等待方式,但它也存在一些缺点:

  1. 时间浪费:强制等待会浪费时间。如果设置的等待时间过长,测试效率会降低;而如果等待时间过短,则有可能无法保证页面或元素已经加载完成,从而导致测试失败。
  2. 依赖于网络环境:网络环境的不稳定性会导致页面加载时间的变化。如果使用固定的强制等待时间,就无法适应各种网络环境的差异。
  3. 不灵活:强制等待是一种静态等待方式,无法根据实际情况动态调整等待时间。

强制等待的使用场景

虽然不建议频繁使用强制等待,但在一些特定情况下仍然需要考虑使用它。以下是一些可能需要使用强制等待的场景:

  1. 页面加载时间较长且不稳定:当页面或元素的加载时间比较长且不稳定时,可以使用固定时间的强制等待来确保元素加载完毕。但请注意,这种方式不是最佳实践,应尽量优化页面加载速度和稳定性。
  2. 其他等待方式无法满足需求:当其他等待方式无法满足需求时,可以考虑使用强制等待来等待某些操作的完成。但请确保在没有更好的替代方案时再采用这种方式。
  3. 调试代码:在调试代码时,可以使用强制等待来暂停程序执行,以便观察程序执行状态和结果。这对于定位问题和调试脚本非常有用。

虽然强制等待在特定的场景下可能是必要的,但请尽量避免过度使用它,并在可能的情况下选择更灵活和准确的等待方式,例如显式等待或条件等待。

虽然强制等待有其局限性,但它在特定场景下仍然是一种有效的等待方式。为了更好地管理强制等待,我们可以考虑以下几点:

  • 设置合理的等待时间:要根据实际情况来设置合理的等待时间,避免过长或过短的等待时间。
  • 结合其他等待方式:如果可能,应该尝试使用其他等待方式,如显式等待、隐式等待或条件等待,以提高测试效率和可靠性。
  • 尽量避免使用:在大多数情况下,我们应该尽量避免使用强制等待,而选择更加智能和可靠的等待方式。

强制等待的方法

方法 描述
time.sleep() 使用 Python 的 time 模块中的 sleep() 方法来实现强制等待。可以指定等待的时间(以秒为单位)。

示例

import time   # 导入time模块,用于等待

from selenium import webdriver  # 导入selenium库的webdriver模块,用于操作浏览器

# 创建Chrome浏览器的实例
driver = webdriver.Chrome()

# 访问CSDN网页
driver.get("https://www.csdn.net/")

# 强制等待5秒
time.sleep(5)

猜你喜欢

转载自blog.csdn.net/m0_67268191/article/details/132171564