Selenium中的显性等待WebDriverWait
前言
在Selenium自动化测试中,显性等待是一项关键技术,它可以解决页面元素加载不稳定、异步加载以及网络延迟等问题。本文将深入研究Selenium中显性等待的深度使用,包括等待条件的种类、使用方式、以及一些实用的技巧。
为什么需要显性等待?
在Web应用程序中,元素不是一开始就存在于DOM中的,有时候需要等待一段时间直到它们出现。显性等待的目的是等待页面元素达到期望的状态,然后再继续执行后续的测试步骤。
显示等待的原理
显示等待(WebDriverWait)配合该类的until()和until_not()方法,就能够根据判断条件而进行灵活地等待了.它主要的意思就是:程序每隔x秒看一眼,如果条件成立了,则执行下一步,否则继续等待,直到超过设置的最长时间,然后抛出TimeoutException异常
显示等待的前提设置
显示等待需要用到两个类:WebDriverWait和expected_conditions两个类
WebDriverWait:指定轮询间隔、超时时间等
expected_conditions:指定了很多条件函数(也可以自定义条件函数)
需要导入:
from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as ec # 用别名的方式,方便应用,简化引用名称
WebDriverWait里面包含了几种参数:
WebDriverWait(driver, timeout=30, poll_frequency=0.5, ignored_exceptions=None)
driver:实例化的浏览器对象
timeout:最长超时时间,默认以秒为单位
poll_frequency:轮询的间隔时间,默认为0.5s
ignored_exceptions:忽略等待时出现的特定类型的异常,默认忽略
显示等待的常用条件设置
显示等待(WebDriverWait)结合expected_conditions提供的方法进行等待的条件设置。
1.until()和until_not()
until():
element = WebDriverWait(driver, 10).until(ec.presence_of_element_located ((By.ID, "my_element_id")))
until_not():
element = WebDriverWait(driver, 10).until_not(ec.presence_of_element_located ((By.ID, "my_element_id")))
2.通过页面标题来判断
title_is():
判断当前页面的title是否完全等于(==)预期字符串,返回布尔值
WebDriverWait(driver,10).until(ec.title_is('titile_element'))
title_contains():
判断当前页面的title是否包含预期字符串,返回布尔值
WebDriverWait(driver, 10).until(ec.title_contains('titile_element'))
3.通过元素是否可见来判断
presence_of_element_located():
判断某个元素是否被加到了dom树里,并不代表该元素一定可见
WebDriverWait(driver, 3).until(ec.presence_of_element_located ((By.ID, "my_element_id")))
visibility_of_element_located():
判断某个元素是否可见. 可见代表元素非隐藏,并且元素的宽和高都不等于0
WebDriverWait(driver, 3).until(ec.visibility_of_element_located ((By.ID, "my_element_id")))
visibility_of():
基本和上面方法效果一致,判断元素将会加载到页面DOM中,并可见
el = WebDriverWait(driver, 3).until(ec.visibility_of(driver.find_element (By.ID, "my_element_id")))
presence_of_all_elements_located():
判断是否至少有1个元素存在于dom树中。
WebDriverWait(driver, 3).until(ec.presence_of_all_elements_located((By.ID, "my_element_id")))
visibility_of_any_elements_located():
判断是否至少有1个元素存在于dom树中,并且可见。
WebDriverWait(driver, 3).until(ec.visibility_of_any_elements_located((By.ID, "my_element_id")))
invisibility_of_element_located():
判断某个元素中是否不存在于dom树或不可见
WebDriverWait(driver, 3).until \ (ec.invisibility_of_element_located((By.ID, "my_element_id"))
4.通过等待的元素包含的内容来判断
text_to_be_present_in_element():
判断某个元素中的text是否 包含 了预期的字符串
WebDriverWait(driver, 3).until(ec.text_to_be_present_in_element((By.ID, "my_element_id", 'elemenet_txt'))
text_to_be_present_in_element_value():
判断某个元素中的value属性是否 包含 了预期的字符串
WebDriverWait(driver, 3).until(ec.text_to_be_present_in_element_value((By.ID, "my_element_id", 'elemenet_txt'))
等待的超时异常
如果超过指定的等待时间,而仍然没有找到期望的元素,将抛出TimeoutException。可以通过try和except块来处理这个异常。
from selenium.common.exceptions import TimeoutException try: element = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CSS_SELECTOR, ".my_selector")) ) except TimeoutException: print("Element not found within 10 seconds.")
自定义等待条件
除了Selenium提供的内置等待条件外,你还可以自定义等待条件。这对于处理一些特殊情况非常有用。
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as ec from selenium.webdriver.common.by import By class custom_condition: def __init__(self, element_locator): self.element_locator = element_locator def __call__(self, driver): element = driver.find_element(self.element_locator) if element.get_attribute("data-custom-attribute") == "expected_value": return element else: return False element_locator = (By.XPATH, "//div[@id='custom_div']") element = WebDriverWait(driver, 10).until(custom_condition(element_locator))
等待的嵌套使用
有时候,页面的某个元素可能是动态加载的,需要等待元素加载完成后再等待它的子元素。
parent_element_locator = (By.ID, "parent_element") child_element_locator = (By.CLASS_NAME, "child_element") parent_element = WebDriverWait(driver, 10).until( ec.presence_of_element_located(parent_element_locator) ) child_element = WebDriverWait(parent_element, 10).until( ec.presence_of_element_located(child_element_locator) )
结语
显示等待是企业中常用的一种综合性的等待方式,能够解决的复杂场景也是多种多样的,那么我们今天就分享到这,下次再见👋🏻,更多测试技术支持 -- vi:lmx201125