2017/06/21自動化的坑

摘抄自:http://tmq.qq.com/2017/03/uizidonghua/

小心!做UI自動化一定要跨過這些坑

一、引子

UI自動化,在移動互聯(lián)網(wǎng)時代的今天,一直都是在各大測試測試社區(qū)最為火爆的一個TOPIC。甚至在測試同行面前一提起自動化,大家就會自然而然的問:“恩,你們是用的什么框架?appium?還是robotium?”

其實在筆者看來,UI自動化是一個ROI較低的測試項(ROI即return?on?investment,中文意思是投資回報率)。但UI自動化相比接口自動化、白盒測試等,它更貼近手工業(yè)務測試行為。對于剛起步測試左移、效率提升的團隊來說,是最迅速的切入點,也是廣大黑盒tester,提升自身技術能力的起跑線。筆者接觸UI自動化一年多,兼顧業(yè)務測試的同時斷斷續(xù)續(xù)地投入,曾經(jīng)無數(shù)次的想放棄:“才剛寫完用例,怎么開發(fā)大哥又改了UI了?”

“維護這些破用例的時間,都夠我手工測三遍了,真的有意義么?”

“測試框架自己有bug,我改用例也沒用啊……”

“我調(diào)試的時候這個用例還是通的,放到daily里面跑就不通,到底怎么回事嘛!”

“adb怎么這么不穩(wěn)定啊,老是斷?。?!”

“怎么跑著跑著就crash了,到底是被測應用有問題,還是測試代碼有問題啊?”

“明明界面上有這個元素,怎么就是查不到呢?”

“這破手機,能不能別老是系統(tǒng)彈框……”

“這手機真是渣,adb screencap截個圖,居然要三分鐘才返回!”

“這些控件都沒有id,沒有text,層級還三天兩頭改,要我怎么查……”

“查了這么多論壇,怎么就沒有人遇到過類似的問題呢?”

……

這些問題讓筆者一度懷疑,UI自動化這個TOPIC,是不是根本沒用,只是tester為了漲薪,或者為了擺脫重復無聊的手工業(yè)務測試,而YY出來自我欺騙的。

二、問題分類及目標明確

筆者將以上所有的問題簡單分成三類:設計類、環(huán)境類、細節(jié)類。一個好的設計模式,能夠避免一部分問題;一套好的環(huán)境,可以讓我們從乏味的維護工作中解脫;精益求精的細節(jié),讓測試用例更加可靠穩(wěn)定。

圖一UI自動化常見問題

填掉這三類坑,基本上就獲得了一套低成本高產(chǎn)出、少量維護、穩(wěn)定可靠的UI自動化用例集。

三、設計類問題分析與解決

“才剛寫完用例,怎么開發(fā)大哥又改了UI了?”

“測試框架自己有bug,我改用例也沒用啊……”這類問題,我們需要從根上治。UI自動化開發(fā),也應該是嚴謹?shù)拈_發(fā)工作,它也需要設計模式,也是磨刀不誤砍柴工。這里的設計,主要包括選工具、框架分層等。很多前輩都分析過UI自動化各類工具的優(yōu)缺點,對工具選用筆者不再贅述。主要依托uiautomator來介紹下筆者認為比較巧妙的用例框架設計。

1、優(yōu)化測試代碼框架

無論你選擇appium、uiautomator、robotium還是espresso,剛?cè)腴T時,看到的sample應該大致都是這樣的。

圖二 uiautomator和espresso邏輯樣例

問題在哪里?這些sample過于簡單,都只教了我們UI自動化三元素:怎么查找元素、怎么操作元素、怎么校驗結(jié)果。如果我們按照大多數(shù)分享帖或GitHub sample來寫作自己的case。最后這種沒有任何設計模式的框架,肯定會面臨重構(gòu)。拿上面的espresso來說:

1.假如action_save這個id開發(fā)改了,而你的用例集中,有30個步驟用例到了這個id,一個個去改,是不是要瘋?

2.不厭其煩的重復寫onView(withXX(xxx)).perform(click())這一長串,你不煩?

