Scalare i test con dispositivi gestiti dalla build

I dispositivi gestiti dalla build migliorano la coerenza, le prestazioni e l'affidabilità dei test strumentati automatici. Questa funzionalità, disponibile per i livelli API 27 e successivi, consente di configurare dispositivi di test fisici virtuali o remoti nei file Gradle del progetto. Il plug-in Android Gradle utilizza le configurazioni per gestire completamente, ovvero creare, eseguire il deployment e smantellare, questi dispositivi durante l'esecuzione dei test automatizzati.

Questa funzionalità consente al plug-in Android Gradle di avere visibilità non solo sui test che stai eseguendo, ma anche sul ciclo di vita dei dispositivi, migliorando così la qualità della tua esperienza di test nei seguenti modi:

  • Gestisce i problemi relativi ai dispositivi per garantire l'esecuzione dei test
  • Per i dispositivi virtuali, utilizza gli snapshot dell'emulatore per migliorare il tempo di avvio del dispositivo e l'utilizzo della memoria e ripristinare i dispositivi a uno stato pulito tra i test.
  • Memorizza nella cache i risultati dei test e ripete solo i test che potrebbero fornire risultati diversi
  • Fornisce un ambiente coerente per l'esecuzione dei test tra le esecuzioni di test locali e remoti

Crea un dispositivo virtuale gestito dalla build

Puoi specificare un dispositivo virtuale da utilizzare per testare la tua app nel file di build a livello di modulo. Il seguente esempio di codice crea un Pixel 2 che esegue il livello API 30 come dispositivo gestito dalla build.

Kotlin

android {
  testOptions {
    managedDevices {
      localDevices {
        create("pixel2api30") {
          // 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"
        }
      }
    }
  }
}

Groovy

android {
  testOptions {
    managedDevices {
      localDevices {
        pixel2api30 {
          // 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"
        }
      }
    }
  }
}

Definisci gruppi di dispositivi

Per aiutarti a scalare i test su più configurazioni di dispositivi, ad esempio diversi livelli API e fattori di forma, puoi definire più dispositivi gestiti dalla build e aggiungerli a un gruppo denominato. Il plug-in Android Gradle può quindi eseguire i test su tutti i dispositivi del gruppo in parallelo.

L'esempio seguente mostra due dispositivi aggiunti a un gruppo di dispositivi chiamato phoneAndTablet.

Kotlin

testOptions {
  managedDevices {
    localDevices {
      create("pixel2api29") { ... }
      create("nexus9api30") { ... }
    }
    groups {
      create("phoneAndTablet") {
        targetDevices.add(devices["pixel2api29"])
        targetDevices.add(devices["nexus9api30"])
      }
    }
  }
}

Groovy

testOptions {
  managedDevices {
    localDevices {
      pixel2api29 { ... }
      nexus9api30 { ... }
    }
    groups {
      phoneAndTablet {
        targetDevices.add(devices.pixel2api29)
        targetDevices.add(devices.nexus9api30)
      }
    }
  }
}

Esegui i test

Per eseguire i test utilizzando i dispositivi gestiti dalla build che hai configurato, utilizza il comando seguente. device-name è il nome del dispositivo che hai configurato nello script di build Gradle (ad esempio pixel2api30) e BuildVariant è la variante di build dell'app che vuoi testare, ad esempio Debug.

Linux e macOS

./gradlew device-nameBuildVariantAndroidTest

Windows

gradlew device-nameBuildVariantAndroidTest

Per eseguire i test su un gruppo di dispositivi gestiti dalla build, utilizza il comando seguente.

Linux e macOS

./gradlew group-nameGroupBuildVariantAndroidTest
./gradlew group-nameGroupBuildVariantAndroidTest

Windows

gradlew group-nameGroupBuildVariantAndroidTest

L'output del test include un percorso a un file HTML contenente il report del test. Puoi anche importare i risultati dei test in Android Studio per un'analisi più approfondita facendo clic su Esegui > Cronologia test nell'IDE.

Abilita lo sharding dei test

I dispositivi gestiti dalla build supportano la suddivisione dei test, che consente di dividere la suite di test in un numero di istanze di dispositivi virtuali identiche, chiamate shard, che vengono eseguite in parallelo. L'utilizzo dello sharding dei test può contribuire a ridurre il tempo complessivo di esecuzione dei test a scapito di risorse di calcolo aggiuntive.

Per impostare il numero di shard che vuoi utilizzare in una determinata esecuzione del test, imposta quanto segue nel file gradle.properties:

android.experimental.androidTest.numManagedDeviceShards=<number_of_shards>

