这是一份在UI自动化测试中使用图像对比的实践分享,分为故事篇和技术篇两部分,故事篇会首先回顾这几年在视觉测试上的历程,技术篇则会介绍一些视觉测试上的技术总结。
六年前刚入职到ThoughtWorks成都办公室后,第一次参加QA社区的Catch Up,那时的我在新环境中还分不清谁是张三谁是李四。 会上,依稀记得有两位貌似道行深厚的人物,就某个工具的使用反馈,询问在座的众生,现场一片寂静。会后,回到组上,我好奇的 问了一下我们的TL(请允许这里隐去TA的名字,不然我多半会被怼的)那是什么东西、我们有没有使用,面对TL一番风卷残云的 介绍,作为刚刚从通讯行业跨入互联网行业才三天的菜鸟,小的我真的是屁都没听懂,唯一听明白并且记下来的就是“它还需要部署服务器,很难用”。
那个工具的名字叫做Viff,在后来很长的一段时间内,我仍然不知道它是干嘛的,而这,就是我第一次和UI测试中的图像对比的擦肩而过。
一不小心,摸到了图像对比的大门
有时候,接触某种技术、思考某种解决方案,靠的真不是大咖的演讲,而就是那么点儿缘分和灵光一现。
时间来到2016年10月,某澳洲项目S。有一次,从王小礼的桌旁溜过,看她一副愁眉苦脸、生无可恋的样子,就猜到多半有”戏”。本着有“戏”大家乐的心态,随便打听了一下。 原来,她们组最近在给客户做产品换肤。了解S项目的同学应该都知道,客户是一个集团企业,旗下有八九个品牌,所以通常一个产品就会有八九套UI。 而她们组在做的,就是给其中的多个品牌同时换肤。面对每天都在变化的UI,有时甚至是往复修改的CSS,别说写自动化测试了,每张卡的人肉检查早都已经应接不暇了。
当时的闲聊中,我提到的建议是,不知道有没有什么工具能帮着检查这类UI快速变更的页面。下来再琢磨这个问题,经过一番折腾,最终发现原来有种手段叫做“Visual Regression Testing”。
至于后来王小礼是怎么熬出她们的品牌换肤的,我就不知道咯,阿弥陀佛~
出师未捷身先死
既然摸到了图像对比的大门,不进去捣腾捣腾,就说不过去了是吧!当时,开源社区中的当家花旦是BackstopJS,使用配置文件的方式来编写和管理测试案例,完全没有多大的上手难度,输出的报告对于从来没接触过视觉测试的人来说,还是让人眼前一亮。
当时,我们组的工作也是维护一个S项目下的某个前端应用,所以在项目上通过BackstopJS来实践视觉测试,便成了非常正儿八经的选项。然而、可是、没想到,仅仅用BackstopJS遍历了两三个页面,测试就…崩了!是的,你没看错,崩了!经过几番调查,问题很快确定了:BackstopJS基于配置文件来组织测试案例,执行测试时为了能够做到Headless,使用的驱动是PhantomJS(是的,就是那个作者半途跑路的PhantomJS),而PhantomJS原生不支持ES6。所以,解决办法就是……没有办法!什么,你说BackstopJS支持Puppeteer?Puppeteer发布v1版本是在2018年的一月,至于BackstopJS完成使用Puppeteer替换PhantomJS,那更是猴年马月的事情咯~
找准目标,二次开发
刚刚开门就撞上了叹息之墙,有够背的,可即便没能取得开门红,图像对比在UI测试中的巨大潜力,仍旧让我深信这是一滩值得去趟的“浑水”。
换个工具继续尝试,接下来盯上的就是Dpxdt(我用办公室阿姨擦桌子的抹布打赌,你第一次绝对不知道这玩意儿怎么念)。选择Dpxdt是有一番考量的,包括:
- 作者是Google的工程师,貌似很靠谱;
- 源码是Python,逼不得已了还能自己抢救抢救;
- 支持以服务化的方式来进行测试;
其中,服务化的测试方式是选择Dpxdt的重中之重!之前虽然在BackstopJS身上出师不利,但却发现了对视觉测试来说非常重要的关键点:视觉测试的最大价值在于图像对比,其它诸如浏览器驱动、页面操作、截图等工作,都不是也不应该是视觉测试的核心内容,它们应该由其它更擅长、更专注于此类活动的技术组件来负责,即术业有专攻,从自动化实施的层面考虑,尽量做到技术组件的功能内聚,这样,无论将来前端技术如何演进,也只需要更新相应的驱动组件即可,而图像对比作为视觉测试的核心,则不会受到影响。
想法很丰满,现实却很骨感。原生的Dpxdt,在实现上与BackstopJS有相似之处,比如,同样使用配置文件来管理测试案例,同样使用PhantomJS来驱动浏览器,但在架构上,Dpxdt实现了测试端和服务端的分离。在测试端,使用PhantomJS驱动浏览器进行页面操作和截图,然后将截取的图片上传到服务端,服务端使用ImageMagic进行图像对比,最后以一个Web应用的方式来管理和展示图像对比的结果。
很明显,直接使用Dpxdt是不可行的,因为绕不过PhantomJS的死结,但Dpxdt两端分离的架构设计,给移花接木带来了可能。为了在项目上进行视觉测试,只能对Dpxdt进行二次开发,包括:
- 封装Dpxdt暴露的API接口,重新构建可独立使用的客户端库;
- 解决一些Dpxdt在Windows环境下的兼容性问题,因为UI测试运行在Windows的EC2上;
- 加入了Ghost功能;
- 重建了部分服务的UI界面,原版的实在有些丑;
- Dpxdt在使用ImageMagic对比不同尺寸的图片时容易出错,使用compose进行了相应的预处理操作;
经过以上的修改,2017年5月,定制版的Dpxdt基本具备了相对稳定的图像对比功能。其带来的收益也是杠杠的,像素对比带来极高的测试敏感度,不会漏掉UI的任何异常,同时,去掉了UI测试中的几乎所有断言语句,大大的提高了测试的稳定性,这在那个Selenium的年代,是非常有价值的。
费劲心思修改出来的Dpxdt,肯定不会仅仅服务于一个项目。通过将Dpxdt部署到独立的EC2上(不得不说当年的客户真的是金主爸爸,EC2基本就是随意开),这个视觉测试服务在TW和该客户合作的最后两年里,先后服务过6个项目产品,完成了超过5000次的图像对比,给合作的客户团队也留下了非常深的印象。
自力更生
“如果让我再选择一次,我绝不会再用Dpxdt”,这是后来TW结束S项目后,正荷在一次QA社区的Catch Up上分享我们的视觉测试实践时,留下的让我记忆最深的话。原因很简单,除了我们当时整套自动化测试架构过于复杂之外,最让人难以忍受的就是Dpxdt的慢!贼慢!比贼还慢!其主要原因有二,一是Dpxdt将图片保存进了sqlite数据库文件,使得历史数据多了之后,数据库读写会非常慢。二是ImageMagic进行图片对比的速度实在是太慢了。久而久之,使用Dpxdt服务浏览图片和进行差异判定,就成了一件非常痛苦的事情。
在Dpxdt服务上近两年的视觉测试实践,让我更加确幸了一件事情:服务型的视觉测试方案,才是UI测试中图像对比的王道,原因我会在之后的技术篇中细聊。
时间来到2020年初,得知春节后将会入场的一个新加坡项目对Web UI有很高的要求(高到啥程度?后来的一次Sign Off,PO说:“你把F12打开,让我看看”,然后,“看吧,这个margin和设计差了2个px吧” ……想知道当时QA和BA的心情吗?),视觉测试自然就被我提上了日程。然而,Dpxdt毕竟已经是六七年前的作品,方案实现落后太多,继续改造已无益处。放眼此时的开源市场,提供图像对比的UI测试工具已经比比皆是了,光Cypress的插件就有一大堆。可是,服务型的解决方案却只有商业软件,比如大名鼎鼎的Applitools,可开源解决方案,一个都没有,这,就有些玩儿不动了。
人不折腾,天诛地灭,没有现成的,就自己撸一个呗!天意弄人,赶上新冠疫情,10天的闭门春节假期,还真就让我码了一个出来,取了个很俗气的名字叫Team Visual Test,简称TVT(是不是很囧)。TVT在考虑之初,就奔着跨团队和开源共享去做的,所以使用的都是非工作时间进行的开发和维护。
为了最大程度的提高视觉测试的速度,TVT在具体的图像对比技术上,选择了native-image-diff,虽然这是一个名不见经传的NodeJS图像对比工具,但它的实测速度是非常理想的,通过比较,native-image-diff的图像对比速度要比ImageMagick和OpenCV快得多。比如,下图是之前做的native-image-diff和ImageMagick在对比不通尺寸图片时的速度表现,native-image-diff的对比速度几乎是ImageMagick的三倍。
除了对图像对比技术的甄选,TVT还在项目上因地制宜的实现了一个图片文件共享的方案。我们使用容器化的方式来执行功能测试,然后将功能测试的容器和TVT服务的容器运行在相同的ECS Fargate实例的Task上,这样功能测试和TVT服务就能通过Bing Mounts的方式共享文件存储,从而实现了功能测试获取的截图,可以被TVT服务直接使用,从而避免了文件上传带来的耗时,使得整个视觉测试方案的速度可以更快。这样的实施方案,既有它的特性,比如项目上本来就使用Fargate实例,也有它的共性,比如即便不使用Fargate,随便一个Docker Swarm的环境,都能使用共享存储的方式实现类似的效果。
另外,不同于Dpxdt的单体服务,TVT在架构上是一个简单的微服务系统,将负责图片对比的图像对比服务和负责测试结果呈现的主服务分离开来。这样,如果将来有更强大的图片对比技术,只需要单独更新图像对比服务,就可以对TVT进行升级。 后来,在那个新加坡项目上,配上与Telegram的消息集成,TVT取得了非常好的效果。
然而,TVT毕竟只是一个春节假期赶工出来的成果,在服务部署、易用性、安全性、以及多客户端支持上都有不少欠缺。下项目后,又陆陆续续的花了一些时间来对TVT进行修修补补,于是打磨出了如今的开源视觉测试服务Micoo。关于Micoo,这里就不多言了,在稍后的技术篇中也许会提到部分内容,更多的细节,感兴趣的同学可以查看:
- Github主页
- 文档
写在最后
目前,在SEA,在没有任何推广的情况下,已经和正在使用Micoo(包括其前身TVT)的客户项目已有4个。所以,故事讲到这里,故事也还在发生。