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

什么是UI測(cè)試中的圖像對(duì)比

首先嘮叨一下什么是UI測(cè)試,顧名思義,UI測(cè)試就是泛指對(duì)UI的測(cè)試工作。UI又分圖形化UI和非圖形化UI,即Graphic User Interface和Non-Graphic User Interface,常見的GUI主要有Web頁面、移動(dòng)應(yīng)用界面、桌面應(yīng)用界面、以及嵌入式設(shè)備的圖形界面等。而非圖形化用戶界面則主要是各種命令行終端程序,比如docker,xcrun,kubectl等。我們這里討論的UI,限定在GUI的范疇內(nèi),嚴(yán)謹(jǐn)?shù)耐瑢W(xué)就別挑刺兒了喲。

對(duì)UI的測(cè)試,又可以分為功能性的測(cè)試和非功能性的測(cè)試。功能測(cè)試主要關(guān)注應(yīng)用的業(yè)務(wù)實(shí)現(xiàn),非功能測(cè)試則關(guān)注業(yè)務(wù)實(shí)現(xiàn)之外的其它方面,比如安全性、性能、易用性、兼容性等。那圖像對(duì)比在UI測(cè)試中扮演怎樣的角色呢?

我們先來看看下面這個(gè),白宮官網(wǎng)的頁腳:

然后,同樣是白宮官網(wǎng)的頁腳:

你能一眼看出它們的區(qū)別嗎?比較困難是吧,那如果再給你提供下面這個(gè)呢:

是不是瞬間就能發(fā)現(xiàn)它們之間的差異了。然后我們來仔細(xì)品味一下它倆的差異,最上面白宮圖標(biāo)的粗細(xì)變化,我們可以認(rèn)為是截圖噪音而忽略不計(jì),那么左下角的單詞錯(cuò)誤,應(yīng)該是文本的錯(cuò)別字,不涉及功能,屬于用戶體驗(yàn)的問題。而右下角缺失YouTube圖標(biāo),則是實(shí)打?qū)嵉墓δ苋毕?。所以,圖像對(duì)比在UI測(cè)試中并不是某種具體的專項(xiàng)測(cè)試,而是一種輔助手段,幫助我們方便快捷地定位各種可以被其捕獲的、泛化的UI異常。

當(dāng)然,稱呼“UI測(cè)試中的圖像對(duì)比”實(shí)在太拗口,所以平常交流中,更多的是使用它的英文及其譯名,即Visual Testing和"視覺測(cè)試"。

圖像對(duì)比在UI測(cè)試中的價(jià)值

在UI測(cè)試、特別是UI自動(dòng)化測(cè)試中應(yīng)用圖像對(duì)比能夠帶來非常直觀的價(jià)值,它們包括:

  • 替代自動(dòng)化測(cè)試中的斷言語句,提高自動(dòng)化測(cè)試的維護(hù)效率和測(cè)試執(zhí)行的穩(wěn)定性;
  • 實(shí)現(xiàn)對(duì)圖表等繪圖元素的回歸測(cè)試;
  • 能夠捕獲意料之外的UI異常;
  • 更加適應(yīng)敏捷項(xiàng)目中UI的頻繁變更;
  • 更好的描述UI的變化;

替代自動(dòng)化測(cè)試中的斷言語句,提高自動(dòng)化測(cè)試的維護(hù)效率和測(cè)試執(zhí)行的穩(wěn)定性

長久以來,UI自動(dòng)化測(cè)試中的測(cè)試期望都是通過斷言語句來實(shí)現(xiàn)的,比如

cy.get('div.main-content-article-wrapper > article > div > div:nth-child(34)').should('contain', 'Price')

期望一個(gè)特定位置的元素內(nèi)容應(yīng)該包含'Price',但如果頁面重構(gòu),變成了

cy.get('div.main-content-article-wrapper > article > div:nth-child(34)').should('contain', 'Price')

那我們的自動(dòng)化測(cè)試就會(huì)失敗。相信凡是寫過UI自動(dòng)化測(cè)試的同學(xué),都遇到過類似的問題,即我們對(duì)特定元素的斷言,都依賴其相應(yīng)的元素定位器,如果UI界面發(fā)生了結(jié)構(gòu)性的調(diào)整(這些調(diào)整有時(shí)對(duì)用戶還是無感的),已有的元素定位器很容易受影響。特別是當(dāng)需要斷言的頁面元素很多時(shí),這樣的重構(gòu)往往是UI自動(dòng)化測(cè)試的噩夢(mèng)。

而圖像對(duì)比完全不需要使用斷言語句來校驗(yàn)頁面元素的特征,從而可以大幅簡化使用斷言語句的工作量,并且極大的提高執(zhí)行自動(dòng)化測(cè)試的穩(wěn)定性,特別是對(duì)于那些內(nèi)容豐富的頁面,無論是校驗(yàn)的工作量、還是校驗(yàn)的穩(wěn)定性,都遠(yuǎn)遠(yuǎn)優(yōu)于傳統(tǒng)的斷言語句。

