由于现在部分web应用加载方式的选择,页面会需要一定时间逐渐加载完毕,也就是说有的页面元素先加载出来,有的元素后加载出来。如果直接定位所查找的元素的话,可能会由于此元素尚未加载完毕找不到元素从而报错,由于网络不稳定这种情况出现的几率会大很多,一般解决方法的话,time.sleep()函数可以避免一些这种状况,但是缺少了灵活性。在selenium中有关于等待的方法可以比较灵活的解决这个问题,这次主要讲解selenium中元素等待WebDriverWait的使用,以及全局的设置。
三个全局设置时间的方法中,设置的时间单位为秒,例如implicitly_wait(30),意思是超过30秒没有定位到一个元素,程序就会报错抛出异常,期间会一直轮询查找定位元素。
设置全局元素查找的超时时间
implicitly_wait(time_to_wait)
设置全局js异步脚本超时时间
set_script_timeout(time_to_wait)
设置全局页面载入超时时间
set_page_load_timeout(time_to_wait)
个人理解:WebDriverWait可以当做元素等待,灵活的设置查找元素时的判断条件,同时由于方法中包含了大量webdriver自带的判断方法,只返回True和False,所以个人认为也可以灵活的当做断言来使用。
这个格式的结构有点像语言中主谓宾的结构,实例的意思是,程序每0.5秒检查,是否满足:标题包含“百度一下”这个条件,检查是否满足条件的最长时间为:15秒,超过15秒仍未满足条件则抛出异常
WebDriverWait(driver, 15, 0.5).until(expected_conditions.title_contains("百度一下"))
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions
满足条件后继续执行,否则在设置时间过后抛出异常
WebDriverWait(driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None)
直到调用的方法返回值为True
until(method, message='')
直到调用的方法返回值为False
until_not(method, message='')
判断当前页面标题是否为title
title_is(title)
判断当前页面标题是否包含title
title_contains(title)
判断此定位的元素是否存在
presence_of_element_located(locator)
判断页面网址中是否包含url
url_contains(url)
判断页面网址是否为url
url_to_be(url)
判断页面网址不是url
url_changes(url)
判断此定位的元素是否可见
visibility_of_element_located(locator)
判断此元素是否可见
visibility_of(element)
判断此定位的一组元素是否至少存在一个
presence_of_all_elements_located(locator)
判断此定位的一组元素至少有一个可见
visibility_of_any_elements_located(locator)
判断此定位的一组元素全部可见
visibility_of_all_elements_located(locator)
判断此定位中是否包含text_的内容
text_to_be_present_in_element(locator, text_)
判断此定位中的value属性中是否包含text_的内容
text_to_be_present_in_element_value(locator, text_)
判断定位的元素是否为frame,并直接切换到这个frame中
frame_to_be_available_and_switch_to_it(locator)
判断定位的元素是否不可见
invisibility_of_element_located(locator)
判断此元素是否不可见
invisibility_of_element(element)
判断所定位的元素是否可见且可点击
element_to_be_clickable(locator)
判断此元素是否不可用
staleness_of(element)
判断该元素是否被选中
element_to_be_selected(element)
判断定位的元素是否被选中
element_located_to_be_selected(locator)
判断该元素被选中状态是否和期望状态相同
element_selection_state_to_be(element,Boolean)
判断定位的元素被选中状态是否和期望状态相同
element_located_selection_state_to_be(locator,Boolean)
判断当前浏览器页签数量是否为num
number_of_windows_to_be(num)
判断此handles页签不是唯一打开的页签
new_window_is_opened(handles)
判断是否会出现alert窗口警报
alert_is_present()
全局设置只需要一行代码,这里为了演示,分别在设置前和设置后分别定位一次元素,元素本身不存在,用来模拟网络波动导致尚未加载出来的状态;然后统计这两次定位所需的时间,发现直接定位只有一次,如果找不到就直接抛出异常了,设置定位超时时间后,在这个时间段内会一直来查找元素。
from selenium import webdriver
import datetime
driver = webdriver.Chrome()
driver.get("https://tieba.baidu.com")
# 未定义全局等待时,直接定位元素
start1 = datetime.datetime.now()
try:
# 使用一个不存在的元素,模拟还没有加载出来的状态
driver.find_element_by_css_selector("aaaa[title = '娱乐明星']").click()
except:
print("没有定位到元素")
end1 = datetime.datetime.now()
print("设置前等待时间: %s 秒" % (end1-start1).total_seconds())
# 设置全局等待后,再进行定位元素
driver.implicitly_wait(10)
start2 = datetime.datetime.now()
try:
driver.find_element_by_css_selector("aaaa[title = '娱乐明星']").click()
except:
print("没有定位到元素")
end2 = datetime.datetime.now()
print("设置后等待时间: %s 秒" % (end2-start2).total_seconds())
运行结果:
没有定位到元素
设置前等待时间: 0.015992 秒
没有定位到元素
设置后等待时间: 10.045907 秒
这里主要展示下WebDriverWait中,大部分的返回类型是True\False,部分方法,例如presence_of_element_located返回类型为一个元素,我们可以定位元素之后,直接对返回的元素进行click、send_keys等操作。
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as Expect
driver = webdriver.Chrome()
driver.get("https://tieba.baidu.com")
# 部分关于元素定位的判断返回类型为:元素
assert_ele = WebDriverWait(driver, 15, 0.5).until(Expect.presence_of_element_located(("id", "wd1")))
assert_ele.send_keys("测试")
print("返回类型 %s" % assert_ele)
# 大部分方法返回类型为True\False
assert_judge = WebDriverWait(driver, 15, 0.5).until_not(Expect.title_is("网易"))
print("返回类型 %s" % assert_judge)
# 判断失败后会报错
assert_judge = WebDriverWait(driver, 5, 0.5).until(Expect.title_is("网易"), "错误信息:网页标题不是网易")
运行结果:
返回类型
返回类型 False
Traceback (most recent call last):
File "D:/1git/cenpur_uitest/test_case/demo.py", line 17, in
assert_judge = WebDriverWait(driver, 5, 0.5).until(Expect.title_is("网易"), "错误信息:网页标题不是网易")
File "C:\Users\test\AppData\Local\Programs\Python\Python35\lib\site-packages\selenium\webdriver\support\wait.py", line 80, in until
raise TimeoutException(message, screen, stacktrace)
selenium.common.exceptions.TimeoutException: Message: 错误信息:网页标题不是网易