筆者是如何做的呢?

分層設計和PageObjects模式。這兩個方法,基本解決了筆者遇到的圖一中所有的設計類問題。

圖三 框架設計建議

按照圖三進行分層設計后,得到如圖四的測試代碼包。

圖四 分層后的用例框架

PageObjects模式發(fā)源于selenium社區(qū),它的目的是減少重復代碼,當開發(fā)修改UI時,測試只需在有限的位置修改代碼。如果大家想深入了解PageObjects,請參照如下wiki:

(https://github.com/SeleniumHQ/selenium/wiki/PageObjects

http://blog.csdn.net/kittyboy0001/article/details/25219053)。

我們來看一下,現(xiàn)在手管首頁Page包中的代碼和頁面。

圖五 手管首頁Page層部分代碼

回憶一下上面的google提供的sample,再對比引入分層設計和PO模式前后的代碼,點擊圖五中的一鍵加速:

圖六 引入PO前后代碼對比

帶來的好處,當然不僅僅是業(yè)務用例代碼更清爽。

1、通過將查找和操作封裝到基礎層中,這部分代碼就具體業(yè)務無關了,即使拿到其他產(chǎn)品中也可以復用;

2、通過page層的分離,所有的與業(yè)務相關的id,text等都被限定在了page包中,哪怕開發(fā)改了UI,修改page包特定的頁面中對應的元素就好了。

3、對page包進行合理的業(yè)務拆分,比如將手管分成 MainPage(主頁),SoftwareManagerPage(軟件管理頁),WiFiManagerPage(WiFi管理頁)等,在開發(fā)改了某個具體業(yè)務的界面后,測試能夠迅速知道測試代碼需要改哪里。

2、兼容資源混淆的測試代碼

除了整個框架的設計,有時候一些小問題也可以經(jīng)過巧妙設計。比如資源混淆的問題。

圖七 資源混淆

如圖七,在手機管家的發(fā)布包中,用uiautomatorviewer dump下來發(fā)現(xiàn),一鍵優(yōu)化的button,其resource-id是o3,但其實開發(fā)coding時,定義的id顯然不會用這種沒有任何字面意義的代號,它在混淆之前叫optimize_button。

純黑盒的UI自動化,也許你會摒棄optimize_button,直接寫o3,但這樣顯然不夠科學,既帶來了嚴重的代碼可讀性問題,同時一旦版本迭代,混淆變了,o3也許就變成了o4。或者你會讓開發(fā)給你測試的包,不要混淆,但如果想用UI自動化測試已發(fā)布的apk呢?

解決該問題,也得從PageObjects說起。回到圖五中OPTIMIZE_BTN的定義,這個靜態(tài)變量并未在page中初始化,只有一個@FindBy的注解。其實,在框架層驅(qū)動測試開始前,框架會先調(diào)用如下圖八所示的setAllField來初始化所有的page頁面。

1、如果被測應用未混淆資源,該方法只是將@FindBy中的值賦值給Field。

2、如果被測應用已混淆資源,該方法則會從mObfuscationMap(未貼出全部代碼,實際是解析一個開發(fā)提供的混淆表,以原始id為key,混淆id為value的HashMap)中讀出對應的id對應關系,將混淆后的id賦值給Field。

圖八 Page層動態(tài)初始化

四、環(huán)境類問題分析與解決

“adb怎么這么不穩(wěn)定啊,老是斷?。。 薄懊髅鹘缑嫔嫌羞@個元素,怎么就是查不到呢?”“這破手機,能不能別老是系統(tǒng)彈框……”

“這手機真是渣,adb screencap截個圖,居然要三分鐘才返回!”……

引子中提到的這些問題,根據(jù)經(jīng)驗,多半你的環(huán)境執(zhí)行環(huán)境還不夠穩(wěn)定。

1、ADB相關問題

已知的ADB不穩(wěn)定原因如:電壓不穩(wěn),各類手機助手的干擾,系統(tǒng)版本與ADB版本不匹配、ADB crash等等。如果我們迎難而上,去重寫ADB,投入將無限擴大。所以建議主要的解決方案,還是盡量規(guī)避。

1)、選用可靠硬件規(guī)避電壓不穩(wěn)定。github上的STF項目組有過成熟的經(jīng)驗,選用性能更優(yōu)的USB分接器,電壓和可靠性會有更穩(wěn)定的表現(xiàn)。(附上鏈接,wiki Recommended hardware一節(jié)中有不同硬件詳細的性能對比:https://github.com/openstf/stf)。

2)、屏蔽各類手機助手的干擾。91助手、豌豆莢等,基本都在adb上做了二次開發(fā),它們會與原生adb間有兼容性問題。建議直接使用Linux/MAC系統(tǒng)作為運行環(huán)境以屏蔽這類干擾。

