標籤:
近期因工作需要,分析了一些Android的測試架構,在這也分享下整理完的資料。
Android測試大致分三大塊:
- 代碼層測試
- 使用者操作類比,功能測試
- 安裝部署及穩定性測試
代碼層測試
對於一般java代碼,採用傳統的Junit測試,開發人員通常會編寫重要介面和函數的白盒測試代碼,不做過多討論。
但因Android的特殊運行機制(Dalvik虛擬機器),其中存在Application、Activity、Service等特殊組件,而這些組件都涉及到生命週期管理的問題。
為了對這些組件進行測試,Google提供了一套針對性的測試架構,AndroidTestFramework
官方教程連結 http://developer.android.com/training/testing.html
官方api http://developer.android.com/reference/android/test/package-summary.html
其中最為常用的就是針對Activity的測試,即ActivityInstrumentationTestCase2<T>類。
繼承該類後可通過getActivity()方法擷取Activity的一個mock對象,從而實現各種介面元素的測試。代碼如下
public class LoginActivityTest extends ActivityInstrumentationTestCase2<LoginActivity> { LoginActivityTest mActivity; Button btnLogin; public LoginActivityTest(){ super(LoginActivity.class);//必須實現super(testclass) } @Override protected void setUp() throws Exception { super.setUp(); mActivity = getActivity(); btnLogin = mActivity.findViewById(R.id.btnLogin); } public void testGetActivity(){ assertNotNull("can‘t get LoginActivity" , mActivity); assertNotNull("can‘t get loginButton" , btnLogin); }}
需要注意的是,測試代碼啟動並執行線程並不是UI線程。因此如果需要對UI元素進行setText或是click之類的操作,需要通過getActivity().runOnUiThread(action)方法執行。代碼如下
getActivity().runOnUiThread(new Runnable() { @Override public void run() { btnLogin.click(); } }); 使用者操作類比,功能測試
雖然AndroidTestFramework可以協助我們完成各種介面的測試。但是,這些代碼的編寫非常繁瑣。而且在大部分情況下,我們需要的是一個連貫性的,在多個Activity之間存在跳轉的商務程序測試。這種測試比較接近傳統的白盒測試,只針對可見的UI元素進行操作,類比使用者的行為來完成測試。
Google同樣為我們提供了一套專門針對UI元素的測試方案,具體可見http://developer.android.com/tools/testing/testing_ui.html
可是Google的這套UI架構仍然不是很友好。為此,我尋找了一些相對成熟的測試架構來協助我們。經過一系列分析比較和實際代碼測試,在這推薦採用Robotium開源架構做為今後一段時間內的主要業務測試架構。
Robotium介紹
Robotium是一款國外的Android自動化測試架構,主要針對Android平台的應用進行黑盒自動化測試,它提供了類比各種手勢操作(點擊、長按、滑動等)、尋找和斷言機制的API,能夠對各種控制項進行操作。Robotium結合Android官方提供的測試架構達到對應用程式進行自動化的測試。另外,Robotium 4.0版本已經支援對WebView的操作。Robotium 對Activity,Dialog,Toast,Menu 都是支援的。
源碼及相關資料地址:https://code.google.com/p/robotium/
Robotium具有清晰的調用方法、良好的相容性、完善的文檔和大量的實際應用案例,並且支援截屏。最為符合我們目前的實際需求。經實際測試,無需特殊配置即可相容Jenkins系統。
下面以一段HSA項目中的實際測試代碼舉例。該測試案例完成從登陸、菜單選取、一直到功能介面輸入驗證的一個流程。
public class LoginActivityTest extends ActivityInstrumentationTestCase2<LoginActivity> { Solo solo; LoginActivity mActivity; public LoginActivityTest(){ super(LoginActivity.class); } @Override protected void setUp() throws Exception { super.setUp(); mActivity = getActivity();//初始LoginActivity solo = new Solo(getInstrumentation(),mActivity);//初始Robotium的主要入口,solo對象 } public void testLogin(){ //清除使用者名稱EditText內容 solo.clearEditText(0); //輸入"userName" 到使用者名稱EditText solo.enterText(0, "userName"); //清除密碼EditText內容 solo.clearEditText(1); //輸入"userPass" 到密碼EditText solo.enterText(1, "userPass"); //清除網站EditText內容 solo.clearEditText(2); //輸入"siteCode" 到網站EditText solo.enterText(2, "siteCode"); //點擊登陸按鈕 solo.clickOnButton("登入"); //檢驗當前介面為MainListActivity solo.assertCurrentActivity("Expected MainListActivity activity", "MainListActivity"); //點擊動態菜單列表中的第一項,進入下一級子功能表介面 solo.clickInList(0); //檢驗當前介面為SubMenuActivity solo.assertCurrentActivity("Expected SubMenuActivity activity", "SubMenuActivity"); //點擊子功能表列表中的第一項,進入功能介面 solo.clickInList(0); //檢驗當前介面為ReceiveActivity solo.assertCurrentActivity("Expected ReceiveActivity activity", "ReceiveActivity"); //點擊介面中的"使用當前人員"按鈕 solo.clickOnButton("使用當前人員"); //輸入重量 solo.enterText(1, "123"); //輸入單號 solo.enterText(2, "21123456798"); //類比軟鍵盤,發送EditText的ACTION_DONE事件 solo.getCurrentActivity().runOnUiThread(new Runnable() { @Override public void run() { solo.getEditText(2).onEditorAction(EditorInfo.IME_ACTION_DONE); } }); //尋找是否有內容為"已掃描1件"的textview, 會自動等待10秒 boolean succ = solo.searchText("已掃描1件")) //判斷成功 assertTrue(succ); }}
可見,Robotium通過一個solo對象來進行各種事件的類比,代碼清晰易懂,並且完全相容原生AndroidTestFramework
安裝部署及穩定性測試
安卓系統最為讓人詬病的問題就是片段化,這點在中國比較明顯。大致上,2.3.X 和 4.x 的系統各佔半壁江山,此外還存在大量的山寨定製系統。
因此在這推薦兩款雲端測試載入器,Testin和百度雲測試。
兩個架構測試都很簡單,在官網註冊帳號後上傳apk即可,網站會用大量的真機進行安裝部署和monkey測試。測試完成後會發送一份測試給註冊郵箱。
Testin支援Robotium架構的代碼測試,同時上傳項目apk和測試apk(相同簽名)即可。
Testin地址: http://www.testin.cn/
百度雲測試: http://mtc.baidu.com/
其他測試架構Monkey測試
Android SDK開發包中內建一個monkeyrunner的工具,可用來進行monkey測試。
文檔地址:
- http://developer.android.com/tools/help/monkeyrunner_concepts.html
- http://developer.android.com/tools/help/monkey.html
Robolectric
一款基於JVM啟動並執行Android測試架構,最大特點就是不需要啟動模擬器,因此速度非常快!
目前已支援大部分原生SDK功能的測試,支援Resource,但對於一些特殊硬體上的類比還存在欠缺。期待進一步的完善
範例程式碼:
// Test class for MyActivity@RunWith(RobolectricTestRunner.class)public class MyActivityTest { @Test public void clickingButton_shouldChangeResultsViewText() throws Exception { Activity activity = Robolectric.buildActivity(MyActivity.class).create().get(); Button pressMeButton = (Button) activity.findViewById(R.id.press_me_button); TextView results = (TextView) activity.findViewById(R.id.results_text_view); pressMeButton.performClick(); String resultsText = results.getText().toString(); assertThat(resultsText, equalTo("Testing Android Rocks!")); }}
地址: http://robolectric.org/index.html
Google Espresso
Google於2013年10月開源的一款測試架構。據稱在Google內部已通過多重專案的實際驗證,並可能在未來加入到預設AndroidSDK中。
設計上接近Robotium,主要用於業務端的類比行為測試。相較Robotium,具有更為強大的UI元素匹配尋找功能和更快的運行速度。
不過經過本人的實際使用,發現該架構的代碼編寫相對複雜,遠不如Robotium來的輕巧。此外,該架構無法運行在預設AndroidTestFramework中(可認為是升級版),且因剛開源,缺少文檔和應用案例等資料,導致測試代碼編寫效率相對低下,故暫時不予採用。
地址: https://code.google.com/p/android-test-kit/wiki/Espresso
Mockito
一款用於Mock測試的主流架構
地址: https://code.google.com/p/mockito/
List mockedList = mock(List.class); when(mockedList.get(0)).thenReturn("first"); System.out.println(mockedList.get(0));
總結
如無意外,接下來一段時間內,Android項目會採用以下的方案搭建測試架構:
- 代碼級: AndroidTestFramework + Junit
- UI業務類比: Robotium
- 安裝部署: Testin
- CI: Jenkins
有興趣的同學也可關注下Robolectric和Espresso兩個架構的進展。
分類: Android
Android開源測試架構學習