Pierwsze kroki z testami pętli gry

Zautomatyzowanie testowania gier może być trudne, gdy gry mobilne są tworzone na różnych platformach. Testy pętli gry pozwalają zintegrować własne testy z Laboratorium i łatwo przeprowadzać je na wybranych urządzeniach. Test pętli gry przeprowadza test w grze mobilnej, jednocześnie symulując działania prawdziwego gracza. Z tego przewodnika dowiesz się, jak przeprowadzić test pętli gry, a potem wyświetlać wyniki testu i zarządzać nimi w konsoli Firebase.

W zależności od silnika gry możesz wdrożyć testy z pojedynczą lub wieloma pętlami. Pętla to całkowite lub częściowe zakończenie testu w grze mobilnej. Pętle gry mogą służyć do:

  • Uruchom poziom gry w taki sam sposób jak użytkownik. Możesz użyć skryptu wpisywanych przez użytkownika danych, pozwolić mu na zachowanie bezczynności lub zastąpić go AI, jeśli ma to sens w Twojej grze (np. jeśli masz aplikację z grami wyścigowymi i masz już zaimplementowaną sztuczną inteligencję. Można łatwo przypisać sterownik AI za ingerencję użytkownika).
  • Uruchom grę w najwyższej jakości, by sprawdzić, czy urządzenie ją obsługuje.
  • Przeprowadź test techniczny (skompiluj wiele programów do cieniowania, wykonaj je, sprawdź, czy dane wyjściowe są zgodne z oczekiwaniami itp.).

Test pętli gry możesz przeprowadzić na jednym urządzeniu testowym, zestawie urządzeń testowych lub w Laboratorium. Nie zalecamy jednak wykonywania testów pętli gry na urządzeniach wirtualnych, ponieważ mają one mniejszą liczbę klatek graficznych niż urządzenia fizyczne.

Zanim zaczniesz

Aby wdrożyć test, musisz najpierw skonfigurować aplikację pod kątem testów pętli gry.

  1. W pliku manifestu aplikacji dodaj nowy filtr intencji do swojej 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>
    

    Dzięki temu Laboratorium może uruchomić Twoją grę, aktywując ją z określonym zamiarem.

  2. Do kodu (zalecamy w deklaracji metody onCreate) dodaj:

    Kotlin+KTX

    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 sprawdzać intencję, która ją uruchamia. Jeśli wolisz, możesz dodać ten kod później (np. po wstępnym wczytaniu silnika gry).

  3. Zalecane: na koniec testu dodaj:

    Kotlin+KTX

    yourActivity.finish()

    Java

    yourActivity.finish();

    Aplikacja zostanie zamknięta po zakończeniu testu pętli gry. Do rozpoczęcia kolejnej pętli test wykorzystuje platformę interfejsu użytkownika aplikacji, a zamknięcie aplikacji informuje o zakończeniu testu.

Tworzenie i uruchamianie testu pętli gry

Po skonfigurowaniu testów pętli gry możesz natychmiast utworzyć test i uruchomić go w grze. Test możesz przeprowadzić w Laboratorium za pomocą konsoli Firebase lub interfejsu wiersza poleceń gcloud albo na urządzeniu lokalnym za pomocą menedżera pętli testowej.

Uruchamianie na urządzeniu lokalnym

Menedżer pętli testowej to aplikacja open source, która pomaga zintegrować testy pętli gry i uruchamiać je na urządzeniach lokalnych. Dzięki temu członkowie zespołu ds. kontroli jakości mogą uruchamiać te same pętle gry na swoich urządzeniach.

Aby przeprowadzić test na urządzeniu lokalnym przy użyciu menedżera pętli testowej:

  1. Pobierz Menedżera pętli testów na telefon lub tablet i zainstaluj go, uruchamiając polecenie:
    adb install testloopmanager.apk
  2. Otwórz aplikację Testuj aplikacje pętli na telefonie lub tablecie. Aplikacja wyświetla listę aplikacji na urządzeniu, które można uruchomić przy użyciu pętli gry. Jeśli nie widzisz tu swojej gry, sprawdź, czy filtr intencji jest zgodny z filtrem opisanym w pierwszym kroku w sekcji Zanim zaczniesz.
  3. Wybierz grę, w której grasz, a potem określ, ile pętli chcesz wykonać. Uwaga: na tym etapie możesz wybrać uruchomienie podzbioru pętli, a nie tylko jednej pętli. Więcej informacji o przeprowadzaniu wielu pętli jednocześnie znajdziesz w sekcji Funkcje opcjonalne.
  4. Kliknij Uruchom test. Test rozpocznie się natychmiast.

