Skalowanie testów przy użyciu urządzeń zarządzanych przez Gradle

Urządzenia zarządzane przez Gradle zwiększają spójność, wydajność i niezawodność zautomatyzowanych testów instrumentowanych. Ta funkcja, dostępna w przypadku interfejsów API na poziomie 27 i wyższych, pozwala konfigurować wirtualne lub zdalne fizyczne urządzenia testowe w plikach Gradle projektu. System kompilacji korzysta z konfiguracji do pełnego zarządzania, czyli tworzenia, wdrażania i demontowania tych urządzeń podczas przeprowadzania automatycznych testów.

Ta funkcja zapewnia Gradle wgląd nie tylko w prowadzone testy, ale także do cyklu życia urządzeń, co pozwala poprawić jakość testów na następujące sposoby:

  • Rozwiązuje problemy związane z urządzeniem, aby mieć pewność, że testy zostaną wykonane
  • W przypadku urządzeń wirtualnych używa zrzutów emulatora, aby skrócić czas uruchamiania urządzenia i wykorzystać pamięć oraz przywrócić urządzenia do nienaruszonego stanu między testami
  • Buforuje wyniki testów i ponownie uruchamia tylko te testy, które prawdopodobnie dostarczą inne wyniki
  • Zapewnia spójne środowisko do przeprowadzania testów między lokalnymi i zdalnymi uruchomieniami testowymi

Tworzenie wirtualnego urządzenia zarządzanego przez Gradle

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

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

Odlotowy

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

Zdefiniuj grupy urządzeń

Aby ułatwić skalowanie testów na różnych konfiguracjach urządzeń, na przykład na różnych poziomach interfejsów API i formatach, możesz zdefiniować wiele urządzeń zarządzanych przez Gradle i dodać je do nazwanej grupy. Gradle może następnie równolegle przeprowadzać testy na wszystkich urządzeniach w grupie.

Przykład poniżej pokazuje 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"])
      }
    }
  }
}

Odlotowy

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 Gradle, 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ć.

Windows:

gradlew device-nameBuildVariantAndroidTest

W systemie Linux lub macOS:

./gradlew device-nameBuildVariantAndroidTest

Aby przeprowadzić testy na grupie urządzeń zarządzanych przez Gradle, użyj poniższych poleceń.

Windows:

gradlew group-nameGroupBuildVariantAndroidTest

W systemie Linux lub macOS:

./gradlew group-nameGroupBuildVariantAndroidTest

Dane wyjściowe testowe zawierają ścieżkę do pliku HTML, który zawiera raport testowy. Wyniki testu możesz też zaimportować do Android Studio w celu dalszej analizy. Aby to zrobić, w IDE kliknij Uruchom > Historia testów.

Włącz fragmentację testową

Urządzenia zarządzane przez Gradle obsługują fragmentację testową, która umożliwia podział pakietu testów na wiele identycznych instancji urządzeń wirtualnych (tzw. fragmentów), które działają równolegle. Fragmentacja testów może pomóc skrócić ogólny czas wykonywania testu 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>

Gdy przeprowadzasz testy z użyciem tej opcji, urządzenia zarządzane przez Gradle udostępniają liczbę fragmentów określoną dla każdego profilu urządzenia podczas testu. Jeśli na przykład wdrożysz testy na 3 urządzeniach w grupie urządzeń i ustawisz numManagedDeviceShards na 2, urządzenia zarządzane przez Gradle udostępnią podczas testu łącznie 6 urządzeń wirtualnych.

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

Używaj zautomatyzowanych urządzeń testowych

Urządzenia zarządzane przez Gradle obsługują typ emulatora zwanego Automatic Test Device (ATD), który jest zoptymalizowany pod kątem zmniejszenia zasobów procesora i pamięci podczas testów instrumentowanych. ATD zwiększa wydajność działania na kilka sposobów:

  • Usuń wstępnie zainstalowane aplikacje, które zwykle nie są przydatne do testowania aplikacji
  • Wyłącz określone usługi w tle, które zwykle nie są przydatne do testowania aplikacji
  • Wyłącz renderowanie sprzętowe

Zanim zaczniesz, zaktualizuj emulator Androida do najnowszej wersji. Następnie określ obraz „-atd” podczas definiowania urządzenia zarządzanego przez Gradle 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"
        }
      }
    }
  }
}

Odlotowy

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ń, podobnie jak w przypadku innych urządzeń zarządzanych przez Gradle. Aby jeszcze bardziej wykorzystać ulepszenia wydajności, możesz też używać ATD z fragmentacją testów, aby skrócić łączny czas wykonywania testów w pakiecie testów.

Co jest usuwane z obrazów ATD?

ATD nie tylko działa w trybie bez interfejsu graficznego, ale także optymalizuje 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 przegląd komponentów, które usunęliśmy lub zablokowaliśmy w obrazach ATD, oraz dowiesz się, dlaczego mogą być nieprzydatne.

Co usuwamy z obrazów ATD Dlaczego ta funkcja może nie być potrzebna w przypadku testów automatycznych
Aplikacje usług Google:
  • poczta,
  • Mapy firmy Apple
  • Chrome,
  • Wiadomości
  • Sklep Play i inne usługi
Zautomatyzowane testy powinny koncentrować się na logice Twojej aplikacji, zakładając, że inne aplikacje lub platforma będą działać prawidłowo.

Dzięki Espresso-Intents możesz dopasowywać i weryfikować intencje wychodzące, a nawet podawać wycinki odpowiedzi zamiast prawdziwych odpowiedzi intencji.

Ustawienia aplikacji i usług:
  • Konfiguracja operatora
  • Informacje alarmowe
  • Inicjal jednorazowy
  • Tabela ze zdjęciami (wygaszacze ekranu)
  • Finansowanie
  • Aplikacja Ustawienia
  • Menedżer miejsca na dane
  • Konfiguracja APN telefonii
  • Przycinanie tapet
  • Selektor tapet
