Android 11 開發者預覽版現已推出;快來測試并分享您的反饋吧

測試基礎知識

用戶可以在各個層面與您的應用進行交互,從按某個按鈕到將信息下載到他們的設備上。因此,在迭代開發您的應用時,您應測試各種用例和交互。

組織整理代碼以便測試

隨著應用的擴展,您可能會發現有必要從服務器獲取數據、與設備的傳感器進行交互、訪問本地存儲或呈現復雜的界面。應用的多功能性需要全面的測試策略。

迭代創建和測試代碼

迭代開發某項功能時,您可以先編寫一個新測試,也可以將用例和斷言添加到現有單元測試。測試最初會失敗,因為該功能尚未實現。

務必考慮隨著設計新功能而出現的責任單元。對于每個單元,您需要編寫相應的單元測試。您的單元測試應幾乎囊括與單元的所有可能的交互,包括標準交互、無效輸入以及資源不可用的情況。應盡可能利用 Jetpack 庫;當您使用這些經過充分測試的庫時,您可以專注于驗證您的應用特有的行為。

在測試開發周期中,先編寫失敗的單元測試,再編寫代碼以使其通過測試,然后重構。整個功能開發周期存在于一個基于界面的更大周期的一個步驟中。
圖 1. 與由測試驅動的迭代開發關聯的兩個周期

完整的工作流(如圖 1 所示)包含一系列嵌套的迭代周期,其中一個由界面驅動的漫長而緩慢的周期用來測試代碼單元的集成。您可以使用更短且更快的開發周期來測試單元本身。這一組周期一直持續到您的應用滿足每個用例為止。

將應用看作一系列模塊

為了使您的代碼更易于測試,應從模塊的角度進行開發,其中每個模塊代表用戶在您的應用中完成的一項特定任務。這種開發角度與基于堆棧的應用視圖(通常包含代表界面、業務邏輯和數據的層)形成對比。

例如,“任務列表”應用可能包含用于創建任務的模塊、查看有關已完成任務的統計信息的模塊,以及拍攝要與特定任務相關聯的照片的模塊。這種模塊化架構還可以幫助您使不相關的類保持分離,并為在開發團隊內分配所有權提供了一個自然的結構。

務必在每個模塊周圍設置明確定義的界限,并隨著應用規模和復雜性的增長而創建新模塊。每個模塊應只重點關注一個領域,并且用于模塊間通信的 API 應保持一致。為更輕松、快捷地測試這些模塊間的交互,不妨考慮創建模塊的虛假實現。在測試中,一個模塊的真實實現可以調用另一個模塊的虛假實現。

不過,當您創建新模塊時,不要過于武斷地馬上使其功能齊全。特定模塊可以沒有應用堆棧的一層或多層。

要詳細了解如何在應用中定義模塊,以及創建和發布模塊的平臺支持,請參閱 Android App Bundle

配置測試環境

設置在應用中創建測試所需的環境和依賴項時,請遵循本部分中所述的最佳做法。

根據執行環境組織整理測試目錄

Android Studio 中的典型項目包含兩個用于放置測試的目錄。請按以下方式組織整理您的測試:

考慮在不同類型的設備上運行測試的利弊

在設備上運行測試時,您可以從以下類型中進行選擇:

真實設備可提供最高的保真度,但運行測試所花費的時間也最多。另一方面,模擬設備可提供較高的測試速度,但代價是保真度較低。不過,平臺在二進制資源和逼真的循環程序上的改進使得模擬設備能夠產生更逼真的結果。

虛擬設備則平衡了保真度和速度。當您使用虛擬設備進行測試時,可以使用快照來最大限度地縮短測試之間的設置時間。

考慮是否要使用測試替身

創建測試時,您可以選擇創建真實對象或測試替身,如虛假對象或模擬對象。通常,在測試中使用真實對象比使用測試替身要好,尤其是當被測對象滿足以下某個條件時:

特別是,模擬您并不擁有的類型的實例通常會導致測試很脆弱,只有在您已經了解其他人實現該類型的復雜性時,測試才有效。只在萬不得已時才使用此類模擬。您可以模擬自己的對象,但請注意,使用 @Spy 標注的模擬比對類中的所有功能打樁的模擬提供的保真度要高。

不過,如果您的測試嘗試對真實對象執行以下類型的操作,則最好創建虛假對象甚至是模擬對象:

提示:請與庫創建者聯系,了解他們是否提供了任何官方支持的測試基礎架構(如虛假對象)能讓您可靠地依賴。

編寫測試

配置完測試環境后,就該編寫用來評估應用功能的測試了。本部分介紹如何編寫小型、中型和大型測試。

測試金字塔的級別

包含三層的金字塔
圖 2. 測試金字塔,顯示了應用的測試套件應包含的三類測試

測試金字塔(如圖 2 所示)說明了應用應如何包含三類測試(即小型、中型和大型測試):

