Android UI自動化測試最佳實踐
轉載地址:http://qa.baidu.com/blog/?p=985
一. 概述
Android系統測試和Web的測試類似,有兩類自動化的方式:錄製回放與基於頁面元素操作的手工開發。由於錄製回放在長期維護與程式碼重用方面存在問題,這裡主要的方式還是後者,這也是Web UI自動化的主流。
在Web自動化測試中有一個比較好的實踐是採用PageFactory的方式(參考文章:http://chon.techliminal.com/page_object/#/intro),Selenium2對其進行了良好的封裝與支援,關於這種模式的具有以下幾點好處:
※減少重複程式碼,將頁面狀態的改變和遷移封裝在頁面物件之中;
※UI的變動只會影響到相應頁面物件而不會影響到上層的test case;
※能夠在不同的test case中重用頁面物件。
Android應用程式的測試也極其類似,每一個Activity可以看成是一個Page Object,可以將Activity中的控制元件以及操作封裝在Page Object之中。為了能夠表述清楚測試的分層和測試方法,先展現一個例項,然後討論對Robotium的改寫與封裝。
二. 例項
以移動鳳巢的登陸頁面為例,LoginActivity中有三個控制元件:使用者名稱EditText,密碼EditText,以及提交按鈕Button,如下圖一,當登陸成功後進入MainActivity,如下圖二:
對於Test Case的組織如下圖,page包中每個Activity都對應一個ActivityPage,test包中的用例可以重用不同的ActivityPage:
其中LoginActivityPage的內容如下,先不用關心@FindBy這種註解,它不是Robotium自帶的,主要作用是能夠在執行時將控制元件注入到ActivityPage之中,類中主要包括需要操作的Android控制元件以及動作:
對於Test case的形式如下,實際內容為對不同ActivityPage的操作,這樣當頁面的控制元件變化時只需要改動ActivityPage而不用動測試邏輯了,而且可讀性更強。
三. Robotium框架改寫與封裝
通過以上示例可以看到為了更好地支援這種測試模式需要對Robotium進行一些封裝和改動,現階段Robotium存在以下問題:
Api不是面向物件的,用起來比較變扭,比如當你獲得了一個EditText的物件,不能editText.putText(“abc”)而必須solo. enterText(editText,”abc”)
※不能很好地支援PageFactory模式,使用時需要寫額外的程式碼
※由於UI測試存在偶爾的不穩定因素,需要有失敗重試和截圖機制
為了改良以上問題,需要對Robotium進行擴充套件和封裝,業界一個比較好的實踐是借用WebDriver的整套規範,對於web元素和android元素他們存在較多的共用操作
:
對於Matching列是我們需要改造實現的,對於大部分Android控制元件,比如EditText、Button等都可以實現以上操作,如果不存在或不支援的方法則丟擲UnsupportedOperationException代替。
PageFactory的實現可以參照org.openqa.selenium.support.PageFactory,主要通過反射獲取Test Case中的Page元素,然後將Activity中的控制元件延遲注入到Page中(延遲注入的目的是為了防止在頁面還未跳轉的時候找不到控制元件,比如只有登入成功後跳轉到主頁才能找到“首頁”按鍵,一開始執行的時候是沒有“首頁”按鍵的)。對於Android控制元件的定位可以引入如下@FindBy註解從三方面定位:控制元件的id、控制元件中出現的某段文字、控制元件的索引(要先指定控制元件的種類,比如第三個EditText控制元件)
接下來是重試和截圖機制,可以通過改造ActivityInstrumentationTestCase2中的runTest()方法來實現,簡略的實現如下:
這樣只要Test Case方法上打上@Failover(times = 3,screenshot = true)註解則表明只有連續三次執行失敗才認為是失敗的,同時會給失敗場景截圖。
最後,為了減輕ActivityPage的程式碼編寫工作我們可以通過解析Android源工程layout中的xml來自動生成程式碼,這樣一旦UI頁面變更我們只需要重新執行生成程式碼的程式就OK了。