Selenium自动化测试中的等待
自动化测试过程中的等待我习惯分为两种固定等待和动态等待。
一、固定等待
固定等待就是直接采用sleep的方式让代码等待固定时间。
这是比较简单的等待方式,是一种不推荐使用但是在某些特定条件下最快能够解决问题的等待方式。不推荐使用是因为,固定等待过多使用的情况下会极大程度的降低代码的执行效率。
UI自动化测试的执行速度在很大程度上取决于页面的响应速度,网速以及电脑的配置,这个时候固定时间的等待为了能够提高代码通过率,会把等待时间设置为最长时间的等待,这就造成了大量时间的浪费。但是在没有找到合适的动态等待方式时,固定时间的等待是保证代码能够正常通过的最有效最快速的解决方案。
我在调试代码时经常使用添加固定等待的方式来确认代码失败的原因是否因为等待时间不够。
二、动态等待
1. 隐士等待
最先接触到的动态等待是selenium的隐示等待。
这种等待方式的优点显而易见,设定一个最长等待时间,在设定的时间内会一直查找元素,直到最长等待时间超时。但是这种等待方式在很多地方也是不被推荐的。
隐式等待是针对drive的全局设置,在所有findElement(s)方法处生效(也仅在findElement方法生效),如果本身想要查找的元素就是不希望存在的,那么他也会等待到最长等待时间。
2. 使用ExpectedConditions进行动态等待
除了selenium的隐示等待,selenium本身还提供了driverwait和ExpectedConditions及其子类,提供了很多动态等待的方式,例如element_to_be_clickable(), text_to_be_present_in_element_value()
基于python的Selenium源码可以在以下路径下找到Python27\Lib\site-packages\selenium\webdriver\support\expected_conditions.py
#coding=utf-8 from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.wait import WebDriverWait driver = webdriver.Firefox(); driver.get("http://www.baidu.com") WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.ID,'kw')))
而且我们可以参考ExpectedCondition中方式实现自己的动态等待。
除此之外我们还可以通过设置计时器的方式来实现动态等待,例如封装动态等待元素出现的方法如下:
接下来我们讨论在UI自动化测试过程中的经常需要添加等待的场景:
1. 等待页面元素出现
这是最常见的等待,我们可以封装等待页面元素出现的查找元素,来替代隐示等待所完成的功能,从而避免隐示等待的不足
以下分别给出使用driverwait和计时器两种方式封装的动态等待的代码(java版本):
2.等待页面加载(刷新,页面跳转,打开新的窗口等)
页面加载通常在系统中是最耗时的,如果单纯使用等待页面元素出现的方式,就需要将等待超时时间设置的很长才能保证程序顺利运行。但是如果添加了先等待页面加载完成再等待元素出现就会灵活很多。我目前使用过的等待页面加载的方式有以下几种:
1)通过document.readyState状态码判断。document.readyState是 javascript中判断页面加载状态的字段,有complete等几个状态,我们需要的是当状态为complete时判断页面加载完成
2)通过jquery判断。页面加载为了保证加载的效率多采用Ajax异步加载的方式,这时document.readyState已经为complete了,但是页面中部分list还是在异步加载过程中。这时我们就需要使用jquery来判断异步加载是否已经完成。return jQuery.active == 0
3)通过页面显示的加载进度条来判断。正规的页面在加载过程中为了与用户进行交互都会添加进度条或者正在加载的图标,最常见的就是动图的⭕️。这个时候我们可以使用等待加载图标消失来判断页面是否加载完成。
当然使用什么方式的等待是需要灵活处理的。这里谈一下我在处理等待页面加载时所遇到的两个坑。
第一个是在点击登录按钮后,我选择了使用判断document.readyState的方式进行等待,但是发现页面程序并没有按照我期望的方式等待。而是直接完成了等待进入了下一个步骤判断元素是否存在,从而因元素不存在而失败了。研究发现点击login按钮后,后台相应处理了一些其他脚本,并没有直接发起页面跳转的request。而这个时候我们的脚本已经去判断了一次document.readyState的状态,这个时候脚本获取的是login页面的状态,而不是我期望home页面的加载状态。在这里我加入了1s的sleep,然后再判断document.readyState,从而解决了问题。
第二个是对于loading的动态图片。我们发现在当前系统加载完成后的html源码中找不到这个图片的img标签,这个标签是动态生成并在加载完成后消失的。所以找到这个标签的locator成为了难点。最后我们通过在页面加载的时候立刻断网的方式来使这个img标签不能正常消失,从而来给我们时间定位这个元素。