一、问题现象
大家是否自动化执行过程中,出现脚本时而成功时而失败的情况;发现常见情况如下:
1、元素时而出现时而提示不存在,timeout
2、元素时而可以操作时而不能操作;提示:元素不可点击或不可操作
3、页面找不到等等
究其根本原因,就是咱们的应用在运行过程中,因为服务器性能、网络延迟等等原因,导致页面响应或者加载变慢,自动化脚本在操作元素时,元素没有加载完成导致的;
那么怎么做才能让脚本无论在服务器慢或者快时都能正常运行呢?
方法是元素出来了我才操作,怎么判断呢?
二、通常有如下几种办法:
1、硬等待 sleep(秒)
2、隐式等待
3、显示等待
其中硬等待和隐式等待功效相同,作用域和使用方法不同;都是等待设定的固定时间;不同是,硬等待是只对后一行脚本起作用,隐式等待是全局设置,所有操作都会等待设置的时间后,才操作;
这两种等待一定程度上能缓解稳定性问题,但不能根本解决,也会带来脚本执行效率问题;
因为本身元素可能1s加载完成了,但是设置后,每次都固定等待10s,白白浪费9s时间;如果几百行脚本,那浪费的时间太可观了!
有没有一种按需等待的呢?智能判断,元素出来了就操作,不出来就等;这就是显示等待
三、几种等待的范例:
四、显示等待讲解
这里重点讲解显示等待,显示等待用到2个类:WebDriverWait和expected_conditions两个类
WebDriverWait(driver,timeout,poll_frequency=0.5,ignored_exceptions=None)
- driver:webdriver对象本身
- timeout:超时时间,单位s;不能永无止境的等待对吧,总有个极限,这个就是极限时间
- poll_frequency:重试间隔,单位s;按照设定的时间每这个时间重新检查一下元素
- ignored_exceptions:是否忽略异常
webDriverWait类有两个常用的方法:until()和until_not()
- unit():直到条件为真,就终止执行,否则一直循环
- until_not():直到条件为否,就终止执行,否则一直循环
那么条件是什么呢?
五、常用条件:
方法 | 说明 |
title_is | 判断当前页面的 title 是否完全等于(==)预期字符串,返回布尔值 |
title_contains | 判断当前页面的 title 是否包含预期字符串,返回布尔值 |
presence_of_element_located | 判断某个元素是否被加到了 dom 树里,并不代表该元素一定可见 |
visibility_of_element_located | 判断元素是否可见(可见代表元素非隐藏,并且元素宽和高都不等于 0) |
visibility_of | 同上一方法,只是上一方法参数为locator,这个方法参数是 定位后的元素 |
presence_of_all_elements_located | 判断是否至少有 1 个元素存在于 dom 树中。举例:如果页面上有 n 个元素的 class 都是’wp’,那么只要有 1 个元素存在,这个方法就返回 True |
text_to_be_present_in_element | 判断某个元素中的 text 是否 包含 了预期的字符串 |
text_to_be_present_in_element_value | 判断某个元素中的 value 属性是否包含 了预期的字符串 |
frame_to_be_available_and_switch_to_it | 判断该 frame 是否可以 switch进去,如果可以的话,返回 True 并且 switch 进去,否则返回 False |
invisibility_of_element_located | 判断某个元素中是否不存在于dom树或不可见 |
element_to_be_clickable | 判断某个元素中是否可见并且可点击 |
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 |
六、显示等待使用实例:
def assertVisible2(self, locate, locateType=By.XPATH):
try:
WebDriverWait(self.driver, 15, 0.5).until(EC.presence_of_element_located((locateType, locate))) #判断元数是否被加载到了dom中,但不一定可见
WebDriverWait(self.driver, 15, 0.1).until(EC.visibility_of(self.driver.find_element(locateType, locate))) #判断元素是可见的
except:
raise AssertionError("断言失败!" + "元素[" + locate + "]不可见!")
else:
pass
return 1