開始遊戲循環測試

當遊戲應用程式建立在不同的 UI 框架上時,自動化遊戲測試可能會很困難。遊戲循環測試可讓您將本機測試與測試實驗室集成,並輕鬆在您選擇的裝置上運行它們。遊戲循環測試透過遊戲應用程式運行測試,同時模擬真實玩家的操作。本指南向您展示如何執行遊戲循環測試,然後在 Firebase 控制台中檢視和管理測試結果。

根據您的遊戲引擎,您可以使用單一或多個循環來實現測試。循環是對遊戲應用程式進行完整或部分測試。遊戲循環可用於:

  • 以最終用戶玩遊戲的方式運行遊戲的某個關卡。您可以編寫用戶輸入的腳本,讓用戶閒置,或者如果在您的遊戲中有意義的話,用 AI 替換用戶(例如,假設您有一個賽車遊戲應用程式並且已經實現了 AI。您可以輕鬆讓人工智慧驅動程式負責使用者的輸入)。
  • 以最高品質設定運行遊戲,看看設備是否支援它。
  • 執行技術測試(編譯多個著色器,執行它們,檢查輸出是否符合預期等)。

您可以在單一測試設備、一組測試設備或測試實驗室上執行遊戲循環測試。但是,我們不建議在虛擬設備上執行遊戲循環測試,因為它們的圖形幀速率低於實體設備。

在你開始之前

要實施測試,您必須先為遊戲循環測試配置應用程式。

  1. 在您的應用程式清單中,為您的Activity新增一個新的意圖過濾器:

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

    這允許測試實驗室透過以特定意圖觸發遊戲來啟動遊戲。

  2. 在您的程式碼中(我們建議在onCreate方法聲明中),加入以下內容:

    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
    }

    這允許您的活動檢查啟動它的意圖。如果您願意,您也可以稍後添加此程式碼(例如,在最初載入遊戲引擎後)。

  3. 建議:在測試結束時新增:

    Kotlin+KTX

    yourActivity.finish()

    Java

    yourActivity.finish();

    當遊戲循環測試完成時,這將關閉您的應用程式。該測試依賴應用程式的 UI 框架來啟動下一個循環,關閉應用程式會告訴它測試已完成。

創建並運行遊戲循環測試

在為遊戲循環測試配置應用程式後,您可以立即建立測試並在遊戲應用程式中執行它。您可以選擇使用Firebase 控制台gcloud 命令列介面 (CLI)在測試實驗室中執行測試,或使用測試循環管理器在本機裝置上執行測試。

在本地設備上運行

Test Lab 的Test Loop Manager是一款開源應用程序,可協助您整合遊戲循環測試並在本機裝置上執行它們。它還允許您的品質保證團隊在他們的設備上運行相同的遊戲循環。

若要使用測試循環管理器在本機裝置上執行測試:

  1. 在手機或平板電腦上下載測試循環管理器並透過執行以下命令進行安裝:
    adb install testloopmanager.apk
  2. 在您的裝置上,打開手機或平板電腦上的Test Loop Apps應用程式。該應用程式顯示裝置上可與遊戲循環一起運行的應用程式清單。如果您在此處沒有看到您的遊戲應用程序,請確保您的意圖過濾器與開始之前部分第一步中描述的過濾器相符。
  3. 選擇您的遊戲應用程序,然後選擇您要執行的循環數。注意:在此步驟中,您可以選擇運行循環的子集而不是只運行一個循環。有關同時運行多個循環的更多信息,請參閱可選功能
  4. 單擊運行測試。您的測試立即開始運行。

在測試實驗室運行

您可以使用Firebase 控制台gcloud CLI 在測試實驗室中執行遊戲循環測試。在開始之前,請開啟Firebase 控制台並建立專案(如果您還沒有這樣做)。

使用 Firebase 控制台

  1. 在 Firebase 控制台中,按一下左側面板中的「測試實驗室」
  2. 按一下「執行您的第一個測試」 (如果您的專案之前執行過測試,請按一下「執行測試」)。
  3. 選擇遊戲循環作為測試類型,然後按一下繼續
  4. 按一下瀏覽,然後瀏覽到應用程式的.apk檔案。注意:在此步驟中,您可以選擇運行循環的子集而不是只運行一個循環。有關同時運行多個循環的更多信息,請參閱可選功能
  5. 單擊繼續
  6. 選擇用於測試您的應用程式的實體設備。
  7. 單擊開始測試

有關 Firebase 控制台入門的更多信息,請參閱使用 Firebase 控制台開始測試。

使用 gcloud 命令列 (CLI)

  1. 如果您尚未安裝,請下載並安裝Google Cloud SDK

  2. 使用您的 Google 帳戶登入 gcloud CLI:

    gcloud auth login

  3. 在 gcloud 中設定您的 Firebase 項目,其中PROJECT_ID是您的 Firebase 項目的 ID:

    gcloud config set project PROJECT_ID
    
  4. 執行您的第一個測試:

    gcloud firebase test android run \
     --type=game-loop --app=<var>path-to-apk</var> \
     --device model=herolte,version=23
    

有關 gcloud CLI 入門的更多信息,請參閱從 gcloud 命令列開始測試。

選用功能

測試實驗室提供了多種可選功能,可讓您進一步自訂測試,包括編寫輸出資料的能力、對多個遊戲循環的支援以及相關循環的標籤。

寫入輸出數據

您的遊戲循環測試可以將輸出寫入launchIntent.getData()方法中指定的檔案。執行測試後,您可以在 Firebase 控制台的測試實驗室部分存取此輸出資料(請參閱遊戲循環測試輸出檔案範例)。