Quando esegui i test utilizzando questa opzione, i dispositivi gestiti dalla build forniscono il numero di shard specificato per ogni profilo del dispositivo nell'esecuzione del test. Ad esempio, se hai eseguito il deployment dei test in un gruppo di tre dispositivi e hai impostato numManagedDeviceShards su due, i dispositivi gestiti dalla build eseguiranno il provisioning di un totale di sei dispositivi virtuali per l'esecuzione del test.

Al termine dei test, Gradle restituisce i risultati in un file .proto per ogni shard utilizzato nell'esecuzione del test.

Utilizzare i dispositivi di test automatici

I dispositivi gestiti dalla build supportano un tipo di dispositivo emulatore chiamato Automated Test Device (ATD), ottimizzato per ridurre le risorse di CPU e memoria durante l'esecuzione dei test strumentati. Gli ATD migliorano le prestazioni di runtime in diversi modi:

  • Rimuovi le app preinstallate che in genere non sono utili per testare la tua app
  • Disattiva alcuni servizi in background che in genere non sono utili per testare l'app
  • Disattivare il rendering hardware

Prima di iniziare, assicurati di aggiornare l'emulatore Android all'ultima versione disponibile. Poi, specifica un'immagine "-atd" quando definisci un dispositivo gestito dalla build nel file di build a livello di modulo, come mostrato di seguito:

Kotlin

android {
  testOptions {
    managedDevices {
      localDevices {
        create("pixel2api30") {
          // 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"
        }
      }
    }
  }
}

Groovy

android {
  testOptions {
    managedDevices {
      localDevices {
        pixel2api30 {
          // 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"
        }
      }
    }
  }
}

Puoi anche creare gruppi di dispositivi come con altri dispositivi gestiti dalla build. Per sfruttare ulteriormente i miglioramenti delle prestazioni, puoi anche utilizzare i test automatici dei dispositivi con lo sharding dei test per ridurre il tempo totale di esecuzione dei test della tua suite di test.

Cosa viene rimosso dalle immagini ATD?

Oltre a funzionare in modalità headless, i dispositivi di test automatico ottimizzano le prestazioni rimuovendo o disattivando app e servizi che in genere non sono necessari per testare il codice dell'app. La tabella seguente fornisce una panoramica dei componenti che abbiamo rimosso o disattivato nelle immagini e nelle descrizioni ATD e dei motivi per cui potrebbero non essere utili.

Cosa viene rimosso dalle immagini ATD Perché potresti non averne bisogno quando esegui test automatici
App di prodotti Google:
  • Mail
  • Maps
  • Chrome
  • Messaggi
  • Play Store e altri
I test automatici devono concentrarsi sulla logica della tua app, presupponendo che le altre app o la piattaforma funzionino correttamente.

Con Espresso-Intents, puoi abbinare e convalidare gli intent in uscita o persino fornire risposte stub al posto delle risposte effettive degli intent.

App e servizi di impostazioni:
  • CarrierConfig
  • EmergencyInfo
  • OneTimeInitializer
  • PhotoTable (salvaschermi)
  • Provisioning
  • App Impostazioni
  • StorageManager
  • Configurazione APN telefonia
  • WallpaperCropper
  • WallpaperPicker
Queste app presentano una GUI per gli utenti finali per modificare le impostazioni della piattaforma, configurare il dispositivo o gestire lo spazio di archiviazione del dispositivo. In genere, questo non rientra nell'ambito dei test automatizzati a livello di app.


Nota: Settings provider è ancora disponibile nell'immagine ATD.

SystemUI I test automatici devono concentrarsi sulla logica della tua app, presupponendo che le altre app o la piattaforma funzionino correttamente.
App e servizi AOSP:
  • Browser2
  • Calendar
  • Camera2
  • Contatti
  • Telefono
  • DeskClock
  • Galleria 2
  • LatinIME
  • Launcher3QuickStep
  • Musica
  • QuickSearchBox
  • SettingsIntelligence
Queste app e questi servizi in genere non rientrano nell'ambito dei test automatizzati per il codice della tua app.

Utilizzare i dispositivi Firebase Test Lab

Puoi eseguire i test strumentati automatizzati su larga scala sui dispositivi Firebase Test Lab quando utilizzi dispositivi gestiti dalla build. Test Lab ti consente di eseguire i test contemporaneamente su una vasta gamma di dispositivi Android, sia fisici che virtuali. Questi test vengono eseguiti nei data center remoti di Google. Con il supporto dei dispositivi gestiti dalla build, il sistema di build può gestire completamente l'esecuzione dei test su questi dispositivi Test Lab in base alle tue configurazioni.