實(shí)現(xiàn)對(duì)圖表等繪圖元素的回歸測(cè)試

另一個(gè)“長久以來”,對(duì)繪圖元素的回歸校驗(yàn)始終是UI自動(dòng)化測(cè)試中的痛點(diǎn)。前端獲取后端提供的數(shù)據(jù),使用Javascript和CSS動(dòng)態(tài)地將其繪制在UI界面上,面對(duì)這些圈圈點(diǎn)點(diǎn)、條條框框,傳統(tǒng)的UI自動(dòng)化測(cè)試,無論是爺爺輩兒的Selenium、還是高富帥的Cypress,都只能望圖心嘆,而唯獨(dú)圖像對(duì)比可以“以圖攻圖”。這對(duì)于那些需要展示圖形報(bào)表的應(yīng)用,比如大數(shù)據(jù)前端,是非常有益的。

能夠捕獲意料之外的UI異常

這是我對(duì)圖像對(duì)比在UI自動(dòng)化測(cè)試中最贊賞的價(jià)值!
傳統(tǒng)的、基于斷言的UI自動(dòng)化測(cè)試,只能做到“期望A在B有C的表現(xiàn)”,即只能期望某事按照希望的方式發(fā)生,可捕獲的異常僅僅是“期望的事件沒有發(fā)生”。而在此基礎(chǔ)上,使用圖像對(duì)比的UI自動(dòng)化測(cè)試還能期望“不希望的事情不要發(fā)生”,即對(duì)于那些無中生有、完全意料之外的UI異常也能進(jìn)行捕獲。

曾經(jīng)的一個(gè)客戶項(xiàng)目,項(xiàng)目的產(chǎn)品是一個(gè)微前端,上線后會(huì)被嵌入到上一層的頁面當(dāng)中。某次,我們的圖像對(duì)比測(cè)試在UAT測(cè)試環(huán)境中意外的發(fā)現(xiàn),自己頁面的某個(gè)widget居然被替換成了廣告,整個(gè)團(tuán)隊(duì)大吃一驚,因?yàn)槲覀兏揪蜎]干過“這活兒”。經(jīng)過幾番技術(shù)調(diào)研和需求確認(rèn),最終才知道這是我們被要求引入的某個(gè)上層頁面的Javascript“偷偷修改”的,而且是正確的業(yè)務(wù)需求。當(dāng)時(shí)的那個(gè)廣告很顯眼,容易被人肉捕捉到,但如果是某個(gè)不起眼的小改動(dòng)呢,常規(guī)的自動(dòng)化測(cè)試方式都束手無策,即便是單元級(jí)別的snapshot測(cè)試也做不到,因?yàn)樗窃诓渴鸷蟛艜?huì)出現(xiàn)的"問題"。

更加適應(yīng)敏捷項(xiàng)目中UI的頻繁變更

對(duì)于UI自動(dòng)化測(cè)試,有一條金句:“只在UI穩(wěn)定后再進(jìn)行自動(dòng)化回歸測(cè)試”。而對(duì)于敏捷項(xiàng)目來說,不好意思,UI穩(wěn)定的那一天多半就是上線的那一天。UI的頻繁變更,對(duì)于自動(dòng)化測(cè)試來說,主要考驗(yàn)的是咋們的體力和(忍)耐力,看你有沒有足夠的體力、三天兩頭的跟著UI變更來修改你的測(cè)試案例,以及面對(duì)一言不合就紅紅火火的pipeline、你能憋著多久不拍桌罵娘。而使用圖像對(duì)比的UI自動(dòng)化測(cè)試,雖然不能完全解除你發(fā)飆的風(fēng)險(xiǎn),但得益于對(duì)斷言需求的大量降低、以及圖像對(duì)比服務(wù)的一鍵rebase,至少能讓你每天少滅亡5000單位的腦細(xì)胞(大誤),阿彌陀佛,善哉善哉!

更好的描述UI的變化

這一點(diǎn),我坦白,很主觀。當(dāng)UI出現(xiàn)變化、需要跟Dev或BA去確認(rèn)時(shí),相較于查看日志或報(bào)告中的描述語言,我更喜歡眼見為實(shí)和看圖說話。當(dāng)然,隨著自動(dòng)失敗截圖和視頻錄制功能的豐富,像Cypress、Detox這樣的測(cè)試工具,在這方面也做得很不錯(cuò)。

值得強(qiáng)調(diào)的是,盡管再高效和準(zhǔn)確,圖像對(duì)比也只是UI測(cè)試中的一種輔助手段,單獨(dú)依靠圖像對(duì)比是無法獨(dú)立完成整個(gè)UI自動(dòng)化測(cè)試的,我們?nèi)匀恍枰猄elenium、Cypress那樣的測(cè)試工具和框架來對(duì)瀏覽器和頁面進(jìn)行基本的操作,比如打開一個(gè)網(wǎng)站、填寫某個(gè)表單、點(diǎn)擊一些按鈕等等。所以,圖像對(duì)比是高效UI自動(dòng)化測(cè)試的助推器,但并不是全部。

