Google的Android生態系統在持續快速擴大。新的移動裝置廠商正在世界各個角落湧現,由此出現了各種不同的螢幕大小、不同的ROM/韌體、不同的晶片等等。這對於安卓開發者而言,成為了難以對付的生態碎片。
幸運的是,Android(包括iOS)的開發者們已可以不受限制地獲得一些先進的基於雲的解決方案,比如Testdroid Cloud,用以在大規模真實的裝置上執行自動化測試來保證質量。不同Android測試框架的出現在很大程度上減輕了Android開發者的負擔。
今天我們將瞭解5個最佳Android測試框架,講解每一個的基本原理和程式碼例項。
Robotium
毫無疑問,早期Android世界裡用得最為廣泛的測試框架就是Robotium。它與Selenium的Android版本有類似之處,可以讓測試API更簡單。
Robotium是一個開源的庫,基於JUnit擴充套件了大量關於Android UI的有效測試方法。它為 Android 應用程式(原生和混合)和web 測試提供了功能強大且可靠的自動化黑盒測試用例。只要原始碼可用,利用Robotium,你就可以編寫功能測試、系統測試和驗收測試場景,並執行測試。
Robotium程式碼示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
//Public void 方法 public void testRecorded() throws Exception { //等待文字“Hello”顯示 if (solo.waitForText("Hello!")) { //找到R類id識別符號為"Sign in"的控制元件-然後點選它 solo.clickOnView(solo.findViewById("com.twitter.android.R.id.sign_in")); //找到使用者名稱的控制元件並輸入登陸使用者名稱 solo.enterText((EditText) solo.findViewById("com.twitter.android.R.id.login_username"),"username"); //找到密碼的控制元件並輸入登陸密碼 solo.enterText((EditText) solo.findViewById("com.twitter.android.R.id.login_password"),"password"); //找到登陸按鈕,點選登陸 solo.clickOnView(solo.findViewById("com.twitter.android.R.id.login_login")); //等待登陸完成 solo.waitForActivity("HomeTabActivity"); } //啟用文字域來編寫一個tweet solo.clickOnView(solo.findViewById("com.twitter.android.R.id.menu_compose_tweet")); //編輯tweet solo.enterText((EditText) solo.findViewById("com.twitter.android.R.id.edit"), "Testdroid"); //推送tweet中! solo.clickOnView(solo.findViewById("com.twitter.android.R.id.composer_post")); } |
Testdroid Recorder 是一個很棒的記錄工具,它基於Robotium來建立測試指令碼為你帶來方便。通過在真正裝置上執行實際操作,它可以記錄每個步驟或者你執行的動作,然後轉換為Javascript供你進一步修改。
此外,你也可以完全下載和使用我們的擴充套件庫——ExtSolo。它包括了一些尚未合併到Robotium的有用方法,比如:
- 支援任意解析度的x、y點選自動縮放
- 多路徑拖拽
- 測試失敗時自動截圖
- 模擬位置
- 修改裝置語言
- 控制WiFi連線
uiautomator
Robotium這個框架不錯但稍顯簡單。uiautomator可以讓你在測試Android app和遊戲時實現更多操作。Google的測試框架(譯者注:uiautomator是Google在SDK4.0以後推出的自動化解決方案)支援在一個或多個裝置上測試本地Android app使用者介面(UI)。uiautomator的另一個優點是它執行JUnit測試用例時有特權,意味著測試用例可以跨程式。它還提供了五個不同的類給開發者使用,包括:
1 2 3 4 5 |
com.android.uiautomator.core.UiCollection; com.android.uiautomator.core.UiDevice; com.android.uiautomator.core.UiObject; com.android.uiautomator.core.UiScrollable; com.android.uiautomator.core.UiSelector |
由於它出現的時間點關係,它只適用於與API級別為16(譯者注:相當於SDK4.1)或更高版本的Android裝置。Uiautomator的另一個缺點是它不支援webview,沒有辦法到直接獲取到Android的UI物件。
uiautomator的程式碼示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
//Public void 方法 public void testSignInAndTweet() throws Exception { //啟動應用 getUiDevice().wakeUp(); //點選Home鍵以保證回到主屏 getUiDevice().pressHome(); //選擇“應用”並點選 new UiObject(new UiSelector().description("Apps")).click(); //選擇“Twitter”並點選 new UiObject(new UiSelector().text("Twitter")).click(); //定位並選擇“登陸” UiSelector signIn = new UiSelector().text("Sign In"); //如果按鈕可用,則點選 UiObject signInButton = new UiObject(signIn); if (signInButton.exists()) { signInButton.click(); //設定使用者名稱 new UiObject(new UiSelector().className("android.widget.EditText").instance(0)).setText("username"); new UiObject(new UiSelector().className("android.widget.EditText").instance(1)).setText("password"); new UiObject(new UiSelector().className("android.widget.Button"). text("Sign In").instance(0)).click(); //等待登陸處理 getUiDevice().waitForWindowUpdate(null, 2000); // 等待主視窗 getUiDevice().waitForWindowUpdate(null, 30000); } new UiObject(new UiSelector().description("New tweet")).click(); //編輯一個新tweet new UiObject(new UiSelector().className("android.widget.LinearLayout").instance(8)). setText("Awesome #Testdroid!"); //推送tweet new UiObject(new UiSelector().text("Tweet")).click(); } |
Espresso
Espresso是一個最新的Android自動化測試框架,由Google開源,它可以幫助開發和測試推敲UI的設計。Espresso有一個很小、可預測的且容易上手的API,它構建在Android instrumentation 框架的頂層。你可以利用它快速寫出簡潔可靠的Android UI測試用例。它支援API級別為8(Froyo)、10 (Gingerbread)和 15 (Ice Cream Sandwich)及之後的裝置。
它相當可靠,與UI執行緒同步並且速度快,因為沒有必要做任何休眠等待的操作(當app空閒時測試執行在同一個毫秒級別)。不過它同樣不支援webview。
Espresso的程式碼示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
public void testEspresso() { // Check if view with the text 'Hello.' is shown //如果帶有文字“Hello”的控制元件顯示,則點選 onView(withText("Hello.")).check(matches(isDisplayed())); // R class ID identifier for 'Sign in' - and click it //找到R類id識別符號為"Sign in"的控制元件-然後點選它 onView(withId(getInstrumentation().getTargetContext().getResources() .getIdentifier("com.twitter.android:id/sign_in", null, null))).perform(click()); // R class ID identifier for entering username //找到使用者名稱的控制元件並輸入登陸使用者名稱 onView(withId(getInstrumentation().getTargetContext().getResources() .getIdentifier("com.twitter.android:id/login_username", null, null))).perform((typeText("username"))); // R class ID identifier for entering password //找到密碼的控制元件並輸入登陸密碼 onView(withId(getInstrumentation().getTargetContext().getResources() .getIdentifier("com.twitter.android:id/login_password", null, null))).perform((typeText("password"))); // R class ID identifier for clicking log in //找到登陸按鈕,點選登陸 onView(withId(getInstrumentation().getTargetContext().getResources() .getIdentifier("com.twitter.android:id/login_login", null, null))).perform(click()); // Activate the text field to compose a tweet //啟用文字域來編寫一個tweet onView(withId(getInstrumentation().getTargetContext().getResources() .getIdentifier("com.twitter.android:id/menu_compose_tweet", null, null))).perform(click()); // Type the tweet //編輯tweet onView(withId(getInstrumentation().getTargetContext().getResources() .getIdentifier("com.twitter.android:id/edit", null, null))).perform((typeText(”#Testdroid"))); // Tweeting! //推送tweet中! onView(withId(getInstrumentation().getTargetContext().getResources() .getIdentifier("com.twitter.android:id/composer_post", null, null))).perform(click()); } |
Calabash
Calabash是一個跨平臺的自動化測試框架,支援Android、iOS原生和混合的應用測試。Calabash的語法通俗易懂,甚至技術零基礎的人也能為執行在各種移動平臺上的應用編寫和執行自動化驗收測試用例。Calabash的測試用例編寫是基於Cucumber(譯者注:Calabash的底層實現是Cucumber,它是一種BDD測試框架),然後在執行時將指令碼轉換為Robotium或者Frank。它支援大約80種自然語言命令(控制器),並且可以用Ruby或Java實現新的控制器。
Calabash的程式碼示例:
1 2 3 4 5 6 7 8 9 10 |
Feature: Login feature Scenario: As a valid user I can log into my app I wait for text "Hello" Then I press view with id "Sign in" Then I enter text "username" into "login_username" Then I enter text "password" into "login_password" Then I wait for activity "HomeTabActivity" Then I press view with id "menu_compose_tweet" Then I enter text "Testdroid" into field with id "edit" Then I press view with id "composer_post" |
Appium
Appium是一個移動自動化測試框架(工具),可支援iOS和Android的原生、混合的移動web應用測試。它內部採用Selenium WebDriver的JSON Wire Protocol來與iOS和Android app互動。它通過驅動uiautomator(API級別高於等於16)和Seledroid(API級別低於16)支援Android,驅動UIAutomation來支援iOS,利用Selenium driver來支援 Android和iOS都有的移動web。
Appium最大的一個優點就是幾乎可以使用任何一種語言(比如Java、Objective-C、JavaScript、PHP、Ruby、Python、C#等)來編寫Appium指令碼,不受工具選擇的限制,相容兩個最重要的平臺(Android和iOS),安裝和配置裝置來測試等也自由許多。而且如果你對Selenium很熟悉,那麼對你而言使用Appium測試移動app輕而易舉。他們使用的是相同的WebDriver,且DesiredCapabilities(譯者注:DesiredCapabilities是由客戶端傳送給Appium伺服器端用來告訴伺服器去啟動哪種會話的一套鍵值對集合)的使用方式相同。因此在Appium上配置執行一個應用與在Selenium上有非常多相似之處。
Appium的程式碼示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# wait for hello #等待hello出現 sleep(3) textFields = driver.find_elements_by_tag_name('textField') assertEqual(textFields[0].get_attribute("value"), "Hello") # click sign-in button #點選登陸按鈕 driver.find_elements_by_name('Sign in')[0].click() # find the text fields again, and enter username and password #找到文字域,然後鍵入使用者名稱和密碼 textFields = driver.find_elements_by_tag_name('textField') textFields[0].send_keys("twitter_username") textFields[1].send_keys("passw0rd") # click the Login button (the first button in the view) #點選登陸按鈕(控制元件中的第一個按鈕) driver.find_elements_by_tag_name('button')[0].click() # sleep #休眠 sleep(3) # click the first button with name "Compose" #點選名字為"Compose"的第一個按鈕 driver.find_elements_by_name('Compose')[0].click() # type in the tweet message #鍵入tweet訊息內容 driver.find_elements_by_tag_name('textField')[0].send_keys(”#Testdroid is awesome!") # press the Send button #點選傳送按鈕 driver.find_elements_by_name('Send')[0].click() # exit #退出 driver.quit() |
總結
在這裡我們列出了5種最佳測試框架,它們支援Android的構建、創立和修改。當然,每一種都有其優勢和劣勢。Appium適合於同時測試應用的Android和iOS版。但是如果你是一個忠誠的Android開發者,只編寫Android版本的應用,那麼使用Robotium就不錯。藉助於Testdroid Recorder來生成測試指令碼絕對會讓你節省大量的時間和錢(它是免費的!)。因此,慎重考慮你的測試需求-功能測試,相容性測試,UI測試等等,然後選擇一個最適合和最優的Android測試框架。
打賞支援我翻譯更多好文章,謝謝!
打賞譯者
打賞支援我翻譯更多好文章,謝謝!
任選一種支付方式