3)、降低用例在執(zhí)行過程中對環(huán)境的依賴。Appium這類自動化工具,每一個測試步驟都需要PC端的appium server和測試手機端的bootstrap交互消息。測試過程中只要USB連接不穩(wěn)定,都會導致整個測試套的失敗。所以筆者認為,使用更原生的uiautomator會是更好的選擇;同時,測試過程中的日志、截圖等,也盡量在測試手機上做持久化。

2、彈框問題的解決

權限彈框,是手管UI自動化中的一個大坑。如下圖,是測試手管過程中,在華為手機上遇到的部分權限彈框。這些彈框,并不會用例每次執(zhí)行都彈出,不同廠商的彈出框也不一致。顯然點擊彈框的邏輯,寫在case邏輯中,只會導致自動化變得更復雜更不穩(wěn)定。

圖九 各類權限彈框

uiautomator的watcher,能夠完全實現(xiàn)點擊彈框和用例邏輯的解耦。當前筆者的實現(xiàn)邏輯是,監(jiān)聽彈框上的某個控件,當該控件出現(xiàn)時,執(zhí)行action來點擊掉其中的取消或確定按鈕。這樣,用例就只需關注業(yè)務邏輯,而任何時候的彈框,都由watcher來自動點擊。如下圖中,checkForCondition關注條件,action是操作。

圖十 查找型Watcher

將所有的watcher分不同的手機廠商進行注冊后,再調(diào)用runWatchers(),然后再執(zhí)行用例。該方法可以在@BeforeClass中或者RunListener的testRunStarted中調(diào)用。當然,如果某個用例不想某個具體的彈框被watcher點擊掉,也可以調(diào)用removeWatcher()反注冊。

圖十一 注冊監(jiān)聽器

Watcher并不能解決所有的彈框問題。例如,在開啟WiFi的場景中,由于WifiManager的setWifiEnabled和UI上的彈框點擊是同步的(意思是調(diào)用了setWifiEnabled之后,如果界面上不點允許,該方法是不會返回的),使用上面的watcher方式并不會點擊WiFi權限申請的允許。這時,就需要用到線程方式來解決(如下圖十二),調(diào)用setWifiEnabled前,先啟動一個線程等待彈框彈出。

圖十二 多線程方式點掉彈框

五、細節(jié)類問題分析與解決

“我調(diào)試的時候這個用例還是通的,放到daily里面跑就不通,到底怎么回事嘛!”

出現(xiàn)上述問題,多半是因為我們的用例細節(jié)不夠嚴謹。這類問題,往往決定著我們自動化用例集,是不是能從90%的case通過率,提升到100%。

1、順序邏輯的用例

自動化相比手工,它只會關注code告訴它的驗證點,所以選擇邏輯在用例中應該是禁用的。如下圖十三中右側(cè)的case,如果用例執(zhí)行到if中,也許else流程中存在BUG,反之亦然。此時考慮拆分用例,左側(cè)才是理想的用例邏輯。

圖十三 用例邏輯

另外,寫作case時,一定要牢記,只有我們告知程序要assert,它才會去assert。查找,操作,斷言,UI自動化三要素缺一不可。

2、解耦的用例

在testng中,會提供dependsOnMethods注解,似乎在鼓勵寫作用例時,使用用例間依賴。但筆者認為,用例間的依賴,會帶來不必要的維護成本。只有高度解耦的用例邏輯,才能夠更加健壯的支撐用例執(zhí)行順序調(diào)整、用例增刪、出現(xiàn)異常場景后,A用例失敗不會導致B用例也失敗。

