Skalowanie testów za pomocą urządzeń zarządzanych przez kompilację

Urządzenia zarządzane przez kompilację zwiększają spójność, wydajność i niezawodność zautomatyzowanych testów z instrumentacją. Ta funkcja, dostępna na poziomach interfejsu API 27 i wyższych, umożliwia konfigurowanie wirtualnych lub zdalnych fizycznych urządzeń testowych w plikach Gradle projektu. Wtyczka Androida do Gradle używa konfiguracji do pełnego zarządzania tymi urządzeniami, czyli ich tworzenia, wdrażania i usuwania, podczas wykonywania testów automatycznych.

Ta funkcja zapewnia wtyczce Androida do Gradle wgląd nie tylko w przeprowadzane testy, ale też w cykl życia urządzeń, co poprawia jakość testowania w następujący sposób:

  • Rozwiązuje problemy związane z urządzeniami, aby zapewnić wykonanie testów.
  • W przypadku urządzeń wirtualnych używa migawek emulatora, aby skrócić czas uruchamiania urządzenia i zmniejszyć zużycie pamięci oraz przywracać urządzenia do stanu początkowego między testami.
  • buforuje wyniki testów i ponownie uruchamia tylko te testy, które mogą dać inne wyniki;
  • Zapewnia spójne środowisko do przeprowadzania testów lokalnych i zdalnych.

Tworzenie wirtualnego urządzenia zarządzanego przez kompilację

W pliku kompilacji na poziomie modułu możesz określić urządzenie wirtualne, którego chcesz używać do testowania aplikacji. Poniższy przykładowy kod tworzy urządzenie Pixel 2 z poziomem API 30 jako urządzenie zarządzane przez kompilację.

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

Definiowanie grup urządzeń

Aby ułatwić skalowanie testów na różnych konfiguracjach urządzeń, np. na różnych poziomach interfejsu API i w różnych formatach, możesz zdefiniować wiele urządzeń zarządzanych przez kompilację i dodać je do nazwanej grupy. Wtyczka Androida do obsługi Gradle może wtedy równolegle uruchamiać testy na wszystkich urządzeniach w grupie.

W przykładzie poniżej pokazano 2 urządzenia dodane do grupy urządzeń o nazwie 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)
      }
    }
  }
}

Przeprowadzanie testów

Aby uruchomić testy na skonfigurowanych urządzeniach zarządzanych przez kompilację, użyj tego polecenia: device-name to nazwa urządzenia skonfigurowanego w skrypcie kompilacji Gradle (np. pixel2api30), a BuildVariant to wariant kompilacji aplikacji, którą chcesz przetestować, np. Debug.

Linux i macOS

./gradlew device-nameBuildVariantAndroidTest

Windows

gradlew device-nameBuildVariantAndroidTest

Aby uruchomić testy na grupie urządzeń zarządzanych przez kompilację, użyj tego polecenia:

Linux i macOS

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

Windows

gradlew group-nameGroupBuildVariantAndroidTest

Dane wyjściowe testu zawierają ścieżkę do pliku HTML z raportem z testu. Możesz też zaimportować wyniki testów do Android Studio, aby przeprowadzić dalszą analizę. W tym celu w IDE kliknij Uruchom > Historia testów.

Włącz podział testów

Urządzenia zarządzane przez kompilację obsługują dzielenie testów na fragmenty, co pozwala podzielić pakiet testów na kilka identycznych instancji wirtualnych urządzeń, zwanych fragmentami, które działają równolegle. Dzielenie testów na części może pomóc skrócić ogólny czas wykonywania testów kosztem dodatkowych zasobów obliczeniowych.

Aby ustawić liczbę fragmentów, których chcesz użyć w danym teście, w pliku gradle.properties ustaw te wartości:

android.experimental.androidTest.numManagedDeviceShards=<number_of_shards>
spróbuj zmniejszyć liczbę żądanych urządzeń, zmniejszając liczbę unikalnych urządzeń lub liczbę fragmentów na urządzenie.

Podczas przeprowadzania testów przy użyciu tej opcji urządzenia zarządzane przez kompilację udostępniają liczbę fragmentów określoną dla każdego profilu urządzenia w przeprowadzonym teście. Jeśli na przykład wdrożysz testy w grupie 3 urządzeń i ustawisz wartość numManagedDeviceShards na 2, urządzenia zarządzane przez kompilację udostępnią łącznie 6 urządzeń wirtualnych na potrzeby testu.

Po zakończeniu testów Gradle generuje wyniki testów w .proto pliku dla każdego fragmentu użytego w teście.

Korzystanie z automatycznych urządzeń testowych

