Check out what’s new from Firebase@ Google I/O 2021, and join our alpha program for early access to the new Remote Config personalization feature. Learn more

開始遊戲循環測試

當遊戲應用程序構建在不同的 UI 框架上時,遊戲測試自動化可能很困難。遊戲循環測試允許您將本機測試與測試實驗室集成,並在您選擇的設備上輕鬆運行它們。遊戲循環測試通過您的遊戲應用程序運行您的測試,同時模擬真實玩家的動作。本指南向您展示如何運行遊戲循環測試,然後在 Firebase 控制台中查看和管理您的測試結果。

根據您的遊戲引擎,您可以使用單個或多個循環實施測試。循環是對遊戲應用程序測試的全部或部分運行。遊戲循環可用於:

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

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

在你開始之前

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

  1. 在您的應用清單中,向您的Activity添加一個新的 Intent 過濾器:

    <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方法聲明中),添加以下內容:

    爪哇

    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
    }

    科特林+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
    }

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

  3. 推薦:在測試結束時,添加:

    爪哇

    yourActivity.finish();

    科特林+KTX

    yourActivity.finish()

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

創建並運行遊戲循環測試

為遊戲循環測試配置應用程序後,您可以立即創建測試並在遊戲應用程序中運行它。您可以選擇使用Firebase 控制台gcloud 命令行界面 (CLI)在測試實驗室中運行測試,或者使用測試循環管理器本地設備上運行測試

在本地設備上運行

測試實驗室的測試循環管理器是一個開源應用程序,可幫助您集成遊戲循環測試並在本地設備上運行它們。它還允許您的質量保證團隊在他們的設備上運行相同的遊戲循環。

要使用測試循環管理器在本地設備上運行測試:

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

在測試實驗室運行

您可以使用Firebase 控制台gcloud CLI在測試實驗室中運行遊戲循環測試在開始之前,如果您還沒有,請打開Firebase 控制台並創建一個項目。

使用 Firebase 控制台

  1. 在 Firebase 控制台中,點擊左側面板中的測試實驗室
  2. 點擊運行第一個測試(或運行一個測試,如果你的項目以前運行測試)。
  3. 選擇Game Loop作為測試類型,然後點擊Continue
  4. 單擊Browse ,然後瀏覽到您的應用程序的.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 控制台的測試實驗室部分訪問此輸出數據(請參閱遊戲循環測試輸出文件示例)。

測試實驗室遵循共享中所描述的應用程序之間的文件最佳實踐共享文件。在您的意圖所在的活動的onCreate()方法中,您可以通過運行以下代碼來檢查您的數據輸出文件:

爪哇

Intent launchIntent = getIntent();
Uri logFile = launchIntent.getData();
if (logFile != null) {
    Log.i(TAG, "Log file " + logFile.getEncodedPath());
    // ...
}

科特林+KTX

val launchIntent = intent
val logFile = launchIntent.data
logFile?.let {
    Log.i(TAG, "Log file ${it.encodedPath}")
    // ...
}

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

爪哇

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

科特林+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);

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++ 代碼:

    爪哇

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

    科特林+KTX

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

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

標記遊戲循環

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

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

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

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

    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應用於循環android:value="1,3-5"和 5。

    2. 在測試循環管理器應用程序中,在標籤字段中輸入一個或多個標籤。

  • 如果您使用 Firebase 控制台運行測試,請在標籤字段中輸入一個或多個標籤。

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

應用許可支持

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

已知的問題

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

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