圖像對(duì)比在UI測(cè)試中的自動(dòng)化實(shí)施模式

圖像對(duì)比是一種高效的測(cè)試手段,理念非常清晰、簡單。在具體的UI自動(dòng)化測(cè)試中,圖像對(duì)比的實(shí)施基本都遵循相同的模式,如下圖:

其中:

  • 初始化baseline的步驟一定是手動(dòng)的,而且也是必須的;
  • 圖像對(duì)比和差異報(bào)告是自動(dòng)完成的;
  • 差異判定目前基本都是手動(dòng)完成的,自動(dòng)化能做的僅僅是發(fā)現(xiàn)差異,但差異并不等于缺陷,對(duì)于設(shè)計(jì)變更、新的需求、以及既有缺陷修復(fù)帶來的UI差異,都是業(yè)務(wù)的正確表現(xiàn);
  • 顯而易見,更新baseline的步驟也一定是手動(dòng)的,當(dāng)報(bào)告的差異屬于正確的業(yè)務(wù)表現(xiàn)時(shí),就應(yīng)該將當(dāng)前版本的UI截圖設(shè)置為最新的baseline,否則后續(xù)測(cè)試會(huì)繼續(xù)沿用之前的baseline;

當(dāng)前的自動(dòng)化圖像對(duì)比方案

如今的視覺測(cè)試工具已經(jīng)非常多了,這里羅列了目前市面上絕大多數(shù)的相關(guān)工具。他們的主要區(qū)別在于:

  • 獲取途徑,開源 vs 商業(yè);
  • 實(shí)現(xiàn)方案,工具&框架型 vs 服務(wù)型;
  • 測(cè)試流程,交互式 vs 批處理式;

商業(yè)和開源的區(qū)別不必多說。開源軟件絕大多數(shù)都是本地工具或框架型的實(shí)現(xiàn)方案,服務(wù)型的實(shí)現(xiàn)方案主要集中在各種商業(yè)服務(wù)中,比如領(lǐng)頭羊的Applitools就是遠(yuǎn)程服務(wù)型解決方案,非常類似于BroswerStack。

無論是工具型的實(shí)現(xiàn)方案(以下簡稱視覺測(cè)試工具)、還是服務(wù)型的實(shí)現(xiàn)方案(以下簡稱視覺測(cè)試服務(wù)),它們都遵循上面提到的自動(dòng)化實(shí)施模式,UI操作和截圖都發(fā)生在執(zhí)行功能測(cè)試的本地環(huán)境。兩者的關(guān)鍵區(qū)別在于圖片的對(duì)比和Baseline的管理,一個(gè)是發(fā)生在本地環(huán)境,一個(gè)是發(fā)生在遠(yuǎn)端服務(wù)內(nèi)。具體來講,當(dāng)測(cè)試獲取到UI的截圖后,視覺測(cè)試工具會(huì)將截圖與本地的Baseline進(jìn)行比較,得出差異報(bào)告,需要更新的Baseline也保存在本地環(huán)境。而使用視覺測(cè)試服務(wù)時(shí),截圖會(huì)被上傳到遠(yuǎn)端的視覺測(cè)試服務(wù),在服務(wù)端完成圖片對(duì)比,當(dāng)需要更新Baseline時(shí),也是在服務(wù)端保存新的Baseline。

本地視覺測(cè)試工具 vs 遠(yuǎn)端視覺測(cè)試服務(wù)

大量的實(shí)踐告訴我們,UI測(cè)試中使用遠(yuǎn)端視覺測(cè)試服務(wù)要遠(yuǎn)遠(yuǎn)優(yōu)于使用本地視覺測(cè)試工具,主要體現(xiàn)在:

Baseline的管理和共享

視覺測(cè)試工具將Baseline保存在本地環(huán)境,如果是一直個(gè)人使用,并沒有多大問題,但如果要多人共享,麻煩就來了。以網(wǎng)頁應(yīng)用為例,圖像都是來自于瀏覽器對(duì)應(yīng)用界面渲染的結(jié)果,如果兩個(gè)人的操作系統(tǒng)、瀏覽器版本、顯示器分辨率等不同,即便面對(duì)相同UI,也可能得出不一致的圖像。A、B分別在各自的電腦上、使用各自的Baseline通過了視覺測(cè)試,但最終發(fā)現(xiàn)兩人的Baseline其實(shí)并不相同。當(dāng)然,這里的差異更多屬于噪音,但對(duì)于像素級(jí)別的圖像對(duì)比來說,這樣的噪音是難以忽略的。

