Escalonar seus testes com dispositivos gerenciados pelo Gradle

Os dispositivos gerenciados pelo Gradle melhoram a consistência, a performance e a confiabilidade dos testes instrumentados automatizados. Esse recurso, disponível para o nível 27 da API e versões mais recentes, permite configurar dispositivos de teste virtuais nos arquivos do Gradle do projeto. O sistema de compilação usa as configurações para gerenciar totalmente (criar, implantar e excluir) esses dispositivos ao executar seus testes automatizados.

Esse recurso concede visibilidade ao Gradle não apenas para os testes que você está executando, mas também para o ciclo de vida dos dispositivos, melhorando a qualidade da sua experiência de testes porque:

  • Processa problemas relacionados ao dispositivo para garantir que seus testes sejam executados.
  • Usa snapshots do emulador para melhorar o tempo de inicialização do dispositivo e o uso de memória e restaurar dispositivos para um estado limpo entre os testes.
  • Armazena em cache os resultados de testes e executa novamente apenas aqueles que provavelmente vão fornecer resultados diferentes.
  • Oferece um ambiente consistente para executar os testes entre execuções locais e remotas.

Além disso, os dispositivos gerenciados pelo Gradle introduzem um novo tipo de dispositivo de emulador, chamado de Dispositivo de teste automatizado (ATD), otimizado para melhorar a performance durante a execução de testes instrumentados. Combinado com o suporte à fragmentação de testes, é possível dividir o conjunto de testes em várias instâncias ATD para reduzir o tempo total de execução.

Criar um dispositivo gerenciado pelo Gradle

Você pode especificar um dispositivo virtual que vai ser usado pelo Gradle para testar o app no arquivo build.gradle do módulo. O exemplo de código abaixo cria um Pixel 2 executando o nível 30 da API como um dispositivo gerenciado pelo Gradle.

Groovy

android {
  testOptions {
    managedDevices {
      devices {
        pixel2api30 (com.android.build.api.dsl.ManagedVirtualDevice) {
          // Use device profiles you typically see in Android Studio.
          device = "Pixel 2"
          // Use only API levels 27 and higher.
          apiLevel = 30
          // To include Google services, use "google".
          systemImageSource = "aosp"
        }
      }
    }
  }
}

Kotlin

android {
  testOptions {
    managedDevices {
      devices {
        maybeCreate<com.android.build.api.dsl.ManagedVirtualDevice>("pixel2api30").apply {
          // Use device profiles you typically see in Android Studio.
          device = "Pixel 2"
          // Use only API levels 27 and higher.
          apiLevel = 30
          // To include Google services, use "google".
          systemImageSource = "aosp"
        }
      }
    }
  }
}

Para executar testes usando os dispositivos gerenciados pelo Gradle que você configurou, use o comando abaixo. device-name é o nome do dispositivo que você configurou no script de build do Gradle (como pixel2api30) e BuildVariant é a variante de build do app a ser testado.

gradlew device-nameBuildVariantAndroidTest

Definir grupos de dispositivos

Para dimensionar os testes em várias configurações de dispositivos, como diferentes níveis de API e formatos, você pode definir inúmeros dispositivos gerenciados pelo Gradle e adicioná-los a um grupo nomeado. O Gradle pode executar os testes em todos os dispositivos do grupo em paralelo.

O exemplo abaixo mostra dois dispositivos gerenciados adicionados a um grupo de dispositivos chamado phoneAndTablet.

Groovy

testOptions {
  managedDevices {
    devices {
      pixel2api29 (com.android.build.api.dsl.ManagedVirtualDevice) { ... }
      nexus9api30 (com.android.build.api.dsl.ManagedVirtualDevice) { ... }
    }
    groups {
      phoneAndTablet {
        targetDevices.add(devices.pixel2api29)
        targetDevices.add(devices.nexus9api30)
      }
    }
  }
}

Kotlin

testOptions {
  managedDevices {
    devices {
      maybeCreate<com.android.build.api.dsl.ManagedVirtualDevice>("pixel2api29").apply { ... }
      maybeCreate<com.android.build.api.dsl.ManagedVirtualDevice>("nexus9api30").apply { ... }
    }
    groups {
      maybeCreate("phoneAndTablet").apply {
        targetDevices.add(devices["pixel2api29"])
        targetDevices.add(devices["nexus9api30"])
      }
    }
  }
}

Para executar testes usando o grupo de dispositivos gerenciados pelo Gradle, use este comando:

gradlew group-nameGroupBuildVariantAndroidTest

Executar testes usando dispositivos de teste automatizados

