Automatyzacja testowania gier może być trudna, gdy aplikacje do gier są tworzone w różnych platformach interfejsu. Testy pętli gry umożliwiają zintegrowanie testów natywnych z Test Lab i łatwe uruchamianie ich na wybranych urządzeniach. Test pętli gry uruchamia test w grze mobilnej, symulując działania prawdziwego gracza. Z tego przewodnika dowiesz się, jak przeprowadzić test pętli gry, a potem wyświetlić wyniki testu i zarządzać nimi w Firebase konsoli.
Co to jest test pętli gry?
Aplikacje do gier renderują się w różnych platformach i silnikach interfejsu, takich jak Unity, Unreal czy kod C++ OpenGL/Vulkan, więc standardowe narzędzia do automatyzacji nie mogą sprawdzać elementów interfejsu ani wchodzić z nimi w interakcję. Test pętli gry umożliwia zintegrowanie testów silnika natywnego z Test Lab przez uruchomienie gry za pomocą intencji zawierającej konkretny numer scenariusza. Ten numer scenariusza powoduje uruchomienie w aplikacji wstępnie zaprogramowanej logiki, symulacji AI lub testów wydajności bezpośrednio w silniku gry.
Po uruchomieniu Test Lab nie wchodzi już w interakcję z interfejsem gry. Zamiast tego Test Lab działa jako transport i środowisko testowe: uruchamia konkretny scenariusz, monitoruje awarie i przekroczenia limitu czasu oraz zbiera niestandardowe dzienniki wyników, gdy aplikacja zakończy wykonywanie pętli.
Czym pętle gier różnią się od testów instrumentacji
- Testy instrumentacyjne (np. Espresso lub UI Automator) korzystają z zewnętrznych platform do obsługi interakcji z interfejsem, klikania przycisków i sprawdzania stanu aplikacji w hierarchii widoków Androida spoza aplikacji.
- Testy pętli gry przekazują logikę testu do aplikacji. Aplikacja uruchamia własną wewnętrzną pętlę testową lub symulację bez interakcji z zewnętrznym interfejsem, a Test Lab wywołuje scenariusz i zbiera dane wyjściowe testu.
Przykłady
Załóżmy, że chcesz sprawdzić, czy Twoja gra utrzymuje co najmniej 60 klatek na sekundę na różnych urządzeniach fizycznych. W kodzie gry możesz zaimplementować scenariusz 1, aby wczytać najbardziej złożony wizualnie poziom i umożliwić graczowi AI lub automatycznemu skryptowi przejście go w ciągu 2 minut.
Gdy Test Lab wywoła scenariusz 1, gra rozpocznie rozgrywkę z udziałem AI, będzie monitorować czas renderowania klatek i wykorzystanie pamięci, przesyłać te dane do niestandardowego pliku dziennika wyjściowego (logFile) i po zakończeniu wywoływać finish().
Test Lab następnie rejestruje plik dziennika i udostępnia go w Cloud Storage oraz w konsoli Firebase.
Przypadki użycia
W zależności od silnika gry możesz wdrażać testy z jedną lub kilkoma pętlami. Pętla to pełne lub częściowe przeprowadzenie testu w aplikacji do gier. Pętli gry można używać do:
- Zagraj w poziom gry tak samo, jak zrobiłby to użytkownik. Możesz zaprogramować dane wejściowe użytkownika, pozwolić mu na bezczynność lub zastąpić go sztuczną inteligencją, jeśli ma to sens w Twojej grze (np. jeśli masz grę mobilną do wyścigów samochodowych i masz już zaimplementowaną sztuczną inteligencję, możesz powierzyć jej sterowanie pojazdem użytkownika).
- Uruchom grę w najwyższej jakości, aby sprawdzić, czy urządzenia ją obsługują.
- Przeprowadź test techniczny (skompiluj wiele shaderów, wykonaj je, sprawdź, czy dane wyjściowe są zgodne z oczekiwaniami itp.).
Test pętli gry możesz przeprowadzić na jednym urządzeniu testowym, na zestawie urządzeń testowych lub Test Lab. Nie zalecamy jednak przeprowadzania testów pętli gry na urządzeniach wirtualnych, ponieważ mają one mniejszą liczbę klatek na sekundę niż urządzenia fizyczne.
Zanim zaczniesz
Aby przeprowadzić test, musisz najpierw skonfigurować aplikację pod kątem testów pętli gry.
W pliku manifestu aplikacji dodaj nowy filtr intencji do aktywności:
<activity android:name=".MyActivity"> <intent-filter> <action android:name="com.google.intent.action.TEST_LOOP"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="application/javascript"/> </intent-filter> <intent-filter> ... (other intent filters here) </intent-filter> </activity>Umożliwia to uruchomienie gry przez Test Lab za pomocą określonego zamiaru.
W kodzie (zalecamy dodanie go w deklaracji metody
onCreate) dodaj ten fragment:Kotlin
val launchIntent = intent if (launchIntent.action == "com.google.intent.action.TEST_LOOP") { val scenario = launchIntent.getIntExtra("scenario", 0) // Code to handle your game loop here }
Java
Intent launchIntent = getIntent(); if(launchIntent.getAction().equals("com.google.intent.action.TEST_LOOP")) { int scenario = launchIntent.getIntExtra("scenario", 0); // Code to handle your game loop here }
Dzięki temu aktywność może sprawdzić intencję, która ją uruchamia. Możesz też dodać ten kod później (np. po początkowym wczytaniu silnika gry).
Zalecane: na końcu testu dodaj:
Kotlin
yourActivity.finish()
Java
yourActivity.finish();
Po zakończeniu testu pętli gry aplikacja zostanie zamknięta. Test polega na tym, że framework interfejsu aplikacji rozpoczyna kolejną pętlę, a zamknięcie aplikacji informuje, że test został zakończony.
Tworzenie i przeprowadzanie testu pętli gry
Po skonfigurowaniu aplikacji pod kątem testów pętli gry możesz od razu utworzyć test i uruchomić go w aplikacji do gier. Możesz uruchomić test w Test Lab za pomocą Firebase konsoli lub interfejsu wiersza poleceń gcloud albo na urządzeniu lokalnym za pomocą Menedżera pętli testowych.
Uruchamianie na urządzeniu lokalnym
Test LabTest Loop Manager to aplikacja open source, która pomaga zintegrować testy pętli gry i przeprowadzać je na urządzeniach lokalnych. Umożliwia to również zespołowi ds. zapewniania jakości uruchamianie tych samych pętli gier na ich urządzeniach.
Aby przeprowadzić test na urządzeniu lokalnym za pomocą Menedżera pętli testowych:
- Pobierz Test Loop Manager na telefon lub tablet i zainstaluj go, uruchamiając:
adb install testloopmanager.apk
- Na urządzeniu otwórz aplikację Test Loop Apps na telefonie lub tablecie. Aplikacja wyświetli listę aplikacji na urządzeniu, które można uruchomić za pomocą pętli gier. Jeśli nie widzisz tu swojej gry mobilnej, upewnij się, że filtr intencji jest zgodny z filtrem opisanym w pierwszym kroku w sekcji Zanim zaczniesz.
- Wybierz grę mobilną, a potem liczbę pętli, które chcesz uruchomić. Uwaga: na tym etapie możesz uruchomić podzbiór pętli zamiast tylko jednej pętli. Więcej informacji o jednoczesnym uruchamianiu wielu pętli znajdziesz w sekcji Funkcje opcjonalne.
- Kliknij Uruchom test. Test rozpocznie się od razu.
Bieg w Test Lab
Test pętli gry możesz uruchomić w Test Lab za pomocą Firebasekonsoli lub gcloud CLI. Zanim zaczniesz, otwórz Firebasekonsolę i utwórz projekt, jeśli jeszcze tego nie zrobiono.
Korzystanie z konsoli Firebase
- W konsoli Firebase kliknij Test Lab w panelu po lewej stronie.
- Kliknij Run Your First Test (Uruchom pierwszy test) lub Run a Test (Uruchom test), jeśli w projekcie przeprowadzono już test.
- Jako typ testu wybierz pętla gry, a potem kliknij Dalej.
- Kliknij Przeglądaj, a następnie przejdź do pliku
.apkaplikacji. Uwaga: na tym etapie możesz uruchomić podzbiór pętli zamiast tylko jednej pętli. Więcej informacji o jednoczesnym uruchamianiu wielu pętli znajdziesz w sekcji Funkcje opcjonalne. - Kliknij Dalej.
- Wybierz urządzenia fizyczne, których chcesz użyć do testowania aplikacji.
- Kliknij Rozpocznij testy.
Więcej informacji o pierwszych krokach z konsolą Firebase znajdziesz w artykule Rozpoczęcie testowania za pomocą konsoli Firebase.
Korzystanie z wiersza poleceń gcloud
Jeśli jeszcze tego nie zrobiono, pobierz i zainstaluj pakiet Google Cloud SDK.
Zaloguj się w gcloud CLI za pomocą konta Google:
gcloud auth loginUstaw projekt w Firebase w gcloud, gdzie
PROJECT_IDto identyfikator projektu w Firebase:gcloud config set project PROJECT_ID
Uruchom pierwszy test:
gcloud firebase test android run \ --type=game-loop --app=<var>path-to-apk</var> \ --device model=herolte,version=23
Więcej informacji o rozpoczynaniu pracy z gcloud CLI znajdziesz w artykule Rozpoczynanie testowania z wiersza poleceń gcloud.
Funkcje opcjonalne
Test Lab oferuje kilka opcjonalnych funkcji, które pozwalają jeszcze bardziej dostosować testy, w tym możliwość zapisywania danych wyjściowych, obsługę wielu pętli gry i etykiety dla powiązanych pętli.
Zapisywanie danych wyjściowych
Gdy Test Lab uruchamia grę, określa adres URL wskazujący lokalny plik wyników na urządzeniu testowym, do którego można uzyskać dostęp za pomocą launchIntent.getData(). Podczas testu gra może zapisywać wyniki testów, dane o skuteczności i dzienniki (logFile) bezpośrednio w tej lokalizacji.
W logFile możesz zapisać dowolną treść, np. zwykły tekst, dane CSV, czasy renderowania klatek lub niestandardowe raporty diagnostyczne. Nie ma żadnych ograniczeń ani wymagań dotyczących formatowania pisanych treści. Plik jest zapisywany po zakończeniu testu i przesyłany do zasobnika Cloud Storage wraz z innymi artefaktami testowymi.
Test Lab jest zgodna ze sprawdzonymi metodami udostępniania plików między aplikacjami opisanymi w sekcji Udostępnianie pliku.
W metodzie onCreate() aktywności, w której znajduje się intencja, możesz pobrać i sprawdzić plik wyjściowy danych, uruchamiając ten kod:
Kotlin
val launchIntent = intent val logFile = launchIntent.data logFile?.let { Log.i(TAG, "Log file ${it.encodedPath}") // ... }
Java
Intent launchIntent = getIntent(); Uri logFile = launchIntent.getData(); if (logFile != null) { Log.i(TAG, "Log file " + logFile.getEncodedPath()); // ... }
Jeśli chcesz zapisywać dane w pliku po stronie C++ aplikacji do gier, możesz przekazać deskryptor pliku zamiast ścieżki do pliku:
Kotlin
val launchIntent = intent val logFile = launchIntent.data var fd = -1 logFile?.let { Log.i(TAG, "Log file ${it.encodedPath}") fd = try { contentResolver .openAssetFileDescriptor(logFile, "w")!! .parcelFileDescriptor .fd } catch (e: FileNotFoundException) { e.printStackTrace() -1 } catch (e: NullPointerException) { e.printStackTrace() -1 } } // C++ code invoked here. // native_function(fd);
Java
Intent launchIntent = getIntent(); Uri logFile = launchIntent.getData(); int fd = -1; if (logFile != null) { Log.i(TAG, "Log file " + logFile.getEncodedPath()); try { fd = getContentResolver() .openAssetFileDescriptor(logFile, "w") .getParcelFileDescriptor() .getFd(); } catch (FileNotFoundException e) { e.printStackTrace(); fd = -1; } catch (NullPointerException e) { e.printStackTrace(); fd = -1; } } // C++ code invoked here. // native_function(fd);
C++
#include <unistd.h> JNIEXPORT void JNICALL Java_my_package_name_MyActivity_native_function(JNIEnv *env, jclass type, jint log_file_descriptor) { // The file descriptor needs to be duplicated. int my_file_descriptor = dup(log_file_descriptor); }
Przykład pliku wyjściowego
Chociaż Test Lab nie wymaga określonego formatu logFile, strukturyzowanie danych wyjściowych jako JSON zgodny z poniższym schematem umożliwia konsoli Firebase (https://console.firebase.google.com/project/_/testlab) analizowanie i wyświetlanie podsumowujących danych o pętli gry.
Najważniejsze informacje o tym przykładzie:
- Kto dostarcza dane: Ty (deweloper testu) odpowiadasz za obliczanie i zapisywanie wszystkich danych w tym pliku z kodu gry. Test Lab nie zbiera ani nie generuje automatycznie tych punktów danych.
- Dodawanie pól niestandardowych: obszary oznaczone jako
/.../wskazują, gdzie można dodać dowolne niestandardowe pary klucz-wartość (np."rendered_vertices": 12000lub"ai_error_count": 0). Podczas zapisywania pliku z aplikacji możesz dodać do danych wyjściowych dowolną prawidłową właściwość JSON, o ile nazwy pól nie powodują konfliktu z polami schematu, takimi jaknamelubstart_timestamp. - Gdzie znaleźć plik wyjściowy: po zakończeniu testu surowy plik wyjściowy jest przechowywany i można go pobrać z zasobnika wyników Cloud Storage (
GCS) projektu w katalogu artefaktów przebiegu testu. Możesz też wyświetlić i sprawdzić przeanalizowane dane wyjściowe na stronie Test Lab w konsoli Firebase.
Oto przykładowy plik wyjściowy JSON o strukturze:
{
"name": "test name",
"start_timestamp": 0, // Timestamp of the test start (in us).
Can be absolute or relative
"driver_info": "...",
"frame_stats": [
{
"timestamp": 1200000, // Timestamp at which this section was written
It contains value regarding the period
start_timestamp(0) -> this timestamp (1200000 us)
"avg_frame_time": 15320, // Average time to render a frame in ns
"nb_swap": 52, // Number of frame rendered
"threads": [
{
"name": "physics",
"Avg_time": 8030 // Average time spent in this thread per frame in us
},
{
"name": "AI",
"Avg_time": 2030 // Average time spent in this thread per frame in us
}
],
/.../ // Any custom field you want (vertices display on the screen, nb units …)
},
{
// Next frame data here, same format as above
}
],
"loading_stats": [
{
"name": "assets_level_1",
"total_time": 7850, // in us
/.../
},
{
"name": "victory_screen",
"total_time": 554, // in us
/.../
}
],
/.../, // You can add custom fields here
}
Wiele pętli gry
W aplikacji może być przydatne uruchamianie kilku pętli gry. Pętla to pełne przejście przez aplikację od początku do końca. Jeśli na przykład Twoja gra ma kilka poziomów, możesz użyć jednej pętli gry do uruchamiania każdego z nich zamiast jednej pętli, która przechodzi przez wszystkie poziomy. Dzięki temu, jeśli aplikacja ulegnie awarii na poziomie 32, możesz bezpośrednio uruchomić tę pętlę gry, aby odtworzyć awarię i przetestować poprawki błędów.
Aby umożliwić aplikacji uruchamianie wielu pętli jednocześnie:
Jeśli testujesz za pomocą narzędzia Test Loop Manager:
Dodaj ten wiersz do pliku manifestu aplikacji w elemencie
<application>:<meta-data android:name="com.google.test.loops" android:value="5" />
Ta intencja uruchomienia zawiera pętlę docelową jako parametr całkowity. W
android:valuemożesz podać liczbę całkowitą od 1 do 1024 (maksymalna liczba pętli dozwolonych w przypadku jednego testu). Pamiętaj, że pętle są indeksowane od 1, a nie od 0.W aplikacji Test Loop Manager pojawi się ekran wyboru, na którym możesz wybrać pętle, które chcesz uruchomić. Jeśli wybierzesz kilka pętli, każda z nich zostanie uruchomiona po zakończeniu poprzedniej.
Jeśli przeprowadzasz test za pomocą konsoli Firebase, w polu Scenariusze wpisz listę lub zakres liczb pętli.
Jeśli testujesz za pomocą gcloud CLI, określ listę numerów pętli za pomocą flagi
--scenario-numbers. Na przykład:--scenario-numbers=1,3,5przebiega pętle 1, 3 i 5.Jeśli piszesz kod w C++ i chcesz zmienić działanie pętli, przekaż do kodu natywnego w C++ te dodatkowe informacje:
Kotlin
val launchIntent = intent val scenario = launchIntent.getIntExtra("scenario", 0)
Java
Intent launchIntent = getIntent(); int scenario = launchIntent.getIntExtra("scenario", 0);
Możesz teraz zmieniać działanie pętli na podstawie uzyskanego
intwartości.
Etykietowanie pętli gry
Gdy oznaczysz pętle co najmniej jedną etykietą scenariusza, Ty i Twój zespół kontroli jakości będziecie mogli łatwo uruchomić zestaw powiązanych pętli (np. „wszystkie pętle zgodności”) i przetestować je w jednej macierzy. Możesz tworzyć własne etykiety lub korzystać z wstępnie zdefiniowanych etykiet oferowanych przez Test Lab:
com.google.test.loops.player_experience: w przypadku pętli używanych do odtwarzania doświadczeń prawdziwego użytkownika podczas grania w grę. Celem testowania za pomocą tych pętli jest wykrycie problemów, które mogą wystąpić u prawdziwego użytkownika podczas grania.com.google.test.loops.gpu_compatibility: Pętle for używane do testowania problemów związanych z GPU. Celem testowania za pomocą tych pętli jest wykonywanie kodu GPU, który może nie działać prawidłowo w środowisku produkcyjnym, aby wykrywać problemy ze sprzętem i sterownikami.com.google.test.loops.compatibility: pętle for używane do testowania szerokiego zakresu problemów ze zgodnością, w tym problemów z wejściem/wyjściem i OpenSSL.com.google.test.loops.performance: Pętle for używane do testowania wydajności urządzenia. Na przykład gra może być uruchamiana z najbardziej złożonymi ustawieniami grafiki, aby sprawdzić, jak zachowuje się nowe urządzenie.
Aby umożliwić aplikacji uruchamianie pętli z tą samą etykietą:
Jeśli testujesz za pomocą narzędzia Test Loop Manager:
W pliku manifestu aplikacji dodaj ten wiersz metadanych i zastąp LABEL_NAME wybraną przez siebie etykietą:
<meta-data android:name="com.google.test.loops.LABEL_NAME" android:value="1,3-5" />
W polu
android:valuemożesz określić zakres lub zbiór liczb całkowitych od 1 do 1024 (maksymalna liczba pętli dozwolonych w przypadku jednego testu), które reprezentują pętle, które chcesz oznaczyć. Pamiętaj, że pętle są indeksowane od 1, a nie od 0. Na przykład regułaandroid:value="1,3-5"ma zastosowanie do pętli 1, 3, 4 i 5.LABEL_NAMEW aplikacji Test Loop Manager wpisz co najmniej jedną etykietę w polu Etykiety.
Jeśli przeprowadzisz test w Firebase konsoli, wpisz co najmniej jedną etykietę w polu Etykiety.
Jeśli przeprowadzasz test za pomocą gcloud CLI, określ co najmniej 1 etykietę scenariusza za pomocą flagi
--scenario-labels(np.--scenario-labels=performance,gpu).
Pomoc dotycząca licencjonowania aplikacji
Test Lab obsługuje aplikacje, które korzystają z usługi Licencjonowanie aplikacji oferowanej przez Google Play. Aby podczas testowania aplikacji za pomocą Test Lab można było sprawdzić licencję, musisz opublikować aplikację w kanale produkcyjnym w Sklepie Play. Aby przetestować aplikację na ścieżce alfa lub beta za pomocą Test Lab, usuń test licencjonowania przed przesłaniem aplikacji do Test Lab.
Znane problemy
Testy pętli gry w Test Lab mają te znane problemy:
- Niektóre awarie nie obsługują śladów wstecznych. Na przykład niektóre wersje mogą pomijać dane wyjściowe procesu
debuggerdza pomocąprctl(PR_SET_DUMPABLE, 0). Więcej informacji znajdziesz w sekcjidebuggerd. - Poziom API 19 nie jest obecnie obsługiwany z powodu błędów uprawnień do plików.