selenium三种等待方式
2020-12-15 本文已影响0人
Gakki0725
作者:Gakki
前言
- 在浏览器加载一个页面时,页面内得元素可能是在不同的时间载入的,这会加大定位元素的困难程度,因为元素不在DOM里,会抛出
ElementNotVisibleException
异常,使用waits,我们就可以解决这个问题了。 - 超时的情况大致区分两类:
- 页面加载出现的超时
- 获取页面元素的超时
等待方式
- Thread.sleep()方法
- 隐式等待
- 它允许您将
WebDriver
暂停特定的时间,直到WebDriver
在网页上找到所需的元素为止。
- 它允许您将
- 显示等待
- 但是如果我们不知道在加载时该元素是可见/可点击的,该怎么办?正如它出现的时候一样,元素是动态的,并且可能会不时地变化。在这种情况下,显式等待将帮助解决此问题。让我们看一下显示等待的细节。
-
显式等待是动态
Selenium
等待的另外一种类型。显式等待帮助可在特定时间段内根据特定条件停止脚本的执行。时间到了以后,脚本将抛出ElementNotVisibleException
异常。在测试人员不确定要等待的时间的情况下,显式等待会派上大用场。使用elementToBeClickable()
或textToBePresentInElement()
之类的条件,可以等待指定的持续时间。可以结合使用WebDriverWait
和ExpectedConditions
类来使用这些预定义方法。
预期条件的类型
以下是在使用Selenium执行自动化测试时通常使用的几种预期条件。
- visibleOfElementLocated():验证给定元素是否存在
- alertIsPresent():验证是否存在警报。
- elementToBeClickable():验证给定元素是否在屏幕上存在/可单击
- textToBePresentInElement():验证给定元素是否具有必需的文本
- titlels():验证条件,等待具有给定标题的页面
还有更多可用的预期条件,您可以通过Selenium
官方GitHub
页面进行引用。与隐式等待一样,显式等待也会在每500毫秒后继续轮询。
显式等待与隐式等待区别
隐式等待 | 显式等待 |
---|---|
默认情况下应用于脚本中的所有元素。 | 仅适用于特定条件的特定元素。 |
不能基于指定条件(例如元素选择/可点击)而不是显式地等待。 | 可以根据特定条件指定等待时间。 |
确定该元素在特定时间内可能可见时,通常使用它 | 不知道元素可见性的时间时,通常使用它。它具有动态性质。 |
强制等待:sleep()
- 定义:设置固定休眠时间,单位为秒。缺点是不智能,使用太多的sleep会影响脚本运行速度。
- 代码展示:
from selenium import webdriver from time import sleep driver = webdriver.Chrome() driver.get("https://www.jianshu.com/") sleep(5) print(driver.current_url) driver.quit()
隐式等待:implicitly_wait
- 由webdriver提供的方法。
一旦设置这个隐式等待会在WebDriver对象实例的整个生命周期起作用,只需要设置一次即可
。它不针对某一个元素,是全局元素等待,即在定位元素时,需要等待页面全部元素加载完成,才会执行下一个语句。如果超出了设置时间则抛出异常。 - 注意: 当同时使用隐式等待和显式等待时,超时时间取二者中较大的
driver.implicitly_wait(10) #隐式等待10秒
- 代码展示:
from selenium import webdriver driver = webdriver.Chrome() driver.implicitly_wait(10) # 隐性等待,最长等10秒 driver.get("https://www.jianshu.com/") print(driver.current_url) driver.quit()
显式等待:WebDriverWait
- 定义:
- 等待某个条件成立时继续执行,否则在达到最大时长时抛出异常(TimeoutException)
- WebDriverWait类是由webdriver提供的等待方法,配合该类提供的until()和until_not()方法一起使用,就可以根据判断条件灵活的进行等待。
from selenium.webdriver.support.wait import WebDriverWait
- 调用方法:
- WebDriverWait(driver, 超时时长, 调用频率, 忽略异常).until(可执行方法, 超时时返回的信息)
- WebDriverWait(driver,timeout,poll_frequency=0.5,ignored_exceptions=None).until()
- 参数:
- driver:传入WebDriver实例,浏览器驱动
- timeout:超时时间,等待的最长时间
- poll_frequency:调用until或until_not中的方法间隔时间,默认是0.5秒
- ignored_exceptions:忽略的异常,如果在调用until或until_not的过程中抛出这个元组中的异常,则不中断代码,继续等待。如果抛出的是这个元组外的异常,则中断代码,抛出异常。默认中有NoSuchElementException。
- until与until_not
- until:当某元素出现或什么条件成立则继续执行
- until_not:当某元素消失或什么条件不成立则继续执行
- until与until_not里面的两个参数
- method:在等待期间,每隔一段时间调用这个传入的方法,直到返回值为True;
- message:如果超时,抛出TimeoutException,将message传入异常
- method的设置
- 必须是含有call的可执行方法。因此我们引用selenium提供的一个模块
from selenium.webdriver.support import expected_conditions as EC
- expected_conditions类提供的预期条件判断方法:
- title_is:判断当前页面的title是否完全等于(==)预期字符串,返回布尔值
from selenium import webdriver from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from selenium.webdriver.support.wait import WebDriverWait driver = webdriver.Chrome() driver.get("https://www.jianshu.com/") locator = (By.CLASS_NAME, 'logo') title = WebDriverWait(driver, 10).until(EC.title_is('简书 - 创作你的创作')) print(title)
- title_contains:判断当前页面的title是否包含预期字符串,返回布尔值
WebDriverWait(driver, 10).until(EC.title_contains('创作你的创作'))
- presence_of_element_located:判断某个元素是否被加到了dom树里,并不代表改元素一定可见,如果定位到就返回WebElement
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'logo')))
- visibility_of_element_located:判断某个元素是否可见,可见代表元素非隐藏,并且元素的宽和高都不等于0,如果可见就返回这个元素。
WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.CLASS_NAME, 'write-btn')))
- visibility_of:如4一样,只是4需要传入locator,而5直接传所定位到的元素element就可以了。
WebDriverWait(driver, 10).until(EC.visibility_of(driver.find_element(by=By.CLASS_NAME, value='write-btn')))
- presence_of_all_elements_located:判断是否至少有1个元素存在于dom树中。如:某个页面上含有N个元素的class都是'title',那么只要有1个元素存在就返回列表
WebDriverWait(driver, 10).until(EC.presence_of_all_elements_located((By.CLASS_NAME, 'title')))
- visibility_of_any_elements_located:判断是否至少有一个元素在页面中可见,存在就返回列表
WebDriverWait(driver, 10).until(EC.visibility_of_any_elements_located((By.CLASS_NAME, 'title')))
- text_to_be_present_in_element:判断某个元素中的text是否包含了预期的字符串,返回布尔值
WebDriverWait(driver, 10).until(EC.text_to_be_present_in_element((By.ID, 'sign_in'), '登录'))
- text_to_be_present_in_element_value:判断某个元素中的value属性是否包含了预期的字符串,返回布尔值
WebDriverWait(driver, 10).until(EC.text_to_be_present_in_element_value((By.NAME, 'utf8'), '✓'))
- frame_to_be_available_and_switch_to_it:判断该frame是否可以switch进去。如果可以,返回True并且switch进去,否则返回False。(很少使用)
- invisibility_of_element_located:判断某个元素中是否不存在于dom树中或不可见,如果可见返回False,不可见返回这个元素
WebDriverWait(driver, 10).until(EC.invisibility_of_element_located((By.CLASS_NAME, 'popver'))) # popver在此页面中是一个隐藏元素
- element_to_be_clickable:判断某个元素中是否可见并且是enable的,这样的话才叫clickable,才可以点击
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, 'sign_up'))).click()
- staleness_of:等某个元素从dom树中移除,返回True。否则返回false
- element_to_be_selected:判断某个元素是否别选中了,一般用在下拉列表
- element_selection_state_to_be:判断某个元素的选中状态是否符合预期
- element_located_selection_state_to_be:跟上面的方法作用一样,只是上面的方法传入定位到的element,而这个方法传入locator。
- alert_is_present:判断页面上是否存在alert
alert = WebDriverWait(driver, 10).until(EC.alert_is_present()) # 如果有就切换到alert并返回alert的内容