Urządzenia zarządzane przez kompilację obsługują typ urządzenia emulującego o nazwie Automated Test Device (ATD), który jest zoptymalizowany pod kątem zmniejszania zużycia zasobów procesora i pamięci podczas przeprowadzania testów instrumentalnych. ATD poprawiają wydajność w czasie działania na kilka sposobów:

  • Usuń wstępnie zainstalowane aplikacje, które zwykle nie są przydatne do testowania aplikacji.
  • wyłączanie niektórych usług działających w tle, które zwykle nie są przydatne do testowania aplikacji;
  • Wyłączanie renderowania sprzętowego

Zanim zaczniesz, zaktualizuj emulator Androida do najnowszej dostępnej wersji. Następnie określ obraz „-atd” podczas definiowania urządzenia zarządzanego przez kompilację w pliku kompilacji na poziomie modułu, jak pokazano poniżej:

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

Możesz też tworzyć grupy urządzeń, tak jak w przypadku innych urządzeń zarządzanych przez producenta. Aby jeszcze bardziej zwiększyć wydajność, możesz też używać ATD z dzieleniem testów, aby skrócić całkowity czas wykonywania pakietu testów.

Co jest usuwane z obrazów ATD?

Oprócz działania w trybie bez interfejsu ATD optymalizują też wydajność przez usuwanie lub wyłączanie aplikacji i usług, które zwykle nie są wymagane do testowania kodu aplikacji. W tabeli poniżej znajdziesz omówienie komponentów, które usunęliśmy lub wyłączyliśmy w przypadku obrazów ATD, oraz wyjaśnienie, dlaczego mogą one być nieprzydatne.

Co jest usuwane z obrazów ATD Dlaczego podczas przeprowadzania testów automatycznych może to nie być konieczne
Aplikacje usług Google:
  • Poczta
  • Map
  • Chrome
  • Wiadomości
  • Sklep Play i inne
Testy automatyczne powinny koncentrować się na logice Twojej aplikacji, przy założeniu, że inne aplikacje lub platforma będą działać prawidłowo.

Za pomocą Espresso-Intents możesz dopasowywać i weryfikować wychodzące intencje, a nawet podawać odpowiedzi zastępcze zamiast rzeczywistych odpowiedzi na intencje.

Ustawienia aplikacji i usług:
  • CarrierConfig
  • EmergencyInfo
  • OneTimeInitializer
  • PhotoTable (wygaszacze ekranu)
  • Finansowanie
  • Aplikacja Ustawienia
  • StorageManager
  • Konfiguracja APN połączeń telefonicznych
  • WallpaperCropper
  • WallpaperPicker
Te aplikacje udostępniają interfejs graficzny, który umożliwia użytkownikom zmianę ustawień platformy, konfigurowanie urządzenia i zarządzanie jego pamięcią. Zwykle wykracza to poza zakres automatycznego testowania na poziomie aplikacji.


Uwaga: dostawca ustawień jest nadal dostępny w obrazie ATD.

SystemUI Testy automatyczne powinny koncentrować się na logice Twojej aplikacji, przy założeniu, że inne aplikacje lub platforma będą działać prawidłowo.
Aplikacje i usługi AOSP:
  • Przeglądarka2
  • Kalendarz
  • Camera2
  • kontakty,
  • Dialer
  • DeskClock
  • Galeria 2
  • LatinIME
  • Launcher3QuickStep
  • Muzyka
  • QuickSearchBox
  • SettingsIntelligence
Te aplikacje i usługi zwykle nie są objęte automatycznymi testami kodu aplikacji.

Korzystanie z urządzeń Laboratorium Firebase

Gdy używasz urządzeń zarządzanych przez kompilację, możesz przeprowadzać zautomatyzowane testy z instrumentacją na dużą skalę na urządzeniach Firebase Test Lab. Test Lab umożliwia jednoczesne przeprowadzanie testów na wielu urządzeniach z Androidem – zarówno fizycznych, jak i wirtualnych. Testy te są przeprowadzane w zdalnych centrach danych Google. Dzięki obsłudze urządzeń zarządzanych przez kompilację system kompilacji może w pełni zarządzać testami na tych urządzeniach Test Lab na podstawie Twoich konfiguracji.

Rozpocznij

