背景
快到年底了,没啥东西要做了,搞一把 WebUI 自动化测试作为 2023 年收官之战,以下仅介绍技术实现思路,也欢迎大家有更好的想法在评论区交流。
需求
实现一个面向普通用户的 WebUI 自动化测试服务,实现效果可以参考MeterSphere的 UI 自动化测试功能,当然这玩意儿是要收费才能用,可以申请个账号去体验下。注意:不是在给 MeterSPhere 打广告,只是懒得写需求而已。
技术选型
虽然现在也有一些开源的 WebUI 自动化测试平台,但是调研了之后发现并不好用,比如 LuckyFrame,代码都是写死的,没啥扩展性,不是说这个项目不好,而是不满足我们的需求。所以最后选择了半天,使用如下技术栈来实现:
Jmeter, Jmeter-plugins-webdriver, Springboot
- 以 Jmeter为底层用例的执行引擎,配合 Jmeter 丰富的组件,可以实现复杂的用例步骤。
- Jmeter-plugins-webdriver是一个开源的 Jmeter 插件,底层基于 Selenium 开发,支持 Jmeter 实现 UI 自动化测试。
- 简单易上手的 web 框架自然是 Springboot 了。
实现流程
以上是大概的实现流程,整体思路为:
- 前端将用户操作封装为后端接口能处理的 json。
- 解析 json,将用户操作识别出来,然后生成代码,原理类似于 Selenium-IDE 中代码生成的逻辑。
- 生成一个空的 HashTree,默认填充 TestPlan 和 ThreadGroup 组件,并设置好属性。
- 按照用户的每一步的操作,分别生成一个 WebDriverSampler 组件,这个组件就是Jmeter-plugins-webdriver提供的采样器组件。
- 将第2步生成好的代码,填充到 WebDriverSampler 组件的 script 属性中。
- 拼装完整的 HashTree,并添加一个自己开发的后台监听器组件(继承AbstractBackendListenerClient即可,不知道的可以自己百度)。
- 将最后生成的 HashTree,交给 Jmeter 执行,注意,为了保证不同测试用例能够独立执行,每次执行新用例,必须要重新 new 一个 StandardJmeterEngine。
遇到的坑
Jmeter-plugins-webdriver 插件有个 bug,就是在执行WebDriverSampler.sample方法时,如果用例中有主动关闭浏览器的步骤,就会导致采样器报错,原因是:在脚本执行结束后,需要对采样器结果进行封装,会将页面源码封装为 SampleResult 对象的 ResposeData,将当前页面的 URL 设置为 SampleResult 对象的 URL,但是因为浏览器已经被主动关闭了,这个时候再也无法获取到页面源码和 url,就会导致采样器结果标记为异常。
WebDriverSampler的 sample方法中,并未设置采样器开始和结束时间,导致自己开发的后台监听器中,无法取到用例的执行时长。
我用的 Jmeter 版本是 5.4.1,其中 beanshell 版本是 Jmeter 自带的 2.0b6 版本,在这个版本中,使用 Java 编写代码时,会将 null 转为 void,详情可见这几个bug:https://github.com/apache/jmeter/issues/3411
https://github.com/apache/jmeter/issues/6110
解决方案就是把 beanshell 升级到 2.1.1在服务器上部署时,需要安装浏览器运行环境,我这边用的 chrome,但是在测试时发现打开的页面要么中文是方框,要么页面默认是英语。记得安装中文语言包,并设置服务器默认语言为中文,不知道怎么设置就去问 gpt 吧,懒得写了。
服务器上运行 chrome 可能会出现 chrome 启动失败,记得增加如下配置到 ChromeOptions 中:
1 | /** |
- 无法并行执行用例,这个坑爹的问题困扰了我很久,最后发现是我在 ChromeOptions 中加了一个配置 “–remote-debugging-port=9222”,这个配置会让 WebDriver 在指定端口启动,多个用例执行时会创建多个 session,但是 9222 端口被占用了,导致其他 session 创建失败,或者出现session 串掉的情况,千万别加这个配置,尤其是你需要并行执行用例的时候。
总结
这个 WebUI 自动化技术实现上没啥难度,难的地方在于如何做技术选型,因为绝大多数人做 UI 自动化都是想着用框架写代码实现,但是很少有人会去挑战通过代码生成的方式来做,只要把实现思路理清楚,其实写代码也就那么回事了。对了,我fork 了这个Jmeter-plugins-webdriver插件到 gitee 了,把上面两个问题处理了一下,有兴趣的可以直接用我改过的代码:https://gitee.com/linvaux/jmeter-plugins-webdriver