圖像對(duì)比在UI測(cè)試中的實(shí)踐-故事篇

這是一份在UI自動(dòng)化測(cè)試中使用圖像對(duì)比的實(shí)踐分享,分為故事篇技術(shù)篇兩部分,故事篇會(huì)首先回顧這幾年在視覺測(cè)試上的歷程,技術(shù)篇?jiǎng)t會(huì)介紹一些視覺測(cè)試上的技術(shù)總結(jié)。

六年前剛?cè)肼毜絋houghtWorks成都辦公室后,第一次參加QA社區(qū)的Catch Up,那時(shí)的我在新環(huán)境中還分不清誰是張三誰是李四。 會(huì)上,依稀記得有兩位貌似道行深厚的人物,就某個(gè)工具的使用反饋,詢問在座的眾生,現(xiàn)場(chǎng)一片寂靜。會(huì)后,回到組上,我好奇的 問了一下我們的TL(請(qǐng)?jiān)试S這里隱去TA的名字,不然我多半會(huì)被懟的)那是什么東西、我們有沒有使用,面對(duì)TL一番風(fēng)卷殘?jiān)频?介紹,作為剛剛從通訊行業(yè)跨入互聯(lián)網(wǎng)行業(yè)才三天的菜鳥,小的我真的是屁都沒聽懂,唯一聽明白并且記下來的就是“它還需要部署服務(wù)器,很難用”。

那個(gè)工具的名字叫做Viff,在后來很長(zhǎng)的一段時(shí)間內(nèi),我仍然不知道它是干嘛的,而這,就是我第一次和UI測(cè)試中的圖像對(duì)比的擦肩而過。

一不小心,摸到了圖像對(duì)比的大門

有時(shí)候,接觸某種技術(shù)、思考某種解決方案,靠的真不是大咖的演講,而就是那么點(diǎn)兒緣分和靈光一現(xiàn)。

時(shí)間來到2016年10月,某澳洲項(xiàng)目S。有一次,從王小禮的桌旁溜過,看她一副愁眉苦臉、生無可戀的樣子,就猜到多半有”戲”。本著有“戲”大家樂的心態(tài),隨便打聽了一下。 原來,她們組最近在給客戶做產(chǎn)品換膚。了解S項(xiàng)目的同學(xué)應(yīng)該都知道,客戶是一個(gè)集團(tuán)企業(yè),旗下有八九個(gè)品牌,所以通常一個(gè)產(chǎn)品就會(huì)有八九套UI。 而她們組在做的,就是給其中的多個(gè)品牌同時(shí)換膚。面對(duì)每天都在變化的UI,有時(shí)甚至是往復(fù)修改的CSS,別說寫自動(dòng)化測(cè)試了,每張卡的人肉檢查早都已經(jīng)應(yīng)接不暇了。

當(dāng)時(shí)的閑聊中,我提到的建議是,不知道有沒有什么工具能幫著檢查這類UI快速變更的頁面。下來再琢磨這個(gè)問題,經(jīng)過一番折騰,最終發(fā)現(xiàn)原來有種手段叫做“Visual Regression Testing”。

至于后來王小禮是怎么熬出她們的品牌換膚的,我就不知道咯,阿彌陀佛~

出師未捷身先死

既然摸到了圖像對(duì)比的大門,不進(jìn)去搗騰搗騰,就說不過去了是吧!當(dāng)時(shí),開源社區(qū)中的當(dāng)家花旦是BackstopJS,使用配置文件的方式來編寫和管理測(cè)試案例,完全沒有多大的上手難度,輸出的報(bào)告對(duì)于從來沒接觸過視覺測(cè)試的人來說,還是讓人眼前一亮。