Os dispositivos gerenciados pelo Gradle oferecem suporte a um novo tipo de dispositivo de emulador, chamado dispositivo de teste automatizado (ATD), que é otimizado para reduzir os recursos de CPU e memória ao executar testes instrumentados. Os ATDs melhoram a performance de execução porque:

  • Removem apps pré-instalados que geralmente não são úteis para testar seu app.
  • Desativam determinados serviços em segundo plano que normalmente não são úteis para testar o app.
  • Desativam a renderização de hardware.

Antes de começar, atualize o Android Emulator para a versão mais recente disponível. Em seguida, especifique uma imagem "-atd" ao definir um dispositivo gerenciado pelo Gradle no seu build.gradle, conforme mostrado abaixo.

Groovy

android {
  testOptions {
    managedDevices {
      devices {
        pixel2api30 (com.android.build.api.dsl.ManagedVirtualDevice) {
          // Use device profiles you typically see in Android Studio.
          device = "Pixel 2"
          // ATDs currently support only API level 30.
          apiLevel = 30
          // You can also specify "google-atd" if you require Google Play Services.
          systemImageSource = "aosp-atd"
        }
      }
    }
  }
}

Kotlin

android {
  testOptions {
    managedDevices {
      devices {
        maybeCreate<com.android.build.api.dsl.ManagedVirtualDevice>("pixel2api30").apply {
          // Use device profiles you typically see in Android Studio.
          device = "Pixel 2"
          // ATDs currently support only API level 30.
          apiLevel = 30
          // You can also specify "google-atd" if you require Google Play Services.
          systemImageSource = "aosp-atd"
        }
      }
    }
  }
}

Você também pode criar grupos de dispositivos da mesma forma que faz com outros dispositivos gerenciados pelo Gradle. Para aproveitar ainda mais as melhorias de performance, também é possível usar ATDs com fragmentação de testes para reduzir o tempo total de execução do teste do seu conjunto.

O que é removido das imagens ATD?

Além de operar em um modo headless, os ATDs também otimizam a performance removendo ou desativando apps e serviços que normalmente não são necessários para testar o código do seu app. A tabela abaixo fornece uma visão geral dos componentes removidos ou desativados em imagens ATD e descrições dos motivos pelos quais eles podem não ser úteis.

O que é removido nas imagens ATD Por que isso não é necessário ao executar testes automatizados?
Apps de produto do Google:
  • E-mail
  • Maps
  • Chrome
  • Mensagens
  • Play Store e outros
Os testes automatizados precisam se concentrar na lógica do próprio app, supondo que outros apps e a plataforma funcionam corretamente.

Com Espresso-Intents, você pode combinar e validar suas intents de saída ou inclusive disponibilizar respostas de stub em vez de respostas de intent reais.

Apps de Configurações e serviços:
  • CarrierConfig
  • EmergencyInfo
  • OneTimeInitializer
  • PhotoTable (protetores de tela)
  • Provisionamento
  • App Configurações
  • StorageManager
  • Configuração de APN de telefonia
  • WallpaperCropper
  • WallpaperPicker
Esses apps apresentam uma GUI para que os usuários finais mudem as configurações da plataforma, configurem o dispositivo ou gerenciem o armazenamento do dispositivo. Normalmente, isso está fora do escopo dos testes automatizados no nível do app.


Observação: o provedor de configurações ainda está disponível na imagem ATD.

SystemUI Os testes automatizados precisam se concentrar na lógica do próprio app, supondo que outros apps e a plataforma funcionam corretamente.
Apps e serviços do AOSP:
  • Browser2
  • Agenda
  • Camera2
  • Contatos
  • Telefone
  • DeskClock
  • Gallery2
  • LatinIME
  • Launcher3QuickStep
  • Música
  • QuickSearchBox
  • SettingsIntelligence
Normalmente, esses apps e serviços estão fora do escopo dos testes automatizados do código do app.

Ativar a fragmentação de testes

Os dispositivos gerenciados pelo Gradle oferecem suporte à fragmentação de testes, o que permite dividir seu conjunto de testes por várias instâncias de dispositivos virtuais idênticas, chamadas fragmentos, que são executadas em paralelo. O uso da fragmentação de testes ajuda a reduzir o tempo geral de execução do teste ao custo de outros recursos computacionais.

Para definir o número de fragmentos que você quer usar em uma determinada execução de teste, defina o seguinte no arquivo gradle.properties:

android.experimental.androidTest.numManagedDeviceShards=<number_of_shards>

Ao executar os testes usando essa opção, os dispositivos gerenciados pelo Gradle provisionam o número de fragmentos especificado para cada perfil de dispositivo na execução do teste. Por exemplo, se você implantou seus testes em um grupo de três dispositivos e definiu numManagedDeviceShards para dois, os dispositivos gerenciados pelo Gradle vão provisionar um total de seis dispositivos virtuais para a execução do teste.

Quando os testes são concluídos, o Gradle gera os resultados em um arquivo .proto para cada fragmento usado na execução.