所以,對(duì)于本地視覺測(cè)試工具來說,一種變通的使用方式就是將Baseline保存在代碼的版本管理系統(tǒng)內(nèi),然后讓組員共享相同的Baseline。該方式可行,但使用代碼管理系統(tǒng)來存儲(chǔ)二進(jìn)制的圖片文件、而且還是經(jīng)常變動(dòng)的圖片文件,其本身并不是一種好的工程實(shí)踐。

而視覺測(cè)試服務(wù)則完全不存在這樣的問題,因?yàn)锽aseline都是保存在服務(wù)端的,共享使用完全沒有任何問題。

更新Baseline的難易程度

圖像對(duì)比替代語句斷言的優(yōu)勢(shì)之一就是能更好的適應(yīng)被測(cè)UI的頻繁變更,這就要求圖像對(duì)比能夠更好的頻繁更新Baseline。視覺測(cè)試工具一般使用單獨(dú)的命令來更新Baseline,集成到持續(xù)集成環(huán)境后,則通常需要設(shè)定一個(gè)單獨(dú)的Job來執(zhí)行該命令。如果使用了版本管理系統(tǒng)來存儲(chǔ)Baseline,那還得將本地的Baseline上傳回版本管理系統(tǒng)才能完成整個(gè)操作。

而視覺測(cè)試服務(wù)則相對(duì)要簡單得多,往往只需要點(diǎn)擊服務(wù)頁面上的一個(gè)按鈕就全搞定了。

歷史版本的可追溯性

本地視覺測(cè)試工具通常都有一個(gè)硬傷,它們只會(huì)保存當(dāng)前的Baseline,當(dāng)需要更新Baseline時(shí),會(huì)用新的Baseline覆蓋掉之前的Baseline,整個(gè)環(huán)境中永遠(yuǎn)只會(huì)有最新的Baseline。然而對(duì)于Baseline來說,除了使用當(dāng)前的Baseline來對(duì)比最新截圖之外,有時(shí)候我們還希望能夠?yàn)g覽歷史的Baseline,因?yàn)锽aseline的歷史版本,其本身就是對(duì)被測(cè)應(yīng)用的迭代描述,甚至是各個(gè)里程碑的圖像記錄,是有其工程意義的。

顯然,本地視覺測(cè)試工具無法提供這樣的可追溯性,而視覺測(cè)試服務(wù)通常都會(huì)保留全部的圖片歷史,所以能夠更好的滿足這一特性。

基準(zhǔn)版本的回滾

舉個(gè)例子,Dev提交部署了版本v005,告訴QA這是新的實(shí)現(xiàn),QA在測(cè)試“確認(rèn)”后,將圖像對(duì)比的Baseline更新為v005版本,稍后,BA提出v005版本的“需求”是錯(cuò)誤的,此時(shí),Dev需要把代碼回滾到v004版本,那問題來了,如果是本地的視覺測(cè)試工具,v004版本的Baseline已經(jīng)被v005版本給替換了,缺少v004版本的Baseline,QA只能人肉確保版本回滾的正確性了。

所以,具備基準(zhǔn)版本的回滾功能,可以在必要的時(shí)候,更好的實(shí)現(xiàn)視覺測(cè)試,而只有視覺測(cè)試服務(wù)才具備回滾基準(zhǔn)版本的能力。

當(dāng)然,視覺測(cè)試服務(wù)也不是無懈可擊的。相較于本地的視覺測(cè)試工具,使用視覺測(cè)試服務(wù)的高成本是顯而易見的,第三方商業(yè)服務(wù)的費(fèi)用是實(shí)實(shí)在在的Money,即便使用開源的視覺測(cè)試服務(wù),在服務(wù)部署上,對(duì)團(tuán)隊(duì)也多多少少有一些DevOps的技能要求。如果為了更好的使用效果,將開源視覺測(cè)試服務(wù)部署到云端,也會(huì)產(chǎn)生相應(yīng)的計(jì)算資源費(fèi)用。

交互式的圖像對(duì)比 vs 批處理式的圖像對(duì)比

無論是本地的視覺測(cè)試工具,還是遠(yuǎn)端的視覺測(cè)試服務(wù),在測(cè)試流程上,一般都可以分為交互式和批處理式兩種。

交互式的測(cè)試流程一般如下圖所示。在該流程中,圖像對(duì)比的工作的全部嵌入到功能測(cè)試的步驟當(dāng)中,每一步視覺測(cè)試都會(huì)將被測(cè)圖像傳遞給圖像對(duì)比的工具或服務(wù),然后等待工具或服務(wù)返回圖像對(duì)比的結(jié)果,就類似平常使用的斷言語句。

批處理式的測(cè)試流程一般如下圖所示。該流程的特點(diǎn)是視覺測(cè)試的步驟和功能測(cè)試的步驟完全分離,功能測(cè)試僅僅需要將圖像保存到指定的路徑下,待整個(gè)功能測(cè)試都結(jié)束后,再將所有的圖像、一次性全部傳遞給視覺測(cè)試工具或服務(wù)進(jìn)行對(duì)比。

