前言
来啦老铁!
最近在做 Web UI 自动化的时候遇到一个比较棘手的问题,那就是:
-
如何在不同 selenium node(也就是不同机器) 上使用 selenium node 上的文件?
相信这个会是 Web UI 自动化比较高端的问题了,记录一下我和我的小伙伴是怎么设计的~
学习路径
- 需求分析;
- 潜在方案;
- 最终方案;
- 其他知识;
1. 需求分析;
背景:
某些 Web UI 自动化测试,涉及前端访问机器文件,例如文件上传功能。
这样的功能在我本地、单台机器,并无大碍,因为执行脚本的机器、启动浏览器的机器都在同一台机器,文件自然能够使用。
而在实际场景中,更多的是,执行脚本的机器(也就是 Jenkins node)、启动浏览器的机器(也就是 selenium node),甚至连 selenium hub(主管负载均衡、selenium node 间通信)也是另外的机器。这时候,selenium node 上并无我们想要的文件,或者并无 Jenkins node 上的文件,因此测试执行失败。
目标:
需要一个能在各个 selenium node 准备文件、管理文件的能力。
难点:
- 能在任意 selenium node 准备文件;
- 能删除任意 selenium node 上的文件,实行文件闭环管理;
2. 潜在方案;
1. 在各 selenium node 机器上事先放好文件,例如通过 shell 去完成这个步骤,然后再开始执行脚本;
优点:
- 对机器拥有全方位的控制能力;
缺点:
- 涉及到 shell 执行,也就是需要管理所有机器的用户名、密码,不方便;
- 增加了测试的复杂度,对所有机器磁盘污染,且磁盘占用时间比较久;
2. 搭建一个专用服务,包含下载文件、删除本地文件的功能,脚本在需要时,访问该服务的前端(或后端接口)进行下载,然后在脚本执行完毕时,访问该服务前端的删除本地文件功能,进行磁盘释放;
优点:
- 如果可行,那么能够对文件进行闭环管理,能达到使用要求;
- 仅对正在使用的机器会有磁盘占用,且该用例执行完毕就可释放磁盘;
缺点:
- 该方案比较重,需要额外的服务器和服务代码;
- 浏览器上并不能操作本地文件进行删除操作,因为删除文件是 nodejs 才能做的,前端是 javascript,二者并不能划等号,因此并不能对文件进行闭环管理;
- 增加了一个工具类平台,增加了系统复杂度;
3. 将文件上传至公司已有的文件服务器,在需要文件时,访问该文件服务器进行下载,同时结合访问本地下载路径,能判断是否下载完成,也可在下载前先访问本地下载路径看是否已有,以做到不重复下载;
优点:
- 利用已有服务,不重复造轮子,轻量;
- 能基本满足使用要求;
缺点:
- 也是无法删除文件,不能做到文件闭环管理;
- 在文件内容发生改动而文件名未改的情况下,并不能更新文件,造成后续的错误表现;
简单的评估,这三个方案都不能完全满足使用需求,而方案 3 最接近。
3. 最终方案;
将文件上传至公司已有的文件服务器;
在需要文件的用例,启动一个独立的 chrome 浏览器(采用无头模式),自定义其下载路径(设置随机路径,例如:const saveToDir = osType == "mac" ?
/tmp/${getRandomString(10)}
:C:\\${getRandomString(10)}
);利用 chrome 浏览器参数 user-data-dir=自定义文件夹,该文件夹在关闭 selenium session 时会自动清理的特性,将 user-data-dir 参数值设置为上一步的自定义下载路径,那么在关闭 selenium session 时也就会将我们的文件删除,释放磁盘,且这个是用例级别的;
访问下载链接,则文件会被下载至自定义的下载路径下;
用例执行结束,则自定义的下载路径则会立马被删除;
优点:
- 利用已有服务,不重复造轮子,轻量,不增加系统复杂度;
- 文件闭环管理,想在哪台 selenium node 执行就在哪台执行;
- 下载的文件自动删除,不需要在用例上增加删除代码,十分方便;
- 由于文件需要即下载,用完即毁,因此并不存在 “在文件内容发生改动而文件名未改的情况下,并不能更新文件,造成后续的错误表现” 的问题!
核心代码:
这个方案我自己觉得非常巧妙,既不增加系统复杂度,又能在不同机器上下载文件、删除文件,文件闭环管理,用例闭环管理!!!
当然,可能还有其他方法,欢迎评论区讨论,望不吝赐教~
4. 其他知识;
1. headless 模式,在 windows 上只需要在 args 添加 --headless 就能工作了,但是在 mac 却不行,根据 https://github.com/serenity-bdd/serenity-core/issues/3059 上描述的,mac 要使用无头模式,需要在 args 上添加 --headless=new,windows 在这样的配置下也能工作,可统一配置为 --headless=new,例如:
2. 如何检查文件是否下载完毕?
下载时,文件会带 . crdownload 后缀,如 abc.mp4.crdownload,下载完成后,文件不会带 . crdownload 后缀,例如:abc.mp4
3. selenium hub 有没有向 node 传递文件的方法?
这个还真有,详见:https://webdriver.io/docs/api/selenium/#file,有机会我们再试试看~
不过,我们的设计更合理,用官方这个方法,仍然需要一个下载文件的方案,也就是我的方案,实际上会更为复杂了,但作为知识点了解一下,还是不错的~
好了,今天就简单记录到这里,欢迎读者朋友与笔者进行交流沟通~
如果本文对您有帮助,麻烦动动手指点点赞?
谢谢!