使用 Espresso Device API 测试屏幕配置更改

当设备经历常见的配置更改(例如旋转和屏幕展开)时,请使用 Espresso Device API 来测试您的应用。Espresso Device API 是在 Jetpack Compose 测试规则之外模拟设备级操作的推荐工具。如果您是编写 Jetpack Compose UI 测试的新手,请参阅测试您的 Compose 布局

Espresso Device API 允许您在虚拟设备上模拟配置更改,并同步执行测试,因此一次只会发生一个 UI 操作或断言,从而使您的测试结果更加可靠。如果您是使用 Espresso 编写 UI 测试的新手,请参阅其文档

要使用 Espresso Device API,您需要满足以下条件

  • Android Studio Iguana 或更高版本
  • Android Gradle 插件 8.3 或更高版本
  • Android 模拟器 33.1.10 或更高版本
  • 运行 API 级别 24 或更高级别的 Android 虚拟设备

为 Espresso Device API 设置您的项目

要设置您的项目以支持 Espresso Device API,请执行以下操作

  1. 为了让测试能够向测试设备发送命令,请将 INTERNETACCESS_NETWORK_STATE 权限添加到 androidTest 源代码集中的清单文件中

      <uses-permission android:name="android.permission.INTERNET" />
      <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    
  2. gradle.properties 文件中启用 enableEmulatorControl 实验性标志

      android.experimental.androidTest.enableEmulatorControl=true
    
  3. 在模块级构建脚本中启用 emulatorControl 选项

    Kotlin

      testOptions {
        emulatorControl {
          enable = true
        }
      }
      

    Groovy

      testOptions {
        emulatorControl {
          enable = true
        }
      }
      
  4. 在模块级构建脚本中,将 Espresso Device 库导入到您的项目中

    Kotlin

    dependencies {
      androidTestImplementation("androidx.test.espresso:espresso-device:1.0.1")
    }

    Groovy

    dependencies {
      androidTestImplementation 'androidx.test.espresso:espresso-device:1.0.1'
    }

针对常见配置更改进行测试

Espresso Device API 提供了多种屏幕方向和可折叠状态,您可以使用它们来模拟设备配置更改。以下示例展示了如何触发这些设备状态并使用 Compose 测试规则来验证由此产生的 UI 更改。

针对屏幕旋转进行测试

以下是一个示例,展示了如何测试当设备屏幕旋转时您的应用会发生什么

  1. 首先,定义您的 Compose 测试规则,并将设备设置为一致的起始状态(例如纵向模式)

    import androidx.compose.ui.test.assertIsDisplayed
    import androidx.compose.ui.test.assertDoesNotExist
    import androidx.compose.ui.test.junit4.createComposeRule
    import androidx.compose.ui.test.onNodeWithTag
    import androidx.test.espresso.device.EspressoDevice.onDevice
    import androidx.test.espresso.device.action.ScreenOrientation
    import androidx.test.espresso.device.rules.ScreenOrientationRule
    import org.junit.Rule
    import org.junit.Test
    
    class MyConfigurationTest {
    
        // 1. Define the Compose test rule
        @get:Rule
        val composeTestRule = createComposeRule()
    
        // 2. Define the Espresso Device rule for a consistent starting state
        @get:Rule
        val screenOrientationRule = ScreenOrientationRule(ScreenOrientation.PORTRAIT)
    }
    
  2. 创建一个测试,在测试执行期间将设备设置为横向

    @Test
    fun myRotationTest() {
      ...
      // Sets the device to landscape orientation during test execution.
      onDevice().setScreenOrientation(ScreenOrientation.LANDSCAPE)
      ...
    }
    
  3. 屏幕旋转后,使用 composeTestRule 检查您的可组合项是否按预期适应了新状态。

    @Test
    fun myRotationTest() {
      ...
      // Sets the device to landscape orientation during test execution.
      onDevice().setScreenOrientation(ScreenOrientation.LANDSCAPE)
      composeTestRule.onNodeWithTag("NavRail").assertIsDisplayed()
      composeTestRule.onNodeWithTag("BottomBar").assertDoesNotExist()
    }
    

针对屏幕展开进行测试

以下是一个示例,展示了如何测试您的应用在可折叠设备上且屏幕展开时会发生什么

  1. 首先,通过调用 onDevice().setClosedMode() 在折叠状态下测试设备。确保您的可组合项能够适应紧凑的屏幕宽度。

    @Test
    fun myUnfoldedTest() {
      onDevice().setClosedMode()
      composeTestRule.onNodeWithTag("BottomBar").assertIsDisplayed()
      composeTestRule.onNodeWithTag("NavRail").assertDoesNotExist()
      ...
    }
    
  2. 要转换到完全展开状态,请调用 onDevice().setFlatMode()。检查可组合项是否适应了展开后的尺寸类别。

    @Test
    fun myUnfoldedTest() {
      onDevice().setClosedMode()
      ...
      onDevice().setFlatMode()
      composeTestRule.onNodeWithTag("NavRail").assertIsDisplayed()
      composeTestRule.onNodeWithTag("BottomBar").assertDoesNotExist()
    }
    

指定您的测试所需的设备

如果您在非折叠设备上运行执行折叠操作的测试,测试很可能会失败。要仅执行与当前运行的设备相关的测试,请使用 @RequiresDeviceMode 注解。测试运行程序会自动跳过在不支持所测试配置的设备上运行测试。您可以将设备要求规则添加到每个测试或整个测试类中。

例如,要指定某个测试仅应在支持展开到平面配置的设备上运行,请将以下 @RequiresDeviceMode 代码添加到您的测试中

@Test
@RequiresDeviceMode(mode = FLAT)
fun myUnfoldedTest() {
  ...
}