交互式視覺測(cè)試和批處理式視覺測(cè)試在流程上的不同,造成了兩者在呈現(xiàn)測(cè)試結(jié)果上的差異。對(duì)于交互式視覺測(cè)試,每一步測(cè)試都會(huì)即時(shí)獲取到對(duì)比結(jié)果,從而使視覺測(cè)試的結(jié)果直接體現(xiàn)在功能測(cè)試的結(jié)得當(dāng)中。而批處理式視覺測(cè)試,其步驟和功能測(cè)試完全隔離,測(cè)試結(jié)果由視覺測(cè)試工具或服務(wù)單獨(dú)呈現(xiàn)。

至于視覺測(cè)試結(jié)果要不要和功能測(cè)試結(jié)果綁定在一起,并沒有什么公理可依,大家盡可按照自己的實(shí)際需求進(jìn)行取舍。只不過就個(gè)人而言,我更傾向于將二者分離,因?yàn)閲?yán)格來講,視覺測(cè)試給出的自動(dòng)化結(jié)果,其本身僅僅是圖像對(duì)比的結(jié)果,而圖像對(duì)比結(jié)果并不等于測(cè)試結(jié)果。我們說過,圖像對(duì)比只是UI測(cè)試的一種輔助手段,幫助我們從UI差異中去快速發(fā)現(xiàn)問題,圖像對(duì)比僅僅揭示差異,而差異并不等于缺陷。所以,自動(dòng)化視覺測(cè)試給出的結(jié)果不應(yīng)該被直接用來表征UI測(cè)試的結(jié)果,否則它會(huì)大大的降低功能測(cè)試結(jié)果的可信度,失去可信度的測(cè)試是沒有有價(jià)值的。

關(guān)于Micoo的一點(diǎn)啰嗦

基于以上的考慮,Micoo選擇了服務(wù)型的實(shí)現(xiàn)方式和批處理式的測(cè)試流程。Micoo的理念是聚焦最核心的圖像對(duì)比工作,僅此。所以從功能上來說,Micoo僅僅是一個(gè)圖像對(duì)比服務(wù),它將操作UI應(yīng)用和截取圖片的工作,全權(quán)留給了功能測(cè)試去完成。這樣貌似偷了個(gè)大懶,但實(shí)則拓寬了實(shí)施視覺測(cè)試的對(duì)象。理論上,任何UI應(yīng)用,無論是Web應(yīng)用、移動(dòng)應(yīng)用、桌面應(yīng)用,只要它能被自動(dòng)化測(cè)試并且截圖,就能借由Micoo完成視覺測(cè)試。而將來,無論這些被測(cè)應(yīng)用如何更新演進(jìn),只要其相應(yīng)的自動(dòng)化功能測(cè)試手段能同步跟進(jìn),Micoo就永遠(yuǎn)能為它們提供視覺測(cè)試的解決方案,這樣就從根本上避開了當(dāng)年BackstopJS在PhantomJS身上踩下的天坑(如果對(duì)這段內(nèi)容感到很突兀,可以參閱之前的故事篇獲取一些上下文)。

視覺測(cè)試在CI中的實(shí)施方式

目前,基于視覺測(cè)試與功能測(cè)試的相互關(guān)系,它們?cè)贑I中的構(gòu)建方式主要有四種,分別為:獨(dú)立型、混合型、同步型、以及異步型的構(gòu)建方式。

獨(dú)立型的CI構(gòu)建方式

下圖是獨(dú)立型的自動(dòng)化測(cè)試在CI中的構(gòu)建方式,其特征是功能測(cè)試和視覺測(cè)試完全獨(dú)立,互不依賴也互不影響。BackstopJS這類的工具就通常使用獨(dú)立型的方式構(gòu)建到CI當(dāng)中。

混合型的CI構(gòu)建方式

然后是混合型的構(gòu)建方式,其特點(diǎn)是視覺測(cè)試的步驟完全跟功能測(cè)試綁定在一起,即使用一套自動(dòng)化測(cè)試實(shí)現(xiàn)功能和視覺的雙重校驗(yàn)。不用多想,這就是標(biāo)準(zhǔn)的交互式視覺測(cè)試方案在CI中的構(gòu)建方式,比如Applitools。

同步型的CI構(gòu)建方式

同步型的構(gòu)建方式中,視覺測(cè)試依賴前置功能測(cè)試的產(chǎn)出,即先由功能測(cè)試獲取到UI截圖,再將截圖交給視覺測(cè)試進(jìn)行圖像對(duì)比。其后續(xù)步驟,比如部署UAT環(huán)境,需要視覺測(cè)試通過才能進(jìn)行。

異步型的CI構(gòu)建方式