當(dāng)時(shí),我們組的工作也是維護(hù)一個(gè)S項(xiàng)目下的某個(gè)前端應(yīng)用,所以在項(xiàng)目上通過BackstopJS來實(shí)踐視覺測(cè)試,便成了非常正兒八經(jīng)的選項(xiàng)。然而、可是、沒想到,僅僅用BackstopJS遍歷了兩三個(gè)頁面,測(cè)試就…崩了!是的,你沒看錯(cuò),崩了!經(jīng)過幾番調(diào)查,問題很快確定了:BackstopJS基于配置文件來組織測(cè)試案例,執(zhí)行測(cè)試時(shí)為了能夠做到Headless,使用的驅(qū)動(dòng)是PhantomJS(是的,就是那個(gè)作者半途跑路的PhantomJS),而PhantomJS原生不支持ES6。所以,解決辦法就是……沒有辦法!什么,你說BackstopJS支持Puppeteer?Puppeteer發(fā)布v1版本是在2018年的一月,至于BackstopJS完成使用Puppeteer替換PhantomJS,那更是猴年馬月的事情咯~

找準(zhǔn)目標(biāo),二次開發(fā)

剛剛開門就撞上了嘆息之墻,有夠背的,可即便沒能取得開門紅,圖像對(duì)比在UI測(cè)試中的巨大潛力,仍舊讓我深信這是一灘值得去趟的“渾水”。

換個(gè)工具繼續(xù)嘗試,接下來盯上的就是Dpxdt(我用辦公室阿姨擦桌子的抹布打賭,你第一次絕對(duì)不知道這玩意兒怎么念)。選擇Dpxdt是有一番考量的,包括:

  • 作者是Google的工程師,貌似很靠譜;
  • 源碼是Python,逼不得已了還能自己搶救搶救;
  • 支持以服務(wù)化的方式來進(jìn)行測(cè)試;

其中,服務(wù)化的測(cè)試方式是選擇Dpxdt的重中之重!之前雖然在BackstopJS身上出師不利,但卻發(fā)現(xiàn)了對(duì)視覺測(cè)試來說非常重要的關(guān)鍵點(diǎn):視覺測(cè)試的最大價(jià)值在于圖像對(duì)比,其它諸如瀏覽器驅(qū)動(dòng)、頁面操作、截圖等工作,都不是也不應(yīng)該是視覺測(cè)試的核心內(nèi)容,它們應(yīng)該由其它更擅長(zhǎng)、更專注于此類活動(dòng)的技術(shù)組件來負(fù)責(zé),即術(shù)業(yè)有專攻,從自動(dòng)化實(shí)施的層面考慮,盡量做到技術(shù)組件的功能內(nèi)聚,這樣,無論將來前端技術(shù)如何演進(jìn),也只需要更新相應(yīng)的驅(qū)動(dòng)組件即可,而圖像對(duì)比作為視覺測(cè)試的核心,則不會(huì)受到影響。

想法很豐滿,現(xiàn)實(shí)卻很骨感。原生的Dpxdt,在實(shí)現(xiàn)上與BackstopJS有相似之處,比如,同樣使用配置文件來管理測(cè)試案例,同樣使用PhantomJS來驅(qū)動(dòng)瀏覽器,但在架構(gòu)上,Dpxdt實(shí)現(xiàn)了測(cè)試端和服務(wù)端的分離。在測(cè)試端,使用PhantomJS驅(qū)動(dòng)瀏覽器進(jìn)行頁面操作和截圖,然后將截取的圖片上傳到服務(wù)端,服務(wù)端使用ImageMagic進(jìn)行圖像對(duì)比,最后以一個(gè)Web應(yīng)用的方式來管理和展示圖像對(duì)比的結(jié)果。

