本頁概述測試 Android 應用程式的核心原則,包括核心最佳做法和其優點。
測試的好處
測試是應用程式開發流程中不可或缺的一環。藉由對應用程式持續執行測試,您可以在公開發布應用程式前,驗證應用程式的正確性、功能行為和可用性。
您可以在瀏覽應用程式時手動測試應用程式。您可能會使用不同的裝置和模擬器、變更系統語言,並嘗試產生每個使用者錯誤或細查每個使用者流程。
不過,手動測試的縮放比例會不佳,而且很容易忽略應用程式行為中的迴歸。自動化測試:「自動化測試」是指使用工具為您執行測試,不但速度更快、更可重複,也通常能在開發階段初期,為您提供更多可做為行動依據的意見回饋。
Android 的測試類型
行動應用程式相當複雜,在許多環境中都能順利運作。因此,測試有很多類型。
主旨
舉例來說,視 subject 劃分不同的測試類型:
- 功能測試:應用程式能執行預期的功能嗎?
- 效能測試:這項功能是否能快速有效地?
- 無障礙測試:這項功能是否能與無障礙服務搭配運作?
- 相容性測試:是否可在所有裝置和 API 級別上順利運作?
範圍
測試也會依「大小」或「隔離程度」而有所不同:
- 單元測試或小型測試,只能驗證應用程式的極小部分,例如方法或類別。
- 端對端測試或大型測試會同時驗證應用程式的較大部分,例如整個螢幕或使用者流程。
- 中等測試介於兩個或多個單元之間,並檢查是否整合。
![測試可分為小、中或大。](https://developer.android.google.cn/static/training/testing/fundamentals/test-scopes.png?authuser=3&hl=zh-tw)
分類測試的方式有很多種。不過,對應用程式開發人員來說,最重要的區別在於執行測試。
檢測設備與本機測試
您可以在 Android 裝置或其他電腦上執行測試:
- 設備測試在 Android 裝置 (實體或模擬) 上執行。應用程式會與測試應用程式一起建構及安裝,以便插入指令及讀取狀態。檢測設備測試通常為 UI 測試,包含啟動應用程式,然後與應用程式互動。
- 本機測試會在開發機器或伺服器上執行,因此也稱為「主機端測試」。這些 API 通常較小、快速,將受測試的主體與應用程式的其餘部分區隔開來。
![測試可以透過裝置進行檢測設備測試,或在開發機器上執行本機測試。](https://developer.android.google.cn/static/training/testing/fundamentals/instru-vs-local.png?authuser=3&hl=zh-tw)
單元測試並非本機進行,而且並非所有端對端測試都會在裝置上執行。例如:
- 大型本機測試:您可以使用在本機執行的 Android 模擬器,例如 Robolectric。
- 小型檢測設備測試:您可以驗證程式碼是否能與架構功能 (例如 SQLite 資料庫) 搭配使用,您可以在多部裝置上執行這項測試,藉此檢查 SQLite 與多個版本的整合情形。
範例
以下程式碼片段示範如何在點按元素並驗證其他元素的檢測設備 UI 測試中與 UI 互動。
Espresso
// When the Continue button is clicked
onView(withText("Continue"))
.perform(click())
// Then the Welcome screen is displayed
onView(withText("Welcome"))
.check(matches(isDisplayed()))
Compose UI
// When the Continue button is clicked
composeTestRule.onNodeWithText("Continue").performClick()
// Then the Welcome screen is displayed
composeTestRule.onNodeWithText("Welcome").assertIsDisplayed()
下列程式碼片段是 ViewModel (本機、主機端測試) 單元測試的一部分:
// Given an instance of MyViewModel
val viewModel = MyViewModel(myFakeDataRepository)
// When data is loaded
viewModel.loadData()
// Then it should be exposing data
assertTrue(viewModel.data != null)
定義測試策略
在理想情況下,您應在應用程式相容的每部裝置上測試應用程式中的每一行程式碼。可惜的是,這種方法太慢 且成本昂貴
良好的測試策略可在測試的準確度、速度和可靠性之間取得適當平衡。測試環境與實際裝置的相似性會決定測試的擬真度。在模擬裝置或實體裝置本身上執行高精確度測試。低擬真度測試可能會在本機工作站的 JVM 上執行。高擬真度測試通常速度較慢,且需要更多資源,因此並非所有測試都應執行高精確度測試。
不穩定的測試
即使在設計和實作正確的情況下,仍會發生錯誤。舉例來說,在實體裝置上執行測試時,自動更新功能可能會在測試期間啟動,並導致更新失敗。程式碼中細微的競爭狀況可能只有一小部分的時間發生。未通過 100% 時間的測試都會不穩定。
可測試的架構
根據可測試的應用程式架構,程式碼採用的結構,可讓您輕鬆獨立測試程式碼的不同部分。可測試的架構還有其他優點,例如更佳的可讀性、可維護性、擴充性和重複使用性。
「無法測試」的架構會產生下列結果:
- 規模較大、速度較慢、不穩定的測試。無法進行單元測試的類別可能會涵蓋在較大的整合測試或 UI 測試中。
- 可減少測試不同情境的機會。大型測試的執行速度較慢,因此測試應用程式的所有可能狀態可能並不切實際。
如要進一步瞭解架構指南,請參閱「應用程式架構指南」。
分離的方法
如果您可以從其他函式中擷取部分函式、類別或模組的部分,那麼進行測試會比較簡單,也更有效率。這種做法稱為分離,是可測試架構最重要的概念。
常見的分離技巧包括:
- 將應用程式分割為多個圖層,例如「呈現」、「網域」和資料。您也可以將應用程式分割成「模組」,每個功能各一個。
- 請避免將邏輯新增至含有大型依附元件的實體,例如活動和片段。您可以使用這些類別做為架構的進入點,並將 UI 和商業邏輯移至其他位置,例如可組合項、ViewModel 或網域層。
- 避免在包含商業邏輯的類別中直接架構依附元件。例如,不要在 ViewModel 中使用 Android Context。
- 讓依附元件很容易取代。舉例來說,您可以使用「介面」,而非具體實作。即使不使用 DI 架構,也請使用依附元件插入功能。
後續步驟
現在您已瞭解應測試的原因和兩種主要測試類型,請參閱測試項目一文。
或者,如要建立第一個測試並學習,請參閱測試程式碼研究室。