Robotium 為專門測試 android ui 的 framework,詳細介紹參考官網
本篇介紹如何導入 Robotium,以及建立測試 Activity 的 Robotium 模板,最後是 Robotium 常用函式介紹。
如何導入 Robotium
- Robotium 的使用環境和 android test project 非常類似,因此先建立 android test project。
建立 android test project 詳細步驟請參考這篇 - 在第1步建立的 android test project 根目錄中建立 libs 資料夾,並將 Robotium 提供的 jar 檔放入 libs ,android 會自動幫你做好其他事。
建立測試 Activity 的 Robotium 模板
完成導入 Robotium 之後,你應該有個 test case,再將以下的 mSolo 加入。
Solo 為 Robotium 提供的類別,大部分測試功能都由它開始。
public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> { private Solo mSolo; public MainActivityTest(String name) { super(MainActivity.class); setName(name); } public MainActivityTest() { this(MainActivityTest.class.getSimpleName()); } protected void tearDown() throws Exception { mSolo.finishOpenedActivities(); super.tearDown(); } protected void setUp() throws Exception { super.setUp(); mSolo = new Solo(getInstrumentation(), getActivity()); } public void testPreconditions() { assertNotNull(mSolo); } }
第24行初始化 mSolo
第17行銷毀 mSolo
以上就是測試 activity 的 Robotium 模板
Robotium 常用函式介紹
使用 Robotium 來寫測試主要分為3個步驟:
- 取得 UI Component
- 操作 UI Component
- 使用斷言(Assert)判斷操作結果是否符合預期
接下來依序介紹在 Robotium 中各個步驟如何進行
取得 UI Component
在 Robotium 主要有2種取得 UI Component 的方式,第1種為根據 UI Component 的 ID 來取得,適合用於 UI Component 具有唯一的 ID 情況。
android.view.View |
getView(int id)
Returns a View matching the specified resource id.
|
android.view.View |
getView(String id)
Returns a View matching the specified resource id.
|
Example
... LinearLayout mainView = (LinearLayout) mSolo.getView(R.id.main_view);//R.id.main_view 為 resource id
UI Component 的內容值可以當作識別的方式,但這種方式只支援 Button, EditText, TextView, 適合用於 UI Component 具有內容值的情況。
android.widget.Button |
getButton(String text)
Returns a Button displaying the specified text.
|
android.widget.EditText |
getEditText(String text)
Returns an EditText displaying the specified text.
|
android.widget.TextView |
getText(String text)
Returns a TextView displaying the specified text.
|
Example
... Button exitButton = mSolo.getButton("Exit");//Exit 為顯示在 button 上的內容
UI Component 的 Tag 可以當作識別的方式,適合用於 UI Component 具有 Tag 的情況下。
android.view.View |
getView(Object tag)
Returns a View matching the specified tag.
|
第2種為根據 UI Component 的類型進行過濾再根據索引來取得,這種情況適用於 UI Component 沒有可以識別的 ID 情況。以下第1個方法為回傳所有類型的 views, 第2個回傳指定類型的 views, 第3個回傳指定類型並指定 parent 的 views
ArrayList<android.view.View> |
getCurrentViews()
Returns an ArrayList of the Views currently displayed in the focused Activity or Dialog.
|
<T extends android.view.View> |
getCurrentViews(Class<T> classToFilterBy)
Returns an ArrayList of Views matching the specified class located in the focused Activity or Dialog.
|
<T extends android.view.View> |
getCurrentViews(Class<T> classToFilterBy, android.view.View parent)
Returns an ArrayList of Views matching the specified class located under the specified parent.
|
使用上述的方法取得 view 的群集之後,再使用以下方法取得個別的 view。
需要注意的是 index 該 index 為子視圖的順序(index 從零開始由左到右或上到下遞增)。
android.widget.Button |
getButton(int index)
Returns a Button matching the specified index.
|
android.widget.EditText |
getEditText(int index)
Returns an EditText matching the specified index.
|
android.widget.ImageView |
getImage(int index)
Returns an ImageView matching the specified index.
|
android.widget.ImageButton |
getImageButton(int index)
Returns an ImageButton matching the specified index.
|
android.widget.TextView |
getText(int index)
Returns a TextView matching the specified index.
|
<T extends android.view.View> |
getView(Class<T> viewClass, int index)
Returns a View matching the specified class and index.
|
Example
... LinearLayout mainView = (LinearLayout) mSolo.getView(R.id.main_view); List<Button> buttons = mSolo.getCurrentViews(Button.class, mainView); for (int i=0; i<buttons.size(); ++i) { Button button = mSolo.getButton(i); } //以上的 source code 即是取得 mainView 中的所有 button
操作 UI Component
Robotium 提供的操作共有點擊,長按,輸入文字,拖曳,滾動,搜尋,等待。
點擊&長按
點擊和長按的方法大致上各為clickOnXXX, clickLongOnXXX,支援的種類有 View, Button, EditText, ImageView, ImageButton, CheckBox, MenuItem, RadioButton, ToggleButton, Screen座標等等 。
詳細參考官網
Example :
... mSolo.clickOnButton("Exit");//點擊 Exit button
輸入和清除文字
各為 typeText 以及 enterText,都是對 EditText 輸入文字,2者不同為 type 會一個一個的輸入,而 enter 為直接全部輸入 ,清除則是只對 EditText 清除 (cleanEditText)。
詳細參考官網
Example :
... EditText numberEditText = mSolo.getEditText("number");//取得內容為 number 的 EditText mSolo.typeText(numberEditText, "123");//在 EditText 填入 123
拖曳
void |
drag(float fromX, float toX, float fromY, float toY, int stepCount)
Simulate touching the specified location and dragging it to a new location.
|
... mSolo.drag(0.0f, 50.0f, 0.0f, 50.0f, 100);
需要注意的是原點從左上角開始算起。
滾動
滾動為 ScrollXXX,基本的有 ScrollDown, ScrollUp 往上下滾動一段。
ScrollToBottom, ScrollToTop 往頂端底端滾動。
ScrollToSide 滾動至左或右。進階可以指定滾動的距離。
支援的種類有 view, ListView, RecyclerView,
詳細參考官網
mSolo.scrollDown();
搜尋
searchXXX,搜尋的目的為確認 UI Compenent 是否存在於 Screen 上,有的話才進行下一步操作。支援 Button, EditText, TextView, ToggleButton, 詳細參考官網
Example :
... if(!mSolo.searchButton("Exit")){//尋找 Exit button 是否在螢幕上 fail("Exit button should on screen"); }
等待
waitForXXX為等待系列,支援 activity, dialog open dialog close, text, view。
需要注意的是 waitFor 函式會在其內預設等待20秒,在20秒之內若等待條件成立的話回傳 true,反之回傳 false,也有提供自定義時間 e.g. mSolo.waitForLogMessage(“”,5000)。
比較特殊等待條件有 waitForLogMessage,這裡的 LogMessage 即為使用 Log 列印出來的內容
e.g. Log.d(TAG,”log message should print”);
就可使用 mSolo.waitForLogMessage(“log message should print”);
另一個是 waitForCondition , 可以自定義複雜條件以滿足特別的需求。
詳細參考官網
另外還有其他操作 e.g. 休息(sleep),擷圖(takeScreenShot),模擬按下實體按鍵, 檢查 UI 狀態(isXXX)。
使用斷言(Assert)判斷操作結果是否符合預期
因為 android test project 預設為使用 junit 來斷言,對於絕大部分的斷言情況來說已經足夠。Robotium 提供的斷言不多,只有4種(assertCurrentAcitvity, assertMemoryNotLow)。
Example :
... assertTrue(mSolo.searchButton("Exit"));//斷言 Exit button 需要在螢幕上