Inizia

I seguenti passaggi descrivono come iniziare a utilizzare i dispositivi Firebase Test Lab con dispositivi gestiti dalla build. Questi passaggi utilizzano gcloud CLI per fornire le credenziali utente, che potrebbero non essere applicabili a tutti gli ambienti di sviluppo. Per ulteriori informazioni su quale processo di autenticazione utilizzare per le tue esigenze, consulta Come funzionano le credenziali predefinite dell'applicazione.

  1. Per creare un progetto Firebase, vai alla Console Firebase. Fai clic su Aggiungi progetto e segui le istruzioni sullo schermo per creare un progetto. Ricorda l'ID progetto.

  2. Per installare Google Cloud CLI, segui i passaggi descritti in Installa gcloud CLI.

  3. Configura l'ambiente locale.

    1. Collega il tuo progetto Firebase in gcloud:

      gcloud config set project FIREBASE_PROJECT_ID
      
    2. Autorizza l'utilizzo delle tue credenziali utente per l'accesso API. Ti consigliamo di autorizzare passando un file JSON dell'account di servizio a Gradle utilizzando la DSL nello script di build a livello di modulo:

      Kotlin

      firebaseTestLab {
        ...
        serviceAccountCredentials.set(file(SERVICE_ACCOUNT_JSON_FILE))
      }

      Groovy

      firebaseTestLab {
        ...
        serviceAccountCredentials = file(SERVICE_ACCOUNT_JSON_FILE)
      }

      In alternativa, puoi autorizzare manualmente utilizzando il seguente comando del terminale:

      gcloud auth application-default login
      
    3. (Facoltativo) Aggiungi il tuo progetto Firebase come progetto quota. Questo passaggio è necessario solo se superi la quota senza costi per Test Lab.

      gcloud auth application-default set-quota-project FIREBASE_PROJECT_ID
      
  4. Abilita le API richieste.

    Nella pagina della libreria API di Google Developers Console, abilita l'API Cloud Testing e l'API Cloud Tool Results digitando i nomi di queste API nella casella di ricerca nella parte superiore della console, quindi facendo clic su Abilita API nella pagina di panoramica di ogni API.

  5. Configura il progetto Android.

    1. Aggiungi il plug-in Firebase Test Lab nello script di build di primo livello:

      Kotlin

      plugins {
        ...
        id("com.google.firebase.testlab") version "0.0.1-alpha05" apply false
      }

      Groovy

      plugins {
        ...
        id 'com.google.firebase.testlab' version '0.0.1-alpha05' apply false
      }
    2. Attiva i tipi di dispositivo personalizzati nel file gradle.properties:

      android.experimental.testOptions.managedDevices.customDevice=true
    3. Aggiungi il plug-in Firebase Test Lab nello script di build a livello di modulo:

      Kotlin

      plugins {
       ...
       id "com.google.firebase.testlab"
      }

      Groovy

      plugins {
       ...
       id 'com.google.firebase.testlab'
      }

Specificare un dispositivo Test Lab

Puoi specificare un dispositivo Firebase Test Lab da utilizzare per testare la tua app nello script di build a livello di modulo. Il seguente esempio di codice crea un Pixel 3 con livello API 30 come dispositivo Test Lab gestito dalla build chiamato ftlDevice. Il blocco firebaseTestLab {} è disponibile quando applichi il plug-in com.google.firebase.testlab al modulo.

Kotlin

firebaseTestLab {
  managedDevices {
    create("ftlDevice") {
      device = "Pixel3"
      apiLevel = 30
    }
  }
  ...
}

Groovy

firebaseTestLab {
  managedDevices {
    ftlDevice {
      device = "Pixel3"
      apiLevel = 30
    }
  }
  ...
}

Per definire un gruppo di dispositivi gestiti dalla build, inclusi i dispositivi Firebase Test Lab, consulta Definire gruppi di dispositivi.

Per eseguire i test, utilizza gli stessi comandi utilizzati per eseguire altri dispositivi gestiti dalla build. Tieni presente che Gradle non esegue i test in parallelo né supporta altre configurazioni di Google Cloud CLI per i dispositivi Test Lab.

Ottimizzare le esecuzioni dei test con lo sharding intelligente

I test sui dispositivi Test Lab gestiti dalla build supportano lo sharding intelligente. Lo sharding intelligente distribuisce automaticamente i test tra gli shard in modo che ogni shard venga eseguito per circa lo stesso tempo, riducendo gli sforzi di allocazione manuale e la durata complessiva dell'esecuzione dei test. Lo sharding intelligente utilizza la cronologia dei test o le informazioni sulla durata dei test eseguiti in precedenza per distribuire i test in modo ottimale. Tieni presente che per utilizzare la suddivisione intelligente è necessaria la versione 0.0.1-alpha05 del plug-in Gradle per Firebase Test Lab.