沿著金字塔逐級向上,從小型測試到大型測試,各類測試的保真度逐級提高,但維護和調試工作所需的執行時間和工作量也逐級增加。因此,您編寫的單元測試應多于集成測試,集成測試應多于端到端測試。雖然各類測試的比例可能會因應用的用例不同而異,但我們通常建議各類測試所占比例如下:小型測試占 70%,中型測試占 20%,大型測試占 10%

要詳細了解 Android 測試金字塔,請觀看 2017 年 Google I/O 大會的 Android 平臺上的測試驅動型開發會議視頻(從 1 分 51 秒開始)。

編寫小型測試

您編寫的小型測試應該是高度集中的單元測試,能夠詳盡地驗證應用中每個類的功能和約定。

在特定類中添加和更改方法時,請針對它們創建和運行單元測試。如果這些測試依賴于 Android 框架,請使用與設備無關的統一 API,如 androidx.test API。這種一致性可讓您在本地運行測試,而無需使用物理設備或模擬器。

如果您的測試依賴于資源,請在應用的 build.gradle 文件中啟用 includeAndroidResources 選項。然后,您的單元測試可以訪問編譯版本的資源,從而使測試更快速且更準確地運行。

app/build.gradle

    android {
        // ...

        testOptions {
            unitTests {
                includeAndroidResources = true
            }
        }
    }
    

本地單元測試

盡可能使用 AndroidX Test API,以便您的單元測試可以在設備或模擬器上運行。對于始終在由 JVM 驅動的開發計算機上運行的測試,您可以使用 Robolectric

Robolectric 會模擬 Android 4.1(API 級別 16)或更高版本的運行時環境,并提供由社區維護的虛假對象(稱為“影子”)。通過此功能,您可以測試依賴于框架的代碼,而無需使用模擬器或模擬對象。Robolectric 支持 Android 平臺的以下幾個方面:

插樁單元測試

您可以在物理設備或模擬器上運行插樁單元測試。不過,這種形式的測試所用的執行時間明顯多于本地單元測試,因此,最好只有在必須根據實際設備硬件評估應用的行為時才依靠此方法。

運行插樁測試時,AndroidX Test 會使用以下線程:

如果您需要在主線程上執行某個測試,請使用 @UiThreadTest 標注該測試。

編寫中型測試

除了通過運行小型測試來測試應用的每個單元之外,您還應從模塊級別驗證應用的行為。為此,請編寫中型測試,即用于驗證一組單元的協作和交互的集成測試。

您可以根據應用的結構和以下中型測試示例(按范圍遞增的順序)來定義表示應用中的單元組的最佳方式:

  1. 視圖和視圖模型之間的交互,如測試 Fragment 對象、驗證布局 XML 或評估 ViewModel 對象的數據綁定邏輯。
  2. 應用的代碼庫層中的測試,驗證不同數據源和數據訪問對象 (DAO) 是否按預期進行交互。
  3. 應用的垂直切片,測試特定屏幕上的交互。此類測試目的在于驗證應用堆棧的所有各層的交互。
  4. 多 Fragment 測試,評估應用的特定區域。與本列表中提到的其他類型的中型測試不同,這種類型的測試通常需要真實設備,因為被測交互涉及多個界面元素。

要執行這些測試,請執行以下操作:

  1. 使用 Espresso-Intents 庫中的方法。要簡化傳入這些測試的信息,請使用虛假對象和打樁。
  2. 結合使用 IntentSubject 和基于 Truth 的斷言來驗證捕獲的 intent。

運行插樁中型測試時使用 Espresso

當您在設備或 Robolectric 上執行類似于下面的界面交互時,Espresso 有助于使任務保持同步:

要詳細了解這些交互以及如何在應用的測試中使用它們,請參閱 Espresso 指南。

編寫大型測試

盡管單獨測試應用中的每個類和模塊很重要,但驗證可引導用戶使用多個模塊和功能的端到端工作流也同樣重要。這些類型的測試會在您的代碼中形成不可避免的瓶頸,但您可以通過驗證盡可能接近實際成品的應用來最大限度地減輕這種影響。

如果您的應用足夠小,您可能只需要一套大型測試來評估應用的整體功能。否則,您應按團隊所有權、功能垂直領域或用戶目標來劃分大型測試套件。

通常,最好在模擬設備或基于云的服務(如 Firebase 測試實驗室)上而不是在物理設備上測試您的應用,因為這樣您可以更方便快捷地測試屏幕尺寸和硬件配置的多種組合。

Espresso 中的同步支持

除了支持中型插樁測試之外,Espresso 還支持在大型測試中完成以下任務時實現同步:

要詳細了解這些交互以及如何在應用的測試中使用它們,請參閱 Espresso 指南。

使用 AndroidX Test 完成其他測試任務

本部分介紹如何使用 AndroidX Test 的元素來進一步優化應用的測試。

使用 Truth 創建更容易讀懂的斷言

Guava 團隊提供了一個名為 Truth 的流利斷言庫。在構建測試的驗證步驟(或 then 步驟)時,您可以使用此庫來代替基于 JUnit 或 Hamcrest 的斷言。