Aplikacje te oferują użytkownikom GUI potrzebnym do zmiany ustawień platformy, skonfigurowania urządzenia lub zarządzania pamięcią urządzenia. Zwykle wykracza to poza zakres automatycznych testów na poziomie aplikacji.


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

SystemUI Zautomatyzowane testy powinny koncentrować się na logice Twojej aplikacji, zakładając, że inne aplikacje lub platforma będą działać prawidłowo.
Aplikacje i usługi AOSP:
  • Przeglądarka 2
  • Kalendarz
  • Camera2
  • Kontakty
  • Dialer
  • Zegar biurkowy
  • Galeria 2
  • LatinIME
  • Launcher3QuickStep
  • Muzyka
  • Pole szybkiego wyszukiwania
  • Analiza ustawień
Te aplikacje i usługi zwykle nie są objęte automatycznymi testami kodu aplikacji.

Korzystanie z urządzeń w Laboratorium Firebase

Jeśli korzystasz z urządzeń zarządzanych przez Gradle, możesz przeprowadzać automatyczne testy z użyciem instrumentów 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. Te testy są przeprowadzane w zdalnych centrach danych Google. Dzięki obsłudze urządzeń zarządzanych przez Gradle system kompilacji może w pełni zarządzać przeprowadzanymi testami na urządzeniach z Laboratorium na podstawie Twoich konfiguracji.

Rozpocznij

Poniżej znajdziesz instrukcje, jak zacząć korzystać z urządzeń w Laboratorium Firebase na urządzeniach zarządzanych przez Gradle. Pamiętaj, że te czynności powodują podanie danych logowania użytkownika za pomocą interfejsu wiersza poleceń gcloud, co może nie mieć zastosowania we wszystkich środowiskach programistycznych. Więcej informacji o procesie uwierzytelniania, które należy zastosować do Twoich potrzeb, znajdziesz w artykule Jak działają domyślne dane logowania aplikacji.

  1. Aby utworzyć projekt Firebase, otwórz konsolę Firebase. Aby utworzyć projekt, kliknij Dodaj projekt i postępuj zgodnie z instrukcjami wyświetlanymi na ekranie. 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. Autoryzuj użycie danych logowania użytkownika do uzyskiwania 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))
      }
      

      Odlotowy

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

      Możesz też autoryzować je ręcznie, korzystając z tego polecenia terminala:

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

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

    Na stronie biblioteki interfejsów API w Google Developers Console włącz interfejsy Cloud Testing API i Cloud Tool Results API, wpisując te nazwy w polu wyszukiwania u góry konsoli, a następnie klikając Włącz API na stronie z omówieniem danego interfejsu API.

  5. Skonfiguruj projekt na Androida.

    1. Dodaj wtyczkę Laboratorium Firebase do skryptu kompilacji najwyższego poziomu:

      Kotlin

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

      Odlotowy

      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 do skryptu kompilacji na poziomie modułu:

      Kotlin

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

      Odlotowy

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

Podaj urządzenie laboratorium testowego

W skrypcie kompilacji na poziomie modułu możesz wskazać urządzenie Laboratorium Firebase do testowania aplikacji Gradle. Poniższy przykładowy kod tworzy urządzenie Pixel 3 z interfejsem API na poziomie 30 jako zarządzane przez Gradle urządzenie o nazwie ftlDevice. Blok firebaseTestLab {} jest dostępny po zastosowaniu wtyczki com.google.firebase.testlab do modułu.

Kotlin

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

Odlotowy

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

Aby zdefiniować grupę urządzeń zarządzanych przez Gradle, w tym urządzenia z Laboratorium Firebase, przeczytaj sekcję Definiowanie grup urządzeń.

Aby uruchomić testy, użyj tych samych poleceń co przy uruchamianiu innych urządzeń zarządzanych przez Gradle. Pamiętaj, że Gradle nie uruchamia testów równolegle ani nie obsługuje innych konfiguracji interfejsu wiersza poleceń Google Cloud na urządzeniach w Laboratorium.

Optymalizowanie testów dzięki inteligentnemu fragmentowaniu

Testowanie na urządzeniach z Laboratorium zarządzanych przez Gradle obsługuje inteligentne fragmentację. Inteligentne fragmentowanie automatycznie rozdziela testy między fragmenty, tak aby każdy fragment działał mniej więcej w tym samym czasie, co zmniejsza ręczne przydzielanie i ogólny czas trwania testu. Inteligentne fragmentowanie wykorzystuje historię testów lub informacje o czasie trwania poprzednich testów, aby rozłożyć testy w optymalny sposób. Pamiętaj, że aby korzystać z inteligentnego fragmentowania, potrzebujesz wtyczki Gradle w wersji 0.0.1-alfa05 dla Laboratorium Firebase.

Aby włączyć inteligentne fragmentowanie, określ czas trwania testów w każdym fragmencie. Ustaw czas trwania fragmentu docelowego na co najmniej 5 minut krócej niż w przypadku ustawienia timeoutMinutes, aby uniknąć sytuacji, w której fragmenty są anulowane przed zakończeniem testów.

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

Więcej informacji znajdziesz w artykule o opcjach DSL na urządzeniach w Laboratorium Firebase.

Zaktualizowano DSL dla urządzeń z Laboratorium

Istnieje więcej opcji DSL, które możesz skonfigurować, aby ułatwić sobie dostosowanie uruchomień testowych lub przeprowadzenie migracji z innych rozwiązań, których być może już używasz. Niektóre z nich znajdziesz w opisie poniżej.

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 in Flank/Fladle.
       */
      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
  }
}