很明顯,直接使用Dpxdt是不可行的,因?yàn)槔@不過PhantomJS的死結(jié),但Dpxdt兩端分離的架構(gòu)設(shè)計(jì),給移花接木帶來了可能。為了在項(xiàng)目上進(jìn)行視覺測(cè)試,只能對(duì)Dpxdt進(jìn)行二次開發(fā),包括:

  • 封裝Dpxdt暴露的API接口,重新構(gòu)建可獨(dú)立使用的客戶端庫;
  • 解決一些Dpxdt在Windows環(huán)境下的兼容性問題,因?yàn)閁I測(cè)試運(yùn)行在Windows的EC2上;
  • 加入了Ghost功能;
  • 重建了部分服務(wù)的UI界面,原版的實(shí)在有些丑;
  • Dpxdt在使用ImageMagic對(duì)比不同尺寸的圖片時(shí)容易出錯(cuò),使用compose進(jìn)行了相應(yīng)的預(yù)處理操作;

經(jīng)過以上的修改,2017年5月,定制版的Dpxdt基本具備了相對(duì)穩(wěn)定的圖像對(duì)比功能。其帶來的收益也是杠杠的,像素對(duì)比帶來極高的測(cè)試敏感度,不會(huì)漏掉UI的任何異常,同時(shí),去掉了UI測(cè)試中的幾乎所有斷言語句,大大的提高了測(cè)試的穩(wěn)定性,這在那個(gè)Selenium的年代,是非常有價(jià)值的。

費(fèi)勁心思修改出來的Dpxdt,肯定不會(huì)僅僅服務(wù)于一個(gè)項(xiàng)目。通過將Dpxdt部署到獨(dú)立的EC2上(不得不說當(dāng)年的客戶真的是金主爸爸,EC2基本就是隨意開),這個(gè)視覺測(cè)試服務(wù)在TW和該客戶合作的最后兩年里,先后服務(wù)過6個(gè)項(xiàng)目產(chǎn)品,完成了超過5000次的圖像對(duì)比,給合作的客戶團(tuán)隊(duì)也留下了非常深的印象。

自力更生

“如果讓我再選擇一次,我絕不會(huì)再用Dpxdt”,這是后來TW結(jié)束S項(xiàng)目后,正荷在一次QA社區(qū)的Catch Up上分享我們的視覺測(cè)試實(shí)踐時(shí),留下的讓我記憶最深的話。原因很簡(jiǎn)單,除了我們當(dāng)時(shí)整套自動(dòng)化測(cè)試架構(gòu)過于復(fù)雜之外,最讓人難以忍受的就是Dpxdt的慢!賊慢!比賊還慢!其主要原因有二,一是Dpxdt將圖片保存進(jìn)了sqlite數(shù)據(jù)庫文件,使得歷史數(shù)據(jù)多了之后,數(shù)據(jù)庫讀寫會(huì)非常慢。二是ImageMagic進(jìn)行圖片對(duì)比的速度實(shí)在是太慢了。久而久之,使用Dpxdt服務(wù)瀏覽圖片和進(jìn)行差異判定,就成了一件非常痛苦的事情。

在Dpxdt服務(wù)上近兩年的視覺測(cè)試實(shí)踐,讓我更加確幸了一件事情:服務(wù)型的視覺測(cè)試方案,才是UI測(cè)試中圖像對(duì)比的王道,原因我會(huì)在之后的技術(shù)篇中細(xì)聊。

時(shí)間來到2020年初,得知春節(jié)后將會(huì)入場(chǎng)的一個(gè)新加坡項(xiàng)目對(duì)Web UI有很高的要求(高到啥程度?后來的一次Sign Off,PO說:“你把F12打開,讓我看看”,然后,“看吧,這個(gè)margin和設(shè)計(jì)差了2個(gè)px吧” ……想知道當(dāng)時(shí)QA和BA的心情嗎?),視覺測(cè)試自然就被我提上了日程。然而,Dpxdt畢竟已經(jīng)是六七年前的作品,方案實(shí)現(xiàn)落后太多,繼續(xù)改造已無益處。放眼此時(shí)的開源市場(chǎng),提供圖像對(duì)比的UI測(cè)試工具已經(jīng)比比皆是了,光Cypress的插件就有一大堆??墒?,服務(wù)型的解決方案卻只有商業(yè)軟件,比如大名鼎鼎的Applitools,可開源解決方案,一個(gè)都沒有,這,就有些玩兒不動(dòng)了。