異步型的構(gòu)建方式與同步型的構(gòu)建方式有相似之處,其視覺測(cè)試都要依賴功能測(cè)試的截圖,不同的是,其后續(xù)步驟,比如部署UAT環(huán)境,可以不依賴視覺測(cè)試的結(jié)果,只要功能測(cè)試通過就可以自動(dòng)部署。

實(shí)踐中,不同CI構(gòu)建方式的選擇沒有太明顯的傾向性,主要還是根據(jù)所使用的視覺測(cè)試方案來制定,比如,獨(dú)立的視覺測(cè)試工具多選擇獨(dú)立型的構(gòu)建方式,交互式的視覺測(cè)試方案肯定是混合型的構(gòu)建方式,而批處理式的視覺測(cè)試方案則可以在同步型和異步型構(gòu)建方式中靈活選擇。

視覺測(cè)試的有益實(shí)踐

最后,作為對(duì)大家耐心閱讀至此的感謝,特此奉上一些實(shí)施視覺測(cè)試時(shí)的有益實(shí)踐,純干貨:

什么樣的項(xiàng)目適合引入視覺測(cè)試?

視覺測(cè)試的實(shí)質(zhì)是UI的一種自動(dòng)化回歸測(cè)試。在考慮是否引入視覺測(cè)試之前,先要確定是否需要建立UI的自動(dòng)化回歸測(cè)試。視覺測(cè)試對(duì)UI回歸測(cè)試的幫助,概括起來就四個(gè)字:減負(fù)增效。通過大大降低測(cè)試斷言的使用來減小自動(dòng)化測(cè)試的編寫和維護(hù)負(fù)擔(dān),同時(shí)提高測(cè)試的效能和穩(wěn)定性。由此可見,真正適合引入視覺測(cè)試的項(xiàng)目,一般來說都是那些UI內(nèi)容復(fù)雜、同時(shí)迭代變更又比較頻繁的項(xiàng)目。此外,那些對(duì)UI呈現(xiàn)效果要求較高的項(xiàng)目,比如客戶全是像素眼的PO,那么視覺測(cè)試也是不錯(cuò)的輔助手段。

什么樣的項(xiàng)目不適合使用視覺測(cè)試?

要明確的是,只要能被自動(dòng)化測(cè)試的UI,技術(shù)上都能進(jìn)行視覺測(cè)試,但視覺測(cè)試是否對(duì)任何UI項(xiàng)目都適用,卻是不一定的:

  • 如果項(xiàng)目連UI自動(dòng)化測(cè)試都不需要,那自然就更談不上視覺測(cè)試了;
  • 過于簡單的UI,有基本的自動(dòng)化功能測(cè)試就足夠了,沒必要再加上視覺測(cè)試,畢竟視覺測(cè)試也是有"成本"的;
  • 過于復(fù)雜的UI,注意,這里的復(fù)雜不是指UI內(nèi)容的復(fù)雜,而是指UI操作的復(fù)雜。比如,一個(gè)需要進(jìn)行滿篇填寫內(nèi)容來提交表單的UI,在其功能測(cè)試的步驟中,就幾乎已經(jīng)遍歷完了所有的界面元素,再對(duì)它進(jìn)行視覺測(cè)試,并不能降低多少元素定位的成本。那么對(duì)這樣的UI引入視覺測(cè)試,收益是不大的;
  • 可以使用圖像對(duì)比測(cè)試視頻播放器,但視覺測(cè)試一個(gè)主要內(nèi)嵌視頻播放器的網(wǎng)頁或移動(dòng)端UI,一般來說不是一個(gè)好想法;

想玩兒服務(wù)型的視覺測(cè)試,但沒有資源怎么辦?

"沒有就要唄,不然還能咋地?" 當(dāng)然,這是半句玩笑話。這里真正想說的是,長久以來,在項(xiàng)目的計(jì)算資源分配上,測(cè)試一直是二等公民。當(dāng)我們計(jì)算啟動(dòng)項(xiàng)目需要使用的資源費(fèi)用時(shí),比如購買哪些云服務(wù)、需要多少計(jì)算實(shí)例、需要怎樣的數(shù)據(jù)庫或緩存等,通常只會(huì)考慮開發(fā)的需求,而不會(huì)也不需要顧及測(cè)試的需求。歷史上,這是正確的,隨便找一個(gè)CI的Agent,就能把我們常用的測(cè)試框架給打發(fā)了。然而,伴隨著容器技術(shù)助推傳統(tǒng)測(cè)試工具、框架向測(cè)試服務(wù)的轉(zhuǎn)型,計(jì)算資源也開始成為自動(dòng)化測(cè)試策略中需要規(guī)劃的要素。這一點(diǎn),對(duì)早就完成測(cè)試平臺(tái)化、測(cè)試服務(wù)化的大廠來說,不是問題,但對(duì)玩兒敏捷的TW團(tuán)隊(duì)來說,卻還是一個(gè)新的思考。所以,言歸正傳,想在項(xiàng)目中使用視覺測(cè)試服務(wù),那么就盡量在項(xiàng)目早期階段,將此需求體現(xiàn)到測(cè)試策略當(dāng)中,呈現(xiàn)給團(tuán)隊(duì)和客戶,從而提前準(zhǔn)備和規(guī)劃。

