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:
|
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:
|
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.
|
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:
|
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.
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.
Aby zainstalować Google Cloud CLI, wykonaj czynności opisane w artykule Instalowanie interfejsu wiersza poleceń gcloud.
Skonfiguruj środowisko lokalne.
Połącz z projektem Firebase w gcloud:
gcloud config set project FIREBASE_PROJECT_ID
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
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
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.
Skonfiguruj projekt na Androida.
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 }
Włącz niestandardowe typy urządzeń w pliku
gradle.properties
:android.experimental.testOptions.managedDevices.customDevice=true
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 } }