作者: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的内容
|