Testar mudanças na configuração da tela com a API Espresso Device

Use a API Espresso Device para testar seu app quando o dispositivo passa por mudanças de configuração comuns, como rotação e desdobramento da tela. A API Espresso Device é a ferramenta recomendada para realizar ações no nível do dispositivo junto com as regras de teste do Jetpack Compose. Se você não tem experiência em escrever testes de UI para o Jetpack Compose, consulte Testar o layout do Compose.

Com a API Espresso Device, é possível acionar mudanças de configuração em um dispositivo virtual e executar os testes de forma síncrona. Assim, apenas uma ação ou declaração de IU acontece por vez, e os resultados do teste são mais confiáveis. Se você não tem experiência em escrever testes de interface com o Espresso, consulte a documentação.

Para usar a API Espresso Device, você precisa do seguinte:

  • Android Studio Iguana ou versão mais recente
  • Plug-in do Android para Gradle 8.3 ou mais recente
  • Android Emulator 33.1.10 ou versão mais recente
  • Dispositivo virtual Android que executa a API de nível 24 ou mais recente

Configurar o projeto para a API Espresso Device

Para configurar seu projeto para que ele seja compatível com a API Espresso Device, faça o seguinte:

  1. Para permitir que o teste transmita comandos ao dispositivo de teste, adicione as permissões de rede necessárias ao arquivo de manifesto no conjunto de origem androidTest:

      <uses-permission android:name="android.permission.INTERNET" />
      <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    

    Se o teste for destinado ao Android 17 (nível 37 da API) ou versões mais recentes, também será necessário declarar a permissão ACCESS_LOCAL_NETWORK:

      <uses-permission android:name="android.permission.ACCESS_LOCAL_NETWORK" />
    
  2. Ative a flag experimental enableEmulatorControl no arquivo gradle.properties:

      android.experimental.androidTest.enableEmulatorControl=true
    
  3. Ative a opção emulatorControl no script de build do módulo:

    Kotlin

      testOptions {
        emulatorControl {
          enable = true
        }
      }
      

    Groovy

      testOptions {
        emulatorControl {
          enable = true
        }
      }
      
  4. No script de build no nível do módulo, importe a biblioteca de dispositivos Espresso para seu projeto:

    Kotlin

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

    Groovy

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

Testar mudanças de configuração comuns

A API Espresso Device tem vários estados de orientação da tela e dobráveis que podem ser usados para acionar mudanças na configuração do dispositivo. Os exemplos a seguir mostram como acionar esses estados do dispositivo e verificar as mudanças resultantes na interface usando regras de teste do Compose.

Teste com rotação de tela

Para testar a rotação de tela, use a classe ScreenOrientationRule para definir a orientação do dispositivo durante o teste.

Confira um exemplo de como testar o que acontece com o app quando a tela do dispositivo gira:

  1. Primeiro, defina sua regra de teste do Compose e use a classe ScreenOrientationRule para definir o dispositivo em um estado inicial consistente (como o modo retrato):

    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)
    }
    

    Se o teste for destinado ao Android 17 (nível 37 da API) ou versões mais recentes, a API de dispositivo do Espresso vai exigir a permissão ACCESS_LOCAL_NETWORK. É preciso garantir que essa permissão seja concedida antes da execução da regra ScreenOrientationRule. Use o RuleChain do JUnit para executar a regra GrantPermissionRule primeiro:

    import androidx.test.rule.GrantPermissionRule
    import org.junit.rules.RuleChain
    
    class MyConfigurationTest {
        val grantPermissionRule = GrantPermissionRule.grant(android.Manifest.permission.ACCESS_LOCAL_NETWORK)
        val composeTestRule = createComposeRule()
        val screenOrientationRule = ScreenOrientationRule(ScreenOrientation.PORTRAIT)
    
        @get:Rule
        val chain = RuleChain
            .outerRule(grantPermissionRule)
            .around(composeTestRule)
            .around(screenOrientationRule)
    }
    
  2. Crie um teste que defina a orientação paisagem no dispositivo durante a execução:

    @Test
    fun myRotationTest() {
      ...
      // Sets the device to landscape orientation during test execution.
      onDevice().setScreenOrientation(ScreenOrientation.LANDSCAPE)
      ...
    }
    
  3. Depois que a tela girar, use composeTestRule para verificar se os combináveis se adaptam ao novo estado conforme esperado.

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

Teste contra o desdobramento da tela

Confira um exemplo de como testar o que acontece com seu app se ele estiver em um dispositivo dobrável e a tela for aberta:

  1. Primeiro, teste com o dispositivo dobrado chamando onDevice().setClosedMode(). Verifique se os elementos combináveis se adaptam à largura de tela compacta.

    @Test
    fun myUnfoldedTest() {
      onDevice().setClosedMode()
      composeTestRule.onNodeWithTag("BottomBar").assertIsDisplayed()
      composeTestRule.onNodeWithTag("NavRail").assertDoesNotExist()
      ...
    }
    
  2. Para fazer a transição para um estado totalmente desdobrado, chame onDevice().setFlatMode(). Verifique se os combináveis se adaptam à classe de tamanho expandida.

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

Especificar quais dispositivos seus testes precisam

Se você estiver executando um teste que realiza ações de dobra em um dispositivo que não é dobrável, é provável que o teste falhe. Para executar apenas os testes relevantes para o dispositivo em execução, use a anotação @RequiresDeviceMode. O executor de testes ignora automaticamente a execução de testes em dispositivos que não são compatíveis com a configuração testada. É possível adicionar a regra de requisito de dispositivo a cada teste ou a uma classe de teste inteira.

Por exemplo, para especificar que um teste só deve ser executado em dispositivos que oferecem suporte ao desdobramento em uma configuração plana, adicione o seguinte código @RequiresDeviceMode ao teste:

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