用webdriver进行web端自动化时,一开始还惊讶300多个用例为何运行了将近五六十分钟,后来发现一个.py里面用例明明只有十多个,但执行却用了140多秒,也就不惊讶了。做电商后台自动化,业务逻辑比较多,操作步骤也比较繁琐。但是,也是可以通过优化代码、减少非必要的繁杂步骤,从而提高测试用例执行效率和用例稳定性的。通过优化后,自动化测试执行时长稳定在30分钟左右,而且用例更加稳定了。

python中selenium如何加速 selenium速度优化_自动化


优化代码,可以从以下九个方面着手:

1、原则:稳定优先级高于运行速度

Selenium脚本的执行速度受多方面因素的影响,如网速,操作步骤的繁琐程度,页面加载的速度,以及我们在脚本中设置的等待时间,运行脚本的线程数等。所以不能单方面追求运行速度,要确保稳定性,能稳定地实现回归测试才是关键。

2、sleep解决操作过快,资源加载不完整引起的问题

元素定位到了,操作过快,也会导致操作失败,无法正常进行下一个步骤。例如,新增某条记录,刚准备好数据就立刻点击提交,因前端的js文件还没加载完成,导致提交失败(也有可能是因为服务器的响应速度慢)。这时候,sleep就发挥着重要作用,它强制页面等待一段时间,等js加载完毕或者资源有所释放,再去操作页面元素。

3、不存在的元素查找时间超长

自动化过程中,发现查询一个不存在的元素,查找时间是很长的,那是因为在setUp()里面设置了隐式等待driver.implicitly_wait(time)。隐式等待是设置全局的查找页面元素的等待时间,在这个时间内没找到指定元素则抛出异常。这告诫我们,在删除记录时,记录最好不要全部删除,implicitly_wait(time)也不宜设置过长,否则,如果去查找一个不存在的元素,会因为隐式等待增加用例的平均执行时间,导致效率低下。

4、web端UI自动化,Firefox稳定性比chrome要好

通过观察Firefox和chrome作为驱动浏览器进行自动化测试,Firefox的稳定性要比chrome的高。如用到send_keys()的时候,偶尔会发现,chrome传值不完整的问题,通过对chrome传值观察,猜测是传值的时候,chrome将字符串拆解成单个字符来传,一旦不小心移开了焦点,会导致传值不完整。

5、按钮无法用click()点击,用js代替

一般而言,用click()是可以解决按钮点击方面的问题的,但是有时候操作某个按钮,会有类似的提示:Element <div class="el-submenu__title"> is not clickable at point (115,358) because another element <div class="el-loading-mask"> obscures it如果确定元素定位没问题,不妨尝试用targetTag = self.find_element(*tarEnsure_loc) self.driver.execute_script("arguments[0].click();", targetTag)替代.click()方法。这种代替方法,在common类定义的公共方法里面使用,特别好用。同时,多点留意公共方法的异常处理。

6、用异常处理的方式解决用例执行失败问题

用例执行失败,一般会因为元素无法定位到,或者操作元素没有达到预期效果,导致下一步卡住了。像展开二级菜单,虽然定位到一级菜单,但是,因为二级菜单的元素尚未加载完成,无法展开二级菜单。无法展开二级菜单,无法打开模块操作页面,下面的用例无疑都会因为无法定位到而执行失败。这时候,try-expect抛异常的方式就显得异常重要,捕捉到异常后,用driver.refresh()方法刷新页面,然后再去重新定位操作。
异常处理,在一定程度上替代了pytest框架重跑的功能,大大提高脚本的可执行性和用例的稳定性。

7、通过优化内存或禁用加载项解决浏览器运行过长导致的内存泄露问题

浏览器运行时间过长,占用大量内存,导致内存不断增大,有内存泄露的风险。这时候,需要禁止一些加载项等手段优化内存。同时,在运行最后一个用例后,建议关掉浏览器释放内存。

7.1、禁止缓存
profile = webdriver.FirefoxProfile()                                          
# 禁用浏览器缓存                                                         
profile.set_preference("network.http.use-cache", False)             
profile.set_preference("browser.cache.memory.enable", False)              profile.set_preference("browser.cache.disk.enable", False)
profile.set_preference("browser.sessionhistory.max_total_viewers", 3)
profile.set_preference("network.dns.disableIPv6", True)              
profile.set_preference("Content.notify.interval", 750000)
profile.set_preference("content.notify.backoffcount", 3)
# 有的网站支持   有的不支持                                              
profile.set_preference("network.http.pipelining", True)                  
profile.set_preference("network.http.proxy.pipelining", True)                  profile.set_preference("network.http.pipelining.maxrequests", 32)
7.2、禁止加载项
fp = webdriver.FirefoxProfile()
fp.set_preference('permissions.default.image', 2)#禁止图片加载
fp.set_preference('browser.migration.version', 9001)  # 部分需要加上这个
fp.set_preference('dom.ipc.plugins.enabled.libflashplayer.so','false')#禁用flash
fp.set_preference('javascript.enabled', 'false')#禁用js
fp.set_preference('permissions.default.stylesheet', 2)#禁止css加载
driver = webdriver.Firefox(firefox_profile=fp)
7.3、不定期清除cookies
driver.delete_all_cookies()

8、用expected_conditions+webDriverWait显示等待

在自动化过程中,sleep是必不可少的,毕竟要请求页面也不是一下子就加载完整了,如果不等待,页面没有加载完整,可能无法定位元素,导致操作元素失败。

9、用多进程/多线程、分布式提高脚本执行效率

网上很多技术性文章建议用多线程或多进程,这样可以降低自动化测试的总耗时,但是,必须注意使用设备的内存问题,因为随着自动化时间推移,内存使用会持续增长,多进程或多线程容易造成内存泄露。用多进程或多线程时,执行完一个.py文件,必须driver.close(),关闭浏览器可释放内存。也可考虑用selenium Grid分布式技术代替多线程,提高脚本的执行效率。