測試實驗室遵循共享文件中所述的在應用程式之間共享文件的最佳實踐。在您的 Activity 的onCreate()方法(您的意圖所在的位置)中,您可以透過執行以下程式碼來檢查資料輸出檔:

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());
    // ...
}

如果您想從遊戲應用程式的 C++ 端寫入文件,您可以傳入文件描述符而不是文件路徑:

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

輸出文件範例

您可以使用輸出資料檔案(格式如下例所示)在 Firebase 控制台的測試實驗室部分中顯示遊戲循環測試結果。顯示為/.../的區域可以包含您需要的任何自訂字段,只要它們不與此文件中使用的其他字段的名稱衝突即可:

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

多個遊戲循環

您可能會發現在應用程式中運行多個遊戲循環很有用。循環是遊戲應用程式從開始到結束的完整運行。例如,如果您的遊戲中有多個關卡,您可能會想要使用一個遊戲循環來啟動每個關卡,而不是使用一個循環遍歷所有關卡。這樣,如果您的應用程式在第 32 級崩潰,您可以直接啟動該遊戲循環來重現崩潰並測試錯誤修復。

要使您的應用程式能夠一次運行多個循環:

  • 如果您使用測試循環管理器執行測試:

    1. 將以下行新增至應用程式清單的<application>元素內:

      <meta-data
        android:name="com.google.test.loops"
        android:value="5" />
      

      此啟動意圖包含目標循環作為整數參數。在android:value欄位中,您可以指定 1 到 1024 之間的整數(單一測試允許的最大循環數)。請注意,循環的索引從 1 開始,而不是從 0 開始。

    2. 在測試循環管理器應用程式中,會出現一個選擇畫面,讓您選擇要執行的循環。如果選擇多個循環,則每個循環將在前一個循環完成後按順序啟動。

  • 如果您使用 Firebase 控制台執行測試,請在場景欄位中輸入循環編號清單或範圍。

  • 如果您使用 gcloud CLI 執行測試,請使用--scenario-numbers標誌指定循環編號清單。例如, --scenario-numbers=1,3,5運行循環 1、3 和 5。

  • 如果您正在編寫 C++ 並且想要更改循環的行為,請將以下額外內容傳遞給您的本機 C++ 程式碼:

    Kotlin+KTX

    val launchIntent = intent
    val scenario = launchIntent.getIntExtra("scenario", 0)

    Java

    Intent launchIntent = getIntent();
    int scenario = launchIntent.getIntExtra("scenario", 0);

    現在您可以根據產生的int值更改循環的行為。

標記遊戲循環

當您使用一個或多個場景標籤來標記遊戲循環時,您和您的 QA 團隊可以輕鬆啟動一組相關的遊戲循環(例如「所有相容性遊戲循環」)並在單一矩陣中測試它們。您可以建立自己的標籤或使用測試實驗室提供的預先定義標籤:

  • com.google.test.loops.player_experience :用於重現真實使用者玩遊戲時的體驗的循環。使用這些循環進行測試的目的是發現真實用戶在玩遊戲時會遇到的問題。
  • com.google.test.loops.gpu_compatibility :用於測試 GPU 相關問題的 For 迴圈。使用這些循環進行測試的目的是執行在生產中可能無法正常運行的 GPU 程式碼,以暴露硬體和驅動程式的問題。
  • com.google.test.loops.compatibility :用於測試各種相容性問題的 For 循環,包括 I/O 問題和 OpenSSL 問題。
  • com.google.test.loops.performance :測試裝置效能的 For 迴圈。例如,遊戲可能會在最複雜的圖形設定下運行,以了解新設備的行為。

要使您的應用程式能夠運行具有相同標籤的循環:

  • 如果您使用測試循環管理器執行測試:

    1. 在應用程式的清單中,新增下列元資料行並將LABEL_NAME替換為您選擇的標籤:

      <meta-data
       android:name="com.google.test.loops.LABEL_NAME"
       android:value="1,3-5" />
      

      android:value欄位中,您可以指定 1 到 1024 之間的範圍或一組整數(單一測試允許的最大循環數),以表示要標記的循環。請注意,循環的索引從 1 開始,而不是從 0 開始。例如, android:value="1,3-5"LABEL_NAME應用於循環 1、3、4 和 5。

    2. 在 Test Loop Manager 應用程式中,在標籤欄位中輸入一個或多個標籤。

  • 如果您使用 Firebase 控制台執行測試,請在「標籤」欄位中輸​​入一個或多個標籤。

  • 如果您使用 gcloud CLI 執行測試,請使用--scenario-labels標誌(例如--scenario-labels=performance,gpu )指定一個或多個場景標籤。

應用程式許可支持

測試實驗室支援使用 Google Play 提供的應用程式授權服務的應用程式。要在使用測試實驗室測試應用程式時成功檢查許可,您必須將應用程式發佈到 Play 商店中的生產管道。若要使用測試實驗室在 Alpha 或 Beta 頻道中測試您的應用程序,請在將應用程式上傳到測試實驗室之前刪除許可檢查。

已知的問題

測試實驗室中的遊戲循環測試有以下已知問題:

  • 有些崩潰不支援回溯。例如,某些發布版本可能會使用prctl(PR_SET_DUMPABLE, 0)抑制debuggerd程序的輸出。要了解更多信息,請參閱debuggerd
  • 由於檔案權限錯誤,目前不支援 API 等級 19。