#按回车键页面更新了
inputbox.send_keys(Keys.ENTER)
time.sleep(1)
self.check_for_row_in_list_table( "1:Buy woolen yarn")
我们看功能测试中的这段代码,这叫强制等待
强制等待,设置固定休眠时间。 python 的 time 包提供了休眠方法 sleep() , 导入 time 包后就可以使用 sleep(),进行脚本的执行过程进行休眠。
隐式等待相比强制等待更智能,在脚本中我们一般看不到等待语句,但是它会在每个页面加载的时候自动等待;隐式等待只需要声明一次,一般在打开浏览器后进行声明。声明之后对整个drvier的生命周期都有效,后面不用重复声明。
某些情况下,selenium 认为正在页面加载时,他会自动等待一会。如果页面查找的元素尚未出现,还可以使用implicitly_wait 指定等待多久
显式等待相比隐式等待更智能,是你定义的一段代码,用于等待某个条件发生然后再继续执行后续代码。
在设置时间内,默认每隔一段时间检测一次当前页面元素是否存在,如果超过设置时间检测不到则抛出异常。默认检测频率为0.5s,默认抛出异常为:NoSuchElementException
我们在这个里使用了强制休眠1秒,但是我们不确定这是一个合理的时间啊,万一他0.1 秒就可以呢,但是如果设置0.1 秒又怕他等待的时间不够。所以说我们的sleep 太过含糊,
所以我们要调整我们的休眠的实现方式:
我们将check_for_row_in_list_table,重命名为wait_for_row_in_list_table,添加一些轮询/重试逻辑
首先看一下 没改之前的check_for_row_in_list_table
我们在没改的时候是休眠一秒,在这个时间内然后把参数row_text传入,先获取元素 id_list_table ,然后定位元素 tr
然后断言判断。但是我们不能确定的是他能够查到呢
def check_for_row_in_list_table(self,row_text):
table = self.browser.find_element_by_id("id_list_table")
rows = table.find_elements_by_tag_name('tr')
self.assertIn(
row_text ,[row.text for row in rows]
)
修改一下:
from selenium.common.exceptions import WebDriverException
MAX_WAIT = 10 #设定准备等待的最长时间常量,10秒足够去应对潜在的问题和缓慢因素了
def wait_for_row_in_list_table(self,row_text):
start_time = time.time()
while True: #这个循环一直运行,直到遇到两个出口中的一个为止
try:
#断言跟上面比是没有变化的
table = self.browser.find_element_by_id("id_list_table")
rows = table.find_elements_by_tag_name('tr')
self.assertIn(
row_text ,[row.text for row in rows]
)
return #如果断言正确就退出函数跳出循环了
except(AssertionError,WebDriverException) as e: #两种异常:AssertionError ,因为页面中虽然有表格,但是可能页面加载前 就存在,里面还是没有我们要找的行;WebDriverException 页面未加载或者selenium 未在页面找到表格元素时抛出。
if time.time()-start_time > MAX_WAIT:
raise e #第二出口 如果执行到此,说明代码有异常不断抛出,已经超过最大时间,因此这里再次抛出异常,向上冒泡,最终出现在调用跟踪中,指明测试失败原因 ( **Python中的raise 关键字**用于引发一个异常,基本上和C#和Java中的throw关键字相同格式: 主动抛出异常终止程序 raise 异常名称(‘异常描述’))
time.sleep(0.5) # 如果捕获异常,那么就等待一小段时间,然后重新循环。
现在我们把time.sleep()去掉然后调用我们新写的方法
运行起来,跟原先一样的效果,不过运行时间快了几秒。哈哈
但是这并不能明确看出我们改动的是否合理,我们改动一下我们要查找的元素,故意写一个没有的,看一下抛出什么错误
while True:
try:
table = self.browser.find_element_by_id("id_list")
rows = table.find_elements_by_tag_name('tr')
self.assertIn(
row_text ,[row.text for row in rows]
)
结果:
这个错误正是我们想要看到的结果:
改回原来,远行确认一下吧。
总结:
避免使用含糊的休眠:
一旦需要等待什么加载,我们第一反应是使用time.sleep ,但是这样做带来的问题是时间长度我们并不能确定:要么短容易假失败,要么长,拖慢测试。所以推荐使用重试循环,它可以轮询应用,今早的向前行走
不要依赖selenium 的隐式等待
selenium 的隐式等待在各个浏览器上的实现各不相同,隐式等待在selenium3 的Firefox 驱动上不太靠谱。
禅道:明了胜于晦涩 因此首选显示等待。