Uruchom w Laboratorium

Test pętli gry możesz uruchomić w Laboratorium za pomocą konsoli Firebase lub interfejsu wiersza poleceń gcloud. Zanim zaczniesz, otwórz konsolę Firebase i utwórz projekt.

Korzystanie z konsoli Firebase

  1. W konsoli Firebase w panelu po lewej stronie kliknij Laboratorium.
  2. Kliknij Przeprowadź pierwszy test (lub Uruchom test, jeśli w projekcie był wcześniej testowany).
  3. Jako typ testu wybierz Pętla gry i kliknij Dalej.
  4. Kliknij Przeglądaj, a potem przejdź do pliku .apk aplikacji. Uwaga: na tym etapie możesz wybrać uruchomienie podzbioru pętli, a nie tylko jednej pętli. Więcej informacji o przeprowadzaniu wielu pętli jednocześnie znajdziesz w sekcji Funkcje opcjonalne.
  5. Kliknij Dalej.
  6. Wybierz urządzenia fizyczne, których chcesz użyć do przetestowania aplikacji.
  7. Kliknij Rozpocznij testy.

Więcej o tym, jak zacząć korzystać z konsoli Firebase, dowiesz się z artykułu Rozpoczynanie testowania za pomocą konsoli Firebase.

Używanie wiersza poleceń gcloud

  1. Pobierz i zainstaluj pakiet SDK Google Cloud (jeśli jeszcze go nie masz).

  2. Zaloguj się w interfejsie wiersza poleceń gcloud za pomocą konta Google:

    gcloud auth login

  3. Skonfiguruj projekt Firebase w gcloud, gdzie PROJECT_ID to identyfikator projektu Firebase:

    gcloud config set project PROJECT_ID
    
  4. Przeprowadź 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 tym, jak zacząć korzystać z interfejsu wiersza poleceń gcloud, znajdziesz w artykule o rozpoczynaniu testowania z poziomu wiersza poleceń gcloud.

Funkcje opcjonalne

Laboratorium oferuje kilka opcjonalnych funkcji, które pozwalają na dalsze dostosowywanie testów, w tym możliwość zapisywania danych wyjściowych, obsługę wielu pętli gry i etykiety powiązanych pętli.

Zapisz dane wyjściowe

Test pętli gry może zapisywać dane wyjściowe w pliku wskazanym w metodzie launchIntent.getData(). Po zakończeniu testu te dane wyjściowe znajdziesz w sekcji Laboratorium w konsoli Firebase (patrz przykładowy plik wyjściowy testu pętli gry).

Laboratorium obejmuje sprawdzone metody udostępniania pliku między aplikacjami opisanymi w sekcji Udostępnianie pliku. W metodzie onCreate() aktywności, w której znajduje się intencja, możesz sprawdzić plik wyjściowy, uruchamiając ten kod:

Kotlin+KTX

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 zapisać plik od strony C++ gry, możesz przekazać deskryptor pliku zamiast ścieżki:

Kotlin+KTX

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

Aby wyświetlić wyniki testu pętli gry w sekcji Laboratorium w konsoli Firebase, możesz użyć plików z danymi wyjściowymi (w formacie jak w przykładzie poniżej). Obszary oznaczone jako /.../ mogą zawierać dowolne potrzebne pola niestandardowe, o ile nie kolidują z nazwami innych pól użytych w tym pliku:

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

Warto uruchomić w aplikacji wiele pętli gry. Jeśli na przykład w grze jest kilka poziomów, możesz utworzyć jedną pętlę gry do uruchamiania każdego z nich, zamiast używać jednej pętli, która powtarza się przez każdy z nich. Dzięki temu, gdy aplikacja ulegnie awarii na poziomie 32, możesz bezpośrednio uruchomić tę pętlę gry, aby odtworzyć błąd i przetestować poprawki błędów.

