• 提升 Selenium 测试稳定性的秘诀:深入理解等待 API 的使用


    目录

    1. 为什么需要等待
    2. Selenium 等待 API 简介
    3. 隐式等待
    4. 显式等待
    5. Fluent Wait
    6. 等待策略的选择
    7. 示例代码
    8. 总结

    正文

    1. 为什么需要等待

    在 Web 自动化测试中,等待是一个关键因素。网络应用通常是动态的,页面加载时间、元素的显示时间都可能不同步。直接操作这些元素可能会导致 NoSuchElementException 或者 ElementNotVisibleException 等错误。因此,等待机制可以帮助我们确保元素加载完成后再进行操作,从而提高测试的稳定性和可靠性。

    2. Selenium 等待 API 简介

    Selenium 提供了三种主要的等待机制:

    • 隐式等待 (Implicit Wait)
    • 显式等待 (Explicit Wait)
    • Fluent Wait

    3. 隐式等待

    隐式等待是全局设置的一种等待方式,它会在查找元素时等待一定的时间,默认时间为 0 秒。

    from selenium import webdriver
    
    driver = webdriver.Chrome()
    driver.implicitly_wait(10)  # 设置隐式等待时间为 10 秒
    driver.get("http://www.example.com")
    
    element = driver.find_element_by_id("element_id")
    

    当元素未立即可见时,WebDriver 将会每隔一段时间检查一次,直到达到指定的等待时间。如果在规定时间内找到了元素,将立即返回,否则抛出 NoSuchElementException

    4. 显式等待

    显式等待是针对特定元素的等待,它在等待条件满足前会定期检查元素的状态。

    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    
    driver = webdriver.Chrome()
    driver.get("http://www.example.com")
    
    try:
        element = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.ID, "element_id"))
        )
    finally:
        driver.quit()
    

    WebDriverWait 结合 expected_conditions 模块可以灵活地等待元素的不同状态,如元素的可见性、元素的可点击性等。
    expected_conditions 是 Selenium 提供的一组条件类,用于显式等待。这些条件可以用来判断特定元素或页面状态,以决定是否继续执行后续的操作。以下是一些常用的 expected_conditions 及其示例说明:

    常用的 expected_conditions
    1. title_is
    2. title_contains
    3. presence_of_element_located
    4. visibility_of_element_located
    5. visibility_of
    6. presence_of_all_elements_located
    7. text_to_be_present_in_element
    8. text_to_be_present_in_element_value
    9. frame_to_be_available_and_switch_to_it
    10. invisibility_of_element_located
    11. element_to_be_clickable
    12. staleness_of
    13. element_to_be_selected
    14. element_located_to_be_selected
    15. alert_is_present
    示例说明
    1. title_is

    等待页面标题等于指定值。

    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    
    WebDriverWait(driver, 10).until(EC.title_is("Expected Title"))
    
    2. title_contains

    等待页面标题包含指定文本。

    WebDriverWait(driver, 10).until(EC.title_contains("Partial Title"))
    
    3. presence_of_element_located

    等待元素出现在页面上。

    from selenium.webdriver.common.by import By
    
    element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.ID, "element_id"))
    )
    
    4. visibility_of_element_located

    等待元素可见。

    element = WebDriverWait(driver, 10).until(
        EC.visibility_of_element_located((By.ID, "element_id"))
    )
    
    5. visibility_of

    等待一个已知元素对象可见。

    element = driver.find_element_by_id("element_id")
    WebDriverWait(driver, 10).until(EC.visibility_of(element))
    
    6. presence_of_all_elements_located

    等待一组元素全部出现在页面上。

    elements = WebDriverWait(driver, 10).until(
        EC.presence_of_all_elements_located((By.CLASS_NAME, "class_name"))
    )
    
    7. text_to_be_present_in_element

    等待元素中包含指定文本。

    WebDriverWait(driver, 10).until(
        EC.text_to_be_present_in_element((By.ID, "element_id"), "Expected Text")
    )
    
    8. text_to_be_present_in_element_value

    等待元素的值包含指定文本。

    WebDriverWait(driver, 10).until(
        EC.text_to_be_present_in_element_value((By.ID, "input_id"), "Expected Value")
    )
    
    9. frame_to_be_available_and_switch_to_it

    等待 iframe 可用并切换到该 frame。

    WebDriverWait(driver, 10).until(
        EC.frame_to_be_available_and_switch_to_it((By.NAME, "frame_name"))
    )
    
    10. invisibility_of_element_located

    等待元素不可见。

    WebDriverWait(driver, 10).until(
        EC.invisibility_of_element_located((By.ID, "element_id"))
    )
    
    11. element_to_be_clickable

    等待元素可点击。

    element = WebDriverWait(driver, 10).until(
        EC.element_to_be_clickable((By.ID, "clickable_element_id"))
    )
    element.click()
    
    12. staleness_of

    等待元素不再附加在 DOM 树上。

    element = driver.find_element_by_id("stale_element_id")
    WebDriverWait(driver, 10).until(EC.staleness_of(element))
    
    13. element_to_be_selected

    等待元素被选中。

    element = driver.find_element_by_id("select_element_id")
    WebDriverWait(driver, 10).until(EC.element_to_be_selected(element))
    
    14. element_located_to_be_selected

    等待特定定位器的元素被选中。

    WebDriverWait(driver, 10).until(
        EC.element_located_to_be_selected((By.ID, "select_element_id"))
    )
    
    15. alert_is_present

    等待警告框出现。

    WebDriverWait(driver, 10).until(EC.alert_is_present())
    alert = driver.switch_to.alert
    alert.accept()
    

    通过这些 expected_conditions,你可以更加灵活地控制 Selenium 测试的等待逻辑,确保测试脚本在正确的时间点进行操作。

    5. Fluent Wait

    Fluent Wait 是显式等待的一种扩展,它允许我们定义等待的最大时间、轮询的频率以及在等待期间遇到的异常处理。

    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.common.exceptions import TimeoutException
    
    driver = webdriver.Chrome()
    driver.get("http://www.example.com")
    
    wait = WebDriverWait(driver, 10, poll_frequency=1, ignored_exceptions=[TimeoutException])
    element = wait.until(EC.presence_of_element_located((By.ID, "element_id")))
    

    Fluent Wait 通过指定轮询频率,可以更精确地控制等待行为。

    6. 等待策略的选择

    选择合适的等待策略取决于测试的具体需求:

    • 隐式等待 适用于大部分情况下的全局设置,但可能导致调试困难,因为它在所有元素查找时都生效。
    • 显式等待 提供了更精确的控制,适用于需要等待特定条件的场景。
    • Fluent Wait 是显式等待的高级版本,适用于需要自定义轮询频率和异常处理的复杂场景。

    7. 示例代码

    综合使用不同等待机制的示例代码:

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    
    driver = webdriver.Chrome()
    driver.get("http://www.example.com")
    
    # 设置隐式等待
    driver.implicitly_wait(10)
    
    try:
        # 使用显式等待
        element = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.ID, "element_id"))
        )
    
        # 使用 Fluent Wait
        wait = WebDriverWait(driver, 10, poll_frequency=1, ignored_exceptions=[TimeoutException])
        element = wait.until(EC.element_to_be_clickable((By.ID, "clickable_element_id")))
    
        element.click()
    finally:
        driver.quit()
    

    8. 总结

    等待机制在 Selenium 测试中起到了至关重要的作用。通过合理选择和使用隐式等待、显式等待和 Fluent Wait,可以大大提高自动化测试的稳定性和可靠性。希望这篇博客能帮助你更好地理解和应用 Selenium 的等待 API,在实际项目中写出更加健壮的测试用例。


    希望这个博客大纲和详细内容对你有所帮助!如果有任何进一步的问题或需要更多示例,请随时告诉我。

  • 相关阅读:
    设计模式-解释器模式
    Linux学习-61-Linux系统服务管理
    Pico示波器 汽车振动异响(NVH)解决方案
    【汇编】汇编语言基础知识(学习笔记)
    【java学习】构造方法重载(26)
    PyQt5 QSS的UI美化
    大数据ClickHouse(十四):Integration系列表引擎
    Linux安装配置awscli命令行接口工具及其从aws上传下载数据
    【每日一题】做菜顺序
    Python画图系列——折线图
  • 原文地址:https://blog.csdn.net/abments/article/details/140049836