Android自動化基於UIAutomator的實現及程式碼生成
Android UI自動化測試這塊一直是google忽略或者技術薄弱的地方,以至於他沒有提供一套完整的自動化測試框架。國內公司做UI自動化測試一般都藉助於第三方測試框架如robotium,淘寶測試(TMTS),Robolectric等。但這些測試框架或多或少都存在一些跨應用,事件等待等不足,無法滿足UI自動化的所有要求。
Android4.0之後,google仿照微軟UIAutomation引入了UIAutomator測試框架,雖然是剛剛推出,各個細節還比較粗糙,但畢竟是Android原生的測試技術,再加上這套東西微軟已經使用了多年,已經是很成熟了, 所以相對第三方測試框架還是比較有優勢的。接觸到uiautomator之後我第一個想法就是可以仿照微軟POM/LFM將測試程式碼寫得更加優雅。整個思路就是一個分層設計,控制元件的定義,和控制元件的操作分為兩層,而測試方法呼叫底下兩層,做為第三層。這麼設計的好處是明顯的:較少程式碼編寫量,並可以在團隊寫程式碼中更加容易保持程式碼風格;程式碼易維護,改動任何一層程式碼對其他層影響較小;可以針對Android系統氾濫的弊端針對不同的android系統或手機,生成一種通用庫,這樣很容易做手機多機適配執行;另外針對POM層,只要程式碼格式設計完成,可以適當擴充套件Uiautomatorviewer以自動生成程式碼(我擴充套件了右邊欄的TreeView,增加了雙擊自動生成程式碼儲存到剪下板裡,這樣想要生成哪個控制元件的定義程式碼,雙擊,貼上一下就行了,非常方便)設計圖如下:
最終程式碼是這個樣子的:
![複製程式碼](http://common.cnblogs.com/images/copycode.gif)
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(), "點選右下角對號,確認傳送"); } }
![複製程式碼](http://common.cnblogs.com/images/copycode.gif)
那麼針對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的工程師也會犯這麼低階的錯誤。
轉載來源:http://www.cnblogs.com/salomon/archive/2013/03/27/2984050.html