通常,您可以使用 Truth 來表達某個對象具有特定屬性,使用的短語包含您要測試的條件,例如:

AndroidX Test 支持 Android 的其他幾個主題,以使基于 Truth 的斷言更易于構建:

AndroidX Test API 可幫助您執行與移動應用測試相關的常見任務,下面幾部分將對此進行介紹。

編寫界面測試

Espresso 可讓您以編程方式且以線程安全的方式找到應用中的界面元素并與之交互。要了解詳情,請參閱 Espresso 指南。

運行界面測試

AndroidJUnitRunner 類定義了一個基于插樁的 JUnit 測試運行程序,可讓您在 Android 設備上運行 JUnit 3 或 JUnit 4 型測試類。該測試運行程序可幫助您將測試軟件包和被測應用加載到設備或模擬器上、運行測試并報告結果。

要進一步提高這些測試的可靠性,請使用 Android Test Orchestrator,它在自己的 Instrumentation 沙盒中運行每個界面測試。這種架構減少了測試之間的共享狀態,并在每個測試的基礎上隔離了應用崩潰。如需詳細了解 Android Test Orchestrator 在測試應用時提供的優勢,請參閱 Android Test Orchestrator 指南。

與可見元素進行交互

通過 UI Automator API,您可以與設備上的可見元素進行交互,而不管獲得焦點的是哪個 Activity 或 Fragment。

注意:我們建議只有在您的應用必須與系統界面或其他應用進行交互以完成關鍵用例時,才使用 UI Automator 測試您的應用。由于 UI Automator 與特定的系統界面進行交互,因此您必須在每次平臺版本升級后以及在每次發布新版本的 Google Play 服務后重新運行并修復 UI Automator 測試。

作為使用 UI Automator 的替代方法,我們建議您添加封閉測試或將大型測試分成一套中小型測試。特別是,一次重點測試一段應用間通信,如向其他應用發送信息和響應 intent 結果。Espresso-Intents 工具可以幫助您編寫這些較小的測試。

添加無障礙功能檢查以驗證普遍易用性

應用的界面應允許所有用戶(包括具有無障礙功能需求的用戶)與設備進行交互,并在應用中更輕松地完成任務。

為了幫助驗證應用的無障礙功能,Android 測試庫提供了幾項內置功能,下面幾部分將對此進行介紹。要詳細了解如何驗證應用對不同類型用戶的易用性,請參閱關于測試應用的無障礙功能的指南。

Robolectric

您可以通過在測試套件開頭添加 @AccessibilityChecks 注釋來啟用無障礙功能檢查,如以下代碼段所示:

Kotlin

    import org.robolectric.annotation.AccessibilityChecks

    @AccessibilityChecks
    class MyTestSuite {
        // Your tests here.
    }
    

Java

    import org.robolectric.annotation.AccessibilityChecks;

    @AccessibilityChecks
    public class MyTestSuite {
        // Your tests here.
    }
    

Espresso

您可以通過在測試套件的 setUp() 方法中調用 AccessibilityChecks.enable() 來啟用無障礙功能檢查,如以下代碼段所示。

如需詳細了解如何解讀這些無障礙功能檢查的結果,請參閱 Espresso 無障礙功能檢查指南。

Kotlin

    import androidx.test.espresso.accessibility.AccessibilityChecks

    @Before
    fun setUp() {
        AccessibilityChecks.enable()
    }
    

Java

    import androidx.test.espresso.accessibility.AccessibilityChecks;

    @Before
    public void setUp() {
        AccessibilityChecks.enable();
    }
    

推動 Activity 和 Fragment 生命周期

您可以使用 ActivityScenarioFragmentScenario 類來測試應用的 Activity 和 Fragment 如何響應系統級中斷和配置更改。要了解詳情,請參閱關于如何測試 Activity測試 Fragment 的指南。

管理服務生命周期

AndroidX Test 包含用于管理關鍵服務的生命周期的代碼。要了解如何定義這些規則,請參閱 JUnit4 規則指南。

評估因 SDK 版本而異的所有行為變體

如果應用的行為取決于設備的 SDK 版本,請使用 @SdkSuppress 注釋,并根據應用邏輯的分叉方式傳入 minSdkVersionmaxSdkVersion 的值:

Kotlin

    @Test
    @SdkSuppress(maxSdkVersion = 27)
    fun testButtonClickOnOreoAndLower() {
        // ...
    }

    @Test
    @SdkSuppress(minSdkVersion = 28)
    fun testButtonClickOnPieAndHigher() {
        // ...
    }
    

Java

    @Test
    @SdkSuppress(maxSdkVersion = 27)
    public void testButtonClickOnOreoAndLower() {
        // ...
    }

    @Test
    @SdkSuppress(minSdkVersion = 28)
    public void testButtonClickOnPieAndHigher() {
        // ...
    }
    

其他資源

如需詳細了解如何在 Android 平臺上進行測試,請參閱以下資源。

示例

Codelab

四虎免费影院-2020最新四虎免费观看