視覺測(cè)試中如何解決UI對(duì)象動(dòng)態(tài)變化的問題?

來了來了,這個(gè)凡是做視覺測(cè)試就一定繞不過去的問題:

  • 頁面中有視頻,怎么辦?
  • 圖片slideshow會(huì)自動(dòng)滾動(dòng),怎么辦?
  • 顯示的時(shí)間每秒鐘都不一樣,怎么辦?
  • 那個(gè)ID每次請(qǐng)求都不一樣,怎么辦?

這些UI中動(dòng)態(tài)變化的元素,對(duì)實(shí)施圖像對(duì)比是非常大的阻礙。當(dāng)然,解決辦法也是有的,比如:

  • 掉包,UI顯示的數(shù)據(jù)大多來自后端(或遠(yuǎn)端),有些數(shù)據(jù)是不恒定的,比如一些每次請(qǐng)求后端都會(huì)變化的信息,如動(dòng)態(tài)ID、數(shù)字簽名、特征碼等等,又或者一些自己團(tuán)隊(duì)不可控的信息,比如一個(gè)顯示價(jià)格的UI,自己團(tuán)隊(duì)只負(fù)責(zé)在UI中將價(jià)格顯示出來,具體的數(shù)字則受后端或后臺(tái)的控制而可變。對(duì)于這樣的場(chǎng)景,我們可以使用服務(wù)虛擬化的技術(shù)來替換掉相應(yīng)的后端,從而使用恒定不變的數(shù)據(jù)來保障視覺測(cè)試的可行。
  • 作弊,使用虛擬服務(wù)來掉包測(cè)試數(shù)據(jù)的成本是很高的,另外,有些前端顯示的內(nèi)容并不是從后端獲取的,而是前端自己生成的隨機(jī)數(shù)據(jù),那么對(duì)于這些無論是來自后端還是前端的動(dòng)態(tài)數(shù)據(jù),另一種"廉價(jià)"的處理方式,就是在功能測(cè)試中將它們直接修改成固定的假數(shù)據(jù)。比如,在Web的測(cè)試中,如果需要進(jìn)行視覺測(cè)試的當(dāng)前頁面包含有動(dòng)態(tài)數(shù)據(jù),我們可以使用Javascript直接修改DOM的內(nèi)容,將某個(gè)本應(yīng)該是動(dòng)態(tài)計(jì)算或獲取的值替換成固定的內(nèi)容,然后再對(duì)當(dāng)前頁面截圖對(duì)比。
  • 抹黑,至于那些頻繁變化的視頻或者圖片,我們甚至可以來得更狠,直接修改DOM將其修改成相同大小的色塊,從而保障視覺測(cè)試的可行。除了抹黑,還有摳圖的操作,即直接刪除視頻或者圖片的DOM節(jié)點(diǎn),但一般不建議,因?yàn)榇蠖鄶?shù)情況下,刪除DOM節(jié)點(diǎn)可能會(huì)影響到頁面的布局展示。
  • 后門,有時(shí)為了實(shí)現(xiàn)視覺測(cè)試,但又不想修改DOM結(jié)構(gòu),就可以讓Dev在測(cè)試環(huán)境中設(shè)置一些功能或者特效開關(guān),比如,當(dāng)開關(guān)關(guān)閉時(shí),圖片slideshow只顯示第一張圖片而不自動(dòng)切換其它圖片,從而使視覺測(cè)試成為可能。一旦使用的功能開關(guān),就增加了UI的實(shí)現(xiàn)復(fù)雜度,測(cè)試也需要相應(yīng)的關(guān)注這些功能開關(guān)不會(huì)影響到產(chǎn)品環(huán)境的表現(xiàn)。
  • 罷工,如果上面這些都解決不了動(dòng)態(tài)數(shù)據(jù)的問題,又或者能解決但成本太高,那么就應(yīng)該考慮放棄進(jìn)行視覺測(cè)試。合理適當(dāng)?shù)氖謩?dòng)測(cè)試有時(shí)才是性價(jià)比最高的解決方案。

盡管我們有這些解決動(dòng)態(tài)元素問題的方法,但顯而易見的是,它們要么成本高昂,要么對(duì)被測(cè)DOM修修改改,帶來收益的同時(shí)也引入了風(fēng)險(xiǎn)。所以對(duì)頁面動(dòng)態(tài)元素的評(píng)估,也是在策略上是否引入視覺測(cè)試的重要參考。

如何解決視覺測(cè)試中截圖環(huán)境不一致的問題?