Aby włączyć w aplikacji wiele pętli jednocześnie:

  • Jeśli przeprowadzasz test za pomocą menedżera pętli testowej:

    1. 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 liczby całkowitej. W polu android:value możesz podać liczbę całkowitą od 1 do 1024 (maksymalną liczbę pętli dozwoloną w ramach jednego testu). Pamiętaj, że pętle są indeksowane od 1, a nie od 0.

    2. W aplikacji Menedżer pętli testowej pojawi się ekran wyboru, na którym możesz wybrać pętle do uruchomienia. Jeśli wybierzesz wiele pętli, każda z nich zostanie uruchomiona w sekwencji po zakończeniu poprzedniej.

  • Jeśli przeprowadzasz test z użyciem konsoli Firebase, w polu Scenariusze wpisz listę lub zakres liczb pętli.

  • Jeśli przeprowadzasz test za pomocą interfejsu wiersza poleceń gcloud, określ listę numerów pętli za pomocą flagi --scenario-numbers. Na przykład --scenario-numbers=1,3,5 uruchamia pętle 1, 3 i 5.

  • Jeśli piszesz w C++ i chcesz zmienić działanie pętli, przekaż ten dodatkowy kod do natywnego kodu C++:

    Kotlin+KTX

    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 wynikowej wartości int.

Oznacz pętle gry

Gdy oznaczysz pętle gry co najmniej jedną etykietą scenariusza, Ty i Twój zespół ds.kontroli jakości będziecie mogli łatwo uruchomić zestaw powiązanych pętli gry (np. „wszystkie pętle gry zgodności”) i przetestować je w jednej macierzy. Możesz tworzyć własne etykiety lub użyć gotowych etykiet oferowanych przez Laboratorium:

  • com.google.test.loops.player_experience: pętle pozwalające odtworzyć wrażenia użytkownika podczas grania. Celem testów jest wykrycie problemów, które mogą wystąpić podczas grania w grę.
  • com.google.test.loops.gpu_compatibility: pętle używane do testowania problemów związanych z GPU. Celem testowania z użyciem tych pętli jest uruchomienie kodu GPU, który może nie działać poprawnie w środowisku produkcyjnym, co stwarza problemy ze sprzętem i sterownikami.
  • com.google.test.loops.compatibility: pętle używane do testowania szerokiego zakresu problemów ze zgodnością, m.in. problemów z wejściem/wyjściem i OpenSSL.
  • com.google.test.loops.performance: na potrzeby pętli używanych do testowania wydajności urządzenia. Na przykład gra może działać w najbardziej złożonych ustawieniach graficznych, aby sprawdzić, jak zachowuje się nowe urządzenie.

Aby w aplikacji można było uruchamiać pętle o tej samej etykiecie:

  • Jeśli przeprowadzasz test za pomocą menedżera pętli testowej:

    1. 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:value możesz określić zakres lub zbiór liczb całkowitych od 1 do 1024 (maksymalną liczbę pętli dozwolonych w jednym teście) reprezentujących pętle, które chcesz oznaczyć etykietą. Pamiętaj, że pętle są indeksowane od 1, a nie od 0. Na przykład funkcja android:value="1,3-5" stosuje LABEL_NAME do pętli 1, 3, 4 i 5.

    2. W aplikacji Menedżer pętli testowej wpisz co najmniej 1 etykietę w polu Etykiety.

  • Jeśli przeprowadzasz test za pomocą konsoli Firebase, wpisz co najmniej 1 etykietę w polu Etykiety.

  • Jeśli wykonujesz test z użyciem interfejsu wiersza poleceń gcloud, podaj co najmniej 1 etykietę scenariusza za pomocą flagi --scenario-labels (np. --scenario-labels=performance,gpu).

Pomoc dotycząca licencjonowania aplikacji

Laboratorium obsługuje aplikacje korzystające z usługi licencjonowania aplikacji dostępnej w Google Play. Aby sprawdzić licencjonowanie podczas testowania aplikacji w Laboratorium, musisz opublikować ją w kanale produkcyjnym w Sklepie Play. Aby przetestować aplikację w kanale alfa lub beta za pomocą Laboratorium, przed przesłaniem jej do Laboratorium usuń kontrolę licencji.

Znane problemy

Podczas testów pętli gry w Laboratorium występują te znane problemy:

  • Niektóre awarie nie obsługują wsteczników. Na przykład niektóre kompilacje wersji mogą pomijać dane wyjściowe procesu debuggerd za pomocą metody prctl(PR_SET_DUMPABLE, 0). Więcej informacji: debuggerd.
  • Poziom API 19 nie jest obecnie obsługiwany z powodu błędów uprawnień do pliku.