測試應用程式活動's 活動

活動是應用程式中所有使用者互動的容器,因此請務必測試應用程式活動在裝置層級事件 (例如下列事件) 期間的行為:

  • 其他應用程式 (例如裝置的電話應用程式) 中斷了應用程式的活動。
  • 系統會刪除並重新建立活動。
  • 使用者將活動置於新的視窗環境,例如子母畫面 (PIP) 或多視窗模式。

特別是,請務必確保活動能正確回應「活動生命週期」一文所述的事件。

本指南說明如何評估應用程式在活動生命週期中轉換不同狀態時,維持資料完整性和良好使用者體驗的能力。

在 Compose 中測試活動

測試以 Jetpack Compose 建構的應用程式時,通常會使用 createAndroidComposeRule 啟動活動,並與 UI 元件互動。

不過,如要測試裝置層級的事件 (例如設定變更,或活動遭系統置於背景或刪除),就必須直接操控活動的生命週期。如要執行這項操作,請使用基礎 ActivityScenario 架構。

Compose 測試規則會自動為您包裝及管理這個情境。 在本指南中,您會看到下列模式,用於彌合新式 UI 測試與標準生命週期管理之間的差距:

@get:Rule
val composeTestRule = createAndroidComposeRule<MyActivity>()

@Test fun testEvent() {
    val scenario = composeTestRule.activityRule.scenario

    // ...
}

控管活動狀態

測試應用程式活動時,其中一個重要環節是將應用程式活動置於特定狀態。如要定義測試的「條件」部分,請使用 AndroidX Test 程式庫的 ActivityScenario 執行個體。使用這個類別,您可以將活動置於模擬裝置層級事件的狀態。

ActivityScenario 是跨平台 API,可用於本機單元測試和裝置端整合測試。在實體或虛擬裝置上,ActivityScenario 可提供執行緒安全,在測試的插樁執行緒與執行受測活動的執行緒之間同步處理事件。

這個 API 特別適合評估受測活動在遭到刪除或建立時的行為。本節介紹與這項 API 相關的最常見用途。

建立活動

如要建立受測活動,請新增下列程式碼片段所示的程式碼:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEvent() {
       launchActivity<MyActivity>().use {
       }
    }
}

建立活動後,ActivityScenario 會將活動轉換為 RESUMED 狀態。這個狀態表示活動正在執行,且使用者可看見。在這個狀態下,您可以使用 Compose 測試 API 自由與活動的可組合函式互動。

Google 建議您在測試完成時,對活動呼叫 close。 這會清除相關資源,並提升測試穩定性。ActivityScenario 實作 Closeable,因此您可以套用 use 擴充功能,讓活動自動關閉。

或者,您可以使用 createAndroidComposeRule 在每個測試前自動啟動 Activity、處理終止作業,並授予您存取 Compose UI 測試方法和基礎 ActivityScenario 的權限。以下範例說明如何定義規則,並從中取得情境的執行個體:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @get:Rule
    val composeTestRule = createAndroidComposeRule<MyActivity>()

    @Test fun testEvent() {
        val scenario = composeTestRule.activityRule.scenario
    }
}

將活動推動到新狀態

如要將活動推動至其他狀態 (例如 CREATEDSTARTED),請呼叫 moveToState。這項動作會模擬活動因遭到其他應用程式或系統動作中斷,而停止或暫停的情況。

以下程式碼片段顯示 moveToState 的使用範例:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEvent() {
        launchActivity<MyActivity>().use { scenario ->
            scenario.moveToState(State.CREATED)
        }
    }
}

判斷目前的活動狀態

如要判斷受測活動的目前狀態,請取得 ActivityScenario 物件中的 state 欄位值。如果活動會重新導向至其他活動或自行完成,檢查受測活動的狀態就特別有幫助,如下列程式碼片段所示:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEvent() {
        launchActivity<MyActivity>().use { scenario ->
            scenario.onActivity { activity ->
              startActivity(Intent(activity, MyOtherActivity::class.java))
            }

            val originalActivityState = scenario.state
        }
    }
}

重新建立活動

當裝置資源不足時,系統可能會刪除活動,因此使用者返回應用程式時,應用程式必須重新建立該活動。如要模擬這些情況,請呼叫 recreate

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEvent() {
        launchActivity<MyActivity>().use { scenario ->
            scenario.recreate()
        }
    }
}

ActivityScenario 類別會維護活動的已儲存執行個體狀態,以及使用 @NonConfigurationInstance 註解的任何物件。這些物件會載入受測活動的新例項。

擷取活動結果

如要取得與已完成活動相關聯的結果代碼或資料,請取得 ActivityScenario 物件中 result 欄位的值。使用 createAndroidComposeRule 即可輕鬆觸發完成活動的 UI 動作,如以下程式碼片段所示:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @get:Rule
    val composeTestRule = createAndroidComposeRule<MyActivity>()

    @Test fun testResult() {
        composeTestRule.onNodeWithTag("finish_button").performClick()

        val scenario = composeTestRule.activityRule.scenario
        val resultCode = scenario.result.resultCode
        val resultData = scenario.result.resultData
    }
}

在活動中觸發動作

ActivityScenario 中的所有方法都是封鎖呼叫,因此 API 會要求您在檢測執行緒中執行這些方法。

如要在受測的活動中觸發動作,請使用 Compose 測試 API 與可組合函式互動:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @get:Rule
    val composeTestRule = createAndroidComposeRule<MyActivity>()

    @Test fun testEvent() {
        composeTestRule.onNodeWithText("Refresh").performClick()
    }
}

不過,如果您需要對活動本身呼叫某種方法,則可以使用 onActivity 安全地執行此動作:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEvent() {
        launchActivity<MyActivity>().use { scenario ->
            scenario.onActivity { activity ->
              activity.handleSwipeToRefresh()
            }
        }
    }
}

其他資源

如要進一步瞭解測試,請參閱下列額外資源:

說明文件