Per attivare lo sharding intelligente, specifica la quantità di tempo che devono impiegare i test all'interno di ogni shard. Devi impostare la durata del tempo di esecuzione del target shard su almeno cinque minuti in meno di timeoutMinutes per evitare che gli shard vengano annullati prima che i test possano terminare.

firebaseTestLab {
  ...
  testOptions {
    targetedShardDurationMinutes = 2
  }
}

Per saperne di più, leggi le opzioni DSL del dispositivo Firebase Test Lab.

DSL aggiornato per i dispositivi Test Lab

Sono disponibili altre opzioni DSL che puoi configurare per personalizzare le esecuzioni dei test o eseguire la migrazione da altre soluzioni che potresti già utilizzare. Vedi alcune di queste opzioni come descritto nel seguente snippet di codice.

firebaseTestLab {
  ...

  /**
   * A path to a JSON file that contains service account credentials to access to
   * a Firebase Test Lab project.
   */
  serviceAccountCredentials.set(file("your_service_account_credentials.json"))


  testOptions {
    fixture {
      /**
       * Whether to grant permissions on the device before tests begin.
       * Available options are "all" or "none".
       *
       * Default value is "all".
       */
      grantedPermissions = "all"

      /**
       * Map of files to push to the device before starting the test.
       *
       * The key is the location on the device.
       * The value is the location of the file, either local or in Google Cloud.
       */
      extraDeviceFiles["/sdcard/dir1/file1.txt"] = "local/file.txt"
      extraDeviceFiles["/sdcard/dir2/file2.txt"] = "gs://bucket/file.jpg"

      /**
       * The name of the network traffic profile.
       *
       * Specifies network conditions to emulate when running tests.
       *
       * Default value is empty.
       */
      networkProfile = "LTE"
    }

    execution {
      /**
       * The maximum time to run the test execution before cancellation,
       * measured in minutes. Does not include the setup or teardown of device,
       * and is handled server-side.
       *
       * The maximum possible testing time is 45 minutes on physical devices
       * and 60 minutes on virtual devices.
       *
       * Defaults to 15 minutes.
       */
       timeoutMinutes = 30

      /**
       * Number of times the test should be rerun if tests fail.
       * The number of times a test execution should be retried if one
       * or more of its test cases fail.
       *
       * The max number of times is 10.
       *
       * The default number of times is 0.
       */
      maxTestReruns = 2

      /**
       * Ensures only a single attempt is made for each execution if
       * an infrastructure issue occurs. This doesn't affect `maxTestReruns`.
       * Normally, two or more attempts are made by Firebase Test Lab if a
       * potential infrastructure issue is detected. This is best enabled for
       * latency sensitive workloads. The number of execution failures might be
       * significantly greater with `failFast` enabled.
       *
       * Defaults to false.
       */
      failFast = false

      /**
       * The number of shards to split the tests across.
       *
       * Default to 0 for no sharding.
       */
      numUniformShards = 20
    }

    /**
     * For smart sharding, the target length of time each shard should takes in
     * minutes. Maxes out at 50 shards for physical devices and 100 shards for
     * virtual devices.
     *
     * Only one of numUniformShards or targetedShardDurationMinutes can be set.
     *
     * Defaults to 0 for no smart sharding.
     */
     targetedShardDurationMinutes = 15
    }

    results {
      /**
       * The name of the Google storage bucket to store the test results in.
       *
       * If left unspecified, the default bucket is used.
       *
       * Please refer to Firebase Test Lab permissions for required permissions
       * for using the bucket.
       */
      cloudStorageBucket = "bucketLocationName"

      /**
       * Name of test results for the Firebase console history list.
       * All tests results with the same history name are grouped
       * together in the Firebase console in a time-ordered test history list.
       *
       * Defaults to the application label in the APK manifest.
       */
      resultsHistoryName = "application-history"

      /**
       * List of paths to copy from the test device's storage to the test
       * results folder. These must be absolute paths under /sdcard or
       * /data/local/tmp.
       */
      directoriesToPull.addAll(
        "/sdcard/path/to/something"
      )

      /**
       * Whether to enable video recording during the test.
       *
       * Disabled by default.
       */
      recordVideo = false

      /**
       * Whether to enable performance metrics. If enabled, monitors and records
       * performance metrics such as CPU, memory, and network usage.
       *
       * Defaults to false.
       */
      performanceMetrics = true
  }
}