初次接觸視覺測(cè)試的同學(xué),通常關(guān)注的是截誰的圖、怎么截圖,而只有在視覺測(cè)試中栽過跟頭的人,才會(huì)更關(guān)注在哪兒去截圖。比如,對(duì)Web應(yīng)用來說,哪怕使用相同版本的Chrome和Puppeteer,在MacOS和Windows上截的圖,可能是有差異的。更別說,在你的MacBook上截取的圖像,和CI的Agent機(jī)器上截取的圖像,差異可能更大。那么該如何避免這種差異呢?目前來說,最合適的方法,是在容器中進(jìn)行截圖。比如,將你需要的Chrome或者Chromium版本,打到特定的容器里,而后無論在本地環(huán)境還是CI環(huán)境,都將自動(dòng)化測(cè)試運(yùn)行在這個(gè)相同的容器內(nèi)部,那么你得到的截圖就一定是相同的。

當(dāng)然,如果你使用Applitools服務(wù),那么也不會(huì)存在截圖環(huán)境不一致的問題,因?yàn)锳pplitools是將DOM片段上傳到服務(wù)器上,在服務(wù)端使用指定的瀏覽器進(jìn)行渲染和截圖。

如何設(shè)定差異閾值最合適?

不使用差異閾值最合適!使用差異閾值的目的,通常都是在一定程度內(nèi)容忍對(duì)比差異,比如設(shè)置3%的差異閾值,就可以使視覺測(cè)試在自動(dòng)報(bào)告對(duì)比結(jié)果時(shí),對(duì)于圖片差異區(qū)域低于整張圖像的3%的測(cè)試,視為對(duì)比結(jié)果一致而通過測(cè)試。差異閾值主要用在一些容易產(chǎn)生截圖噪音、或者對(duì)比經(jīng)常出現(xiàn)一些小范圍且無意義的差異的測(cè)試中,用來提高測(cè)試的魯棒性。從測(cè)試方案設(shè)計(jì)的角度來說,差異閾值是很不錯(cuò)的想法,但真正的項(xiàng)目實(shí)踐中,卻并不是那么回事。原因很簡單,差異閾值提高測(cè)試魯棒性的代價(jià)是犧牲圖像對(duì)比的敏感性。基于像素對(duì)比的視覺測(cè)試,高敏感性是其最大的優(yōu)勢(shì),同時(shí)也是建立其測(cè)試結(jié)果可信度的根基。使用了差異閾值的視覺測(cè)試,其對(duì)比結(jié)果就從完全可信變成了部分可信,哪怕其可信閾達(dá)到99.99%,只要不是100%的完全可信,其測(cè)試結(jié)果就會(huì)受到質(zhì)疑,任何存在可質(zhì)疑結(jié)果的自動(dòng)化測(cè)試都是無益的。具體來說,設(shè)置1%的差異閾值,測(cè)試就會(huì)自動(dòng)容忍1%的圖像差異,然而,沒人能確保這1%的差異永遠(yuǎn)都發(fā)生在那些期望的、無關(guān)緊要的邊角料區(qū)域,如果下一次這1%的差異正好就發(fā)生在一些關(guān)鍵的地方,比如價(jià)格的單位符號(hào),那么測(cè)試遺漏的結(jié)果就可能很嚴(yán)重。另外,差異閾值是絕對(duì)的,但差異區(qū)域卻是相對(duì)的。請(qǐng)問,3%的差異和1%的差異誰大?答案是不確定,比如,200x400圖像的3%的差異,和1920x1080圖像的1%的差異,后者的差異明顯比前者要大得多。所以,請(qǐng)一定慎用差異閾值。

視覺測(cè)試掛得太頻繁,怎么辦?

恭喜你,咋要的就是這效果!圖像對(duì)比作為UI回歸測(cè)試的一種輔助手段,當(dāng)它頻繁"掛掉"的時(shí)候,說明UI正在經(jīng)歷快速的變更,這其實(shí)并不是什么壞事。傳統(tǒng)的功能性自動(dòng)化測(cè)試,面對(duì)UI的快速變更,測(cè)試斷言會(huì)頻繁失效,給自動(dòng)化測(cè)試的維護(hù)工作帶來極大的工作量,搞得我們心煩意亂,這時(shí)往往需要評(píng)估繼續(xù)進(jìn)行自動(dòng)化測(cè)試的ROI。而圖像對(duì)比測(cè)試在更新baseline上的優(yōu)勢(shì),極大的減少甚至部分消除了這些維護(hù)工作,讓我們可以泰然面對(duì)頻繁的測(cè)試失敗。所以,不同的測(cè)試方式帶來不同的測(cè)試體驗(yàn),同時(shí)也改變著我們面對(duì)測(cè)試失敗的心態(tài)。

最后

UI測(cè)試中的圖像對(duì)比并不是什么技術(shù)含量很高的工作,但它卻一定是效能很高的手段,把簡單的事情做到精致、做到極致,也能得到非同尋常的收獲。

?著作權(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),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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