人不折騰,天誅地滅,沒有現(xiàn)成的,就自己擼一個(gè)唄!天意弄人,趕上新冠疫情,10天的閉門春節(jié)假期,還真就讓我碼了一個(gè)出來,取了個(gè)很俗氣的名字叫Team Visual Test,簡(jiǎn)稱TVT(是不是很囧)。TVT在考慮之初,就奔著跨團(tuán)隊(duì)和開源共享去做的,所以使用的都是非工作時(shí)間進(jìn)行的開發(fā)和維護(hù)。

為了最大程度的提高視覺測(cè)試的速度,TVT在具體的圖像對(duì)比技術(shù)上,選擇了native-image-diff,雖然這是一個(gè)名不見經(jīng)傳的NodeJS圖像對(duì)比工具,但它的實(shí)測(cè)速度是非常理想的,通過比較,native-image-diff的圖像對(duì)比速度要比ImageMagick和OpenCV快得多。比如,下圖是之前做的native-image-diff和ImageMagick在對(duì)比不通尺寸圖片時(shí)的速度表現(xiàn),native-image-diff的對(duì)比速度幾乎是ImageMagick的三倍。

除了對(duì)圖像對(duì)比技術(shù)的甄選,TVT還在項(xiàng)目上因地制宜的實(shí)現(xiàn)了一個(gè)圖片文件共享的方案。我們使用容器化的方式來執(zhí)行功能測(cè)試,然后將功能測(cè)試的容器和TVT服務(wù)的容器運(yùn)行在相同的ECS Fargate實(shí)例的Task上,這樣功能測(cè)試和TVT服務(wù)就能通過Bing Mounts的方式共享文件存儲(chǔ),從而實(shí)現(xiàn)了功能測(cè)試獲取的截圖,可以被TVT服務(wù)直接使用,從而避免了文件上傳帶來的耗時(shí),使得整個(gè)視覺測(cè)試方案的速度可以更快。這樣的實(shí)施方案,既有它的特性,比如項(xiàng)目上本來就使用Fargate實(shí)例,也有它的共性,比如即便不使用Fargate,隨便一個(gè)Docker Swarm的環(huán)境,都能使用共享存儲(chǔ)的方式實(shí)現(xiàn)類似的效果。

另外,不同于Dpxdt的單體服務(wù),TVT在架構(gòu)上是一個(gè)簡(jiǎn)單的微服務(wù)系統(tǒng),將負(fù)責(zé)圖片對(duì)比的圖像對(duì)比服務(wù)和負(fù)責(zé)測(cè)試結(jié)果呈現(xiàn)的主服務(wù)分離開來。這樣,如果將來有更強(qiáng)大的圖片對(duì)比技術(shù),只需要單獨(dú)更新圖像對(duì)比服務(wù),就可以對(duì)TVT進(jìn)行升級(jí)。 后來,在那個(gè)新加坡項(xiàng)目上,配上與Telegram的消息集成,TVT取得了非常好的效果。

然而,TVT畢竟只是一個(gè)春節(jié)假期趕工出來的成果,在服務(wù)部署、易用性、安全性、以及多客戶端支持上都有不少欠缺。下項(xiàng)目后,又陸陸續(xù)續(xù)的花了一些時(shí)間來對(duì)TVT進(jìn)行修修補(bǔ)補(bǔ),于是打磨出了如今的開源視覺測(cè)試服務(wù)Micoo。關(guān)于Micoo,這里就不多言了,在稍后的技術(shù)篇中也許會(huì)提到部分內(nèi)容,更多的細(xì)節(jié),感興趣的同學(xué)可以查看:

寫在最后

目前,在SEA,在沒有任何推廣的情況下,已經(jīng)和正在使用Micoo(包括其前身TVT)的客戶項(xiàng)目已有4個(gè)。所以,故事講到這里,故事也還在發(fā)生。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容