3、優(yōu)化等待

有時候會遇到以下場景,雖然原生的自動化工具提供了等待元素可見的方法,但使用起來,還是無法真正等到元素可見。針對這個問題,如下圖的waitCondition方法是一個不錯的方案,它相對于thread.sleep來說,更節(jié)省時間。

圖十四 反復等待方法

4、不用絕對坐標點擊

絕對坐標點擊,在不同尺寸屏幕上無法兼容。

第一方案應該是,推動開發(fā)對需要用到的控件添加ID或Accessibility。但根據(jù)經(jīng)驗還是會有一些場景需要用到坐標點擊:

1、考慮投入產(chǎn)出比,為所有控件添加id的成本過高;

2、動態(tài)布局添加的ID都一樣;

3、存在非xml布局的界面(代碼中直接布局)。

這時,筆者依然不建議mDevice.click(100,200)這樣的坐標點擊。有以下兩種值得一試的方案。

1、找到相鄰控件坐標,計算當前控件的絕對坐標。如下圖十四,uiautomatorviewer中點擊右上角警告小三角,會得到有一些元素(黃色控件),是可能無法找到的。而使用相對坐標就是說,我們可以獲取它相鄰控件的坐標,然后減去或加上一個比較小的px值,再點擊計算后的坐標即可。

圖十五相對坐標

2、使用屏幕尺寸計算相對位置。在測試開始,將屏幕尺寸存下來,使用百分比的方式計算得到需要點擊的位置。如下代碼,點擊【50%屏幕寬度,80%屏幕高度】的位置。

CODE: mDevice.click( screenWidth/2 , screenHeight*80/100 )。

六、總結(jié)

UI自動化測試是一門學起來很簡單,用起來很麻煩的測試技術。

想要入門,兩周就可以了解清楚uiautomator或espresso這類工具。UI自動化,無非就是查找元素、操作元素或設備、驗證結(jié)果。這三個步驟循環(huán)多次,就是一個用例。但要用好,并產(chǎn)出能效,需要走的路其實很長。由于篇幅限制和知識有限,這里不可能把所有的問題一一列出。對于所有這些問題,無非兩個思路:一是繞過,二是解決。1、選一個盡量簡化,盡量底層的工具(uiautomator或espresso),從根上繞過一些工具會存在的問題;

2、采用良好的設計模式,讓自己的框架更穩(wěn)定,生命周期更長,維護成本更低;

3、明知道會耗費很多時間精力,收效卻很小的環(huán)境問題,盡量繞過;

4、優(yōu)化用例邏輯和細節(jié),使之穩(wěn)定可靠,更能說服別人相信自動化的測試結(jié)論。

七、最后

不知您是否也曾在UI自動化過程中遇到過難以解決的問題呢?歡迎大家留言討論。也祝愿大家在UI自動化的道路上越走越順!

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

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,176評論 25 708
  • 前言 如果有測試大佬發(fā)現(xiàn)內(nèi)容不對,歡迎指正,我會及時修改。 大多數(shù)的iOS App(沒有持續(xù)集成)迭代流程是這樣的...
    默默_David閱讀 1,778評論 0 4
  • 作者:Ringoyan,騰訊測試開發(fā)工程師。先后為植物大戰(zhàn)僵尸Online,糖果傳奇等游戲擔任測試經(jīng)理,其負責的“...
    飯盒閱讀 2,887評論 2 41
  • 前言 準備打算用一個月時間學習Swift,包括語法跟實戰(zhàn),順便寫寫博客記錄學習里程,方便日后重拾。 目錄 Play...
    紹清_shao閱讀 498評論 2 1
  • 題記:煙籠寒水月籠沙,夜泊秦淮近酒家。商女不知亡國恨,隔江猶唱后庭花。 我習慣枕著古卷入睡 醉夢中,或許泛舟湖上 ...
    柳四公子閱讀 292評論 0 0

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