Android UI自動化測試這塊一直是google忽略或者技術薄弱的地方,以至於他沒有提供一套完整的自動化測試框架。國內公司做UI自動化測試一般都借助於第三方測試框架如robotium,淘寶測試(TMTS),Robolectric等。但這些測試框架或多或少都存在一些跨應用,事件等待等不足,無法滿足UI自動化的所有要求。
Android4.0之后,google仿照微軟UIAutomation引入了UIAutomator測試框架,雖然是剛剛推出,各個細節還比較粗糙,但畢竟是Android原生的測試技術,再加上這套東西微軟已經使用了多年,已經是很成熟了, 所以相對第三方測試框架還是比較有優勢的。接觸到uiautomator之后我第一個想法就是可以仿照微軟POM/LFM將測試代碼寫得更加優雅。整個思路就是一個分層設計,控件的定義,和控件的操作分為兩層,而測試方法調用底下兩層,做為第三層。這么設計的好處是明顯的:較少代碼編寫量,並可以在團隊寫代碼中更加容易保持代碼風格;代碼易維護,改動任何一層代碼對其他層影響較小;可以針對Android系統泛濫的弊端針對不同的android系統或手機,生成一種通用庫,這樣很容易做手機多機適配運行;另外針對POM層,只要代碼格式設計完成,可以適當擴展Uiautomatorviewer以自動生成代碼(我擴展了右邊欄的TreeView,增加了雙擊自動生成代碼保存到剪切板里,這樣想要生成哪個控件的定義代碼,雙擊,粘貼一下就行了,非常方便)設計圖如下:
最終代碼是這個樣子的:
public void testSendPicByLocal() {
this.lfm.openApp();
this.lfm.goTabMessagesByXY(); Uia.hand.clickAndWaitForNewWindow( this.pom.messages.relativeLayoutChatSession(1), "點擊回話列表中第一個"); if (this.pom.chat.buttonHoldToRecord().exists()) { Uia.hand.click(this.pom.chat.buttonCancelRecord(), "如果錄音按鈕存在,則點擊關閉"); } Uia.hand.click(this.pom.chat.imageButtonPlus(), "點擊+"); for (int loop = 0; loop < 500; loop++) { if (!this.pom.chat.textViewPhotoWhenPlusClicked().exists()) { Uia.hand.click(this.pom.chat.imageButtonPlus(), "加號區域已經收回,點擊+再次彈出"); }
Uia.hand.click(this.pom.chat.textViewPhotoWhenPlusClicked(), "點擊Photo"); this.lib.lfm.photo.getPhotoFromAlbum(); // 調用公共類庫拍照方法,可根據不同手機實例化出不同對象 Uia.hand.click(this.pom.chat.imageViewImageSelected(), "點擊右下角對號,確認發送"); } }
那么針對uiautomator的代碼自動生成或者說錄制怎么做呢?
有一個取巧的辦法可以通過UiAutomator將頁面所有的控件保存到xml中,然后解析xml,生成POM層的代碼,雖然只能簡單生成POM層代碼,但這至少也減少了百分之三十的編碼量。
上述擴展uiautomatorviewer的方式比這種更加方便一點。
其實可以考慮使用AccessibilityService,監控用戶輸入,在onAccessibilityEvent(AccessibilityEvent)方法中解析Event,根據Event類型和其攜帶的控件屬性生成基於UIAutomator的測試代碼,然后將測試代碼拉出手機,放入事先建好的工程模板中編譯即可。
EventSource eventSource = praser.prase(event.toString()); // 設置篩選條件,選擇特定事件生成代碼。 if (Config.MatchedEvents.contains(eventSource.getEventType())) { generator.generateCode(template.getMethodStepSteam(eventSource)); }
這里不給出具體實現了。
這里提一下Uiautomator源碼的一個小bug,這個bug在最新版的4.2.2里已經修復,但你用uiautomator的時候還得注意一下:
uiautomator4.2.2版本一下引入uiautomator.jar時,凡是繼承自uicollection的方法UiObjectNotFoundException都沒有被拋出,google的工程師自己catch到給打印出來了,所以你的測試代碼沒辦法catch這個異常,
發現這個bug是在scroll一個feedlist時調用scrollforward的方法,結果總是有異常UiObjectNotFoundException,於是想測試代碼catch代碼段重新scrollforward一下,結果發現這個異常沒有拋出,去官網看wiki文檔,確實拋出有寫這個方法會拋出這個異常,也去翻看了uiautomator源碼,確認了,可就是找不到原因,后來靈光一閃,才確認了引入了4.1.2的uiautomator.jar包,這個包里源碼給處理了,google的工程師也會犯這么低級的錯誤。
在這里強烈鄙視那些轉載我博客,不表明出處的網站!!!!!