Poniżej znajdziesz instrukcje, jak zacząć korzystać z urządzeń Laboratorium Firebase z urządzeniami zarządzanymi przez kompilację. W tych krokach używamy gcloud CLI do podawania danych logowania użytkownika, co może nie mieć zastosowania we wszystkich środowiskach programistycznych. Więcej informacji o tym, jakiego procesu uwierzytelniania użyć w swoim przypadku, znajdziesz w artykule Jak działają domyślne dane logowania aplikacji.

  1. Aby utworzyć projekt Firebase, otwórz konsolę Firebase. Kliknij Dodaj projekt i postępuj zgodnie z instrukcjami wyświetlanymi na ekranie, aby utworzyć projekt. Zapamiętaj identyfikator projektu.

  2. Aby zainstalować Google Cloud CLI, wykonaj czynności opisane w artykule Instalowanie interfejsu wiersza poleceń gcloud.

  3. Skonfiguruj środowisko lokalne.

    1. Połącz z projektem Firebase w gcloud:

      gcloud config set project FIREBASE_PROJECT_ID
      
    2. autoryzować używanie danych logowania użytkownika w celu uzyskania dostępu do interfejsu API; Zalecamy autoryzację przez przekazanie do Gradle pliku JSON konta usługi za pomocą DSL w skrypcie kompilacji na poziomie modułu:

      Kotlin

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

      Groovy

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

      Możesz też autoryzować ręcznie za pomocą tego polecenia terminala:

      gcloud auth application-default login
      
    3. Opcjonalnie: dodaj projekt Firebase jako projekt limitu. Ten krok jest potrzebny tylko wtedy, gdy przekroczysz bezpłatny limit Test Lab.

      gcloud auth application-default set-quota-project FIREBASE_PROJECT_ID
      
  4. Włącz wymagane interfejsy API.

    Na stronie Biblioteka interfejsów API w konsoli Google Developers włącz Cloud Testing APICloud Tool Results API. Aby to zrobić, wpisz nazwy tych interfejsów API w polu wyszukiwania u góry konsoli, a potem na stronie przeglądu każdego interfejsu API kliknij Włącz interfejs API.

  5. Skonfiguruj projekt na Androida.

    1. Dodaj wtyczkę Laboratorium Firebase w skrypcie kompilacji najwyższego poziomu:

      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. Włącz niestandardowe typy urządzeń w pliku gradle.properties:

      android.experimental.testOptions.managedDevices.customDevice=true
    3. Dodaj wtyczkę Laboratorium Firebase w skrypcie kompilacji na poziomie modułu:

      Kotlin

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

      Groovy

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

Określanie urządzenia w Test Lab

W skrypcie kompilacji na poziomie modułu możesz określić urządzenie Firebase Test Lab, którego Gradle ma używać do testowania aplikacji. Poniższy przykładowy kod tworzy urządzenie Pixel 3 z poziomem interfejsu API 30 jako urządzenie Laboratorium zarządzane przez kompilację o nazwie ftlDevice. Blok firebaseTestLab {} jest dostępny po zastosowaniu wtyczki com.google.firebase.testlab w module.

Kotlin

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

Groovy

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

Aby zdefiniować grupę urządzeń zarządzanych w ramach kompilacji, w tym urządzeń Laboratorium testów Firebase, zapoznaj się z sekcją Definiowanie grup urządzeń.

Aby uruchomić testy, użyj tych samych poleceń, których używasz do uruchamiania innych urządzeń zarządzanych przez kompilację. Pamiętaj, że Gradle nie uruchamia testów równolegle ani nie obsługuje innych konfiguracji interfejsu wiersza poleceń Google Cloud na urządzeniach Test Lab.

Optymalizowanie przebiegów testów za pomocą inteligentnego dzielenia na części

Testowanie na urządzeniach Laboratorium zarządzanych przez kompilację obsługuje inteligentne dzielenie na fragmenty. Inteligentne dzielenie na partycje automatycznie rozdziela testy na partycje w taki sposób, aby każda z nich była wykonywana przez mniej więcej taki sam czas. Dzięki temu zmniejsza się nakład pracy związany z ręcznym przydzielaniem testów i skraca się ogólny czas wykonywania testów. Inteligentne dzielenie na fragmenty wykorzystuje historię testów lub informacje o tym, jak długo trwały one wcześniej, aby optymalnie rozdzielać testy. Pamiętaj, że aby korzystać z inteligentnego dzielenia na partycje, musisz mieć wtyczkę Gradle do Laboratorium Firebase w wersji 0.0.1-alpha05.

Aby włączyć inteligentne dzielenie na części, określ czas, jaki powinny zająć testy w każdej części. Aby uniknąć sytuacji, w której fragmenty zostaną anulowane przed zakończeniem testów, ustaw czas trwania fragmentu docelowego na co najmniej 5 minut krótszy niż timeoutMinutes.

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

Więcej informacji znajdziesz w artykule Opcje DSL urządzenia w Laboratorium testów Firebase.

Zaktualizowany DSL dla urządzeń w Laboratorium

Możesz skonfigurować więcej opcji DSL, aby dostosować przebieg testów lub przeprowadzić migrację z innych rozwiązań, których być może już używasz. Niektóre z tych opcji znajdziesz w poniższym fragmencie kodu.

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