Firebase 测试实验室游戏循环测试

由于用于游戏开发的界面框架(其中一些依赖于引擎)多种多样,以及在游戏中自动执行界面导航困难重重,因此自动化游戏测试十分具有挑战性。为了支持游戏应用测试,测试实验室现在加入了对“演示模式”的支持(测试版),在该模式下游戏应用可以一边运行一边模拟玩家的操作。此模式可以包括多个循环(即场景),您可以使用标签对这些循环进行逻辑整理,以便将相关的循环组合在一起运行。

本文档介绍了有关如何实现游戏循环的准则,以便您在开发过程中可以轻松地利用循环来测试您的游戏。无论您是在单台测试设备或一组测试设备上运行测试,还是使用测试实验室进行测试,这些准则均适用。

游戏循环支持目前为测试版

使用入门

要在测试实验室中使用游戏循环测试,您必须修改自己的游戏以执行以下操作:

  1. 启动循环
  2. 运行循环
  3. (可选)关闭游戏应用

启动循环

启动游戏循环测试时,您的游戏将通过某个特定的 intent 触发,因此您需要修改您的清单文件并为您的 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>

运行循环

您的 Activity 在启动时会检查是哪一个 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
}

我们建议您在 onCreate 方法中运行此代码,但如果您愿意,也可以稍后再运行此代码(例如,在最初加载游戏引擎之后)。然后,您可以按照自己喜欢的任何方式实现一个游戏循环(或多个循环,如多个游戏循环中所述),具体取决于您的游戏引擎。例如,游戏循环可用于:

  • 以最终用户玩游戏的方式运行游戏的某一关卡。您可以用脚本代替用户输入、让用户空闲下来,或者在游戏中行得通的情况下用人工智能来代替用户(例如,如果您已经在自己的赛车游戏中实现了人工智能,那么就可以轻松设置一个人工智能驾驶员来代替用户输入)。
  • 以最高的画质设置运行游戏,看看设备是否支持。
  • 运行技术测试(编译多个着色器,执行这些着色器,检查输出结果是否与预期一样,等等)。

Test Loop Manager

为了帮助您集成游戏循环并在您的本地设备上运行这些循环,以及帮助您的质量保证团队在他们的设备上运行游戏循环,我们提供了一个名为 Test Loop Manager 的开源应用。

要使用 Test Loop Manager,请执行以下操作:

  1. 下载 Test Loop Manager
  2. 使用以下命令在您的设备上安装 Test Loop Manager:
    adb install testloopmanager.apk
  3. 在手机或平板电脑上打开应用(名为“Test Loop Apps”);您将看到该设备上包含游戏循环的应用的列表。如果在这里看不到您的应用,请检查以确保您的 intent 过滤器与启动循环中描述的 intent 过滤器相匹配。
  4. 选择您要测试的游戏应用。
    1. 从列表中点击游戏应用的名称后,选择该应用实现的场景(即游戏循环)。如果您的应用实现了多个循环,请参阅多个游戏循环
    2. 点击 Run test,并在运行场景时进行观察。

关闭游戏应用

在测试结束时,您应该使用以下代码关闭应用:

yourActivity.finish();

通常,游戏循环测试可以让界面框架启动下一轮循环。如果您没有关闭该应用,运行循环的界面框架将不知道测试已经完成,并且可能会在一段时间后终止该应用。

在测试实验室中运行游戏循环测试

转到 Firebase 控制台并创建一个项目(如果您还没有任何项目)。要免费使用测试实验室,可使用 Spark 结算方案,但每日配额有一定限制。要了解如何无限制地使用测试实验室,请参阅 Firebase 定价方案

使用 Firebase 控制台

按照以下说明使用 Firebase 控制台运行游戏循环测试:

  1. 在 Firebase 控制台中,点击左侧导航面板中的 Test Lab(测试实验室)。
  2. 点击运行首个测试(如果您的项目以前运行过测试,则点击运行测试)。
  3. 选择游戏循环作为测试类型,然后点击继续
  4. 点击浏览以找到您的应用的 .apk 文件。
  5. (可选)要选择一部分可用的场景(游戏循环),请执行以下操作之一:

    • 要选择特定场景,请在场景字段中输入场景编号的列表或范围。
    • 要选择所有带有特定标签的场景,请在标签字段中输入一个或多个场景标签。
  6. 点击继续

  7. 选择要用于测试您的应用的真机设备。

  8. 点击开始测试

如需详细了解 Firebase 控制台,请参阅通过 Firebase 控制台使用 Firebase 测试实验室

使用 gcloud 命令行环境

按照以下说明使用 gcloud 命令行环境 (CLI) 运行游戏循环测试:

  1. 如果您还没有 Firebase 项目,可转到 Firebase 控制台,然后点击添加项目以创建一个项目。
  2. 安装 Google Cloud SDK,其中包括 gcloud CLI。
  3. 使用 Google 帐号登录:

    gcloud auth login

  4. 使用以下命令设置您的 Firebase 项目,其中 PROJECT_ID 就是您在第 1 步中所创建的 Firebase 项目:

    gcloud config set project PROJECT_ID
    
  5. 运行您的第一个测试,如下所示:

    gcloud beta firebase test android run \
    --type=game-loop --app=<path-to-apk> \
    --device model=herolte,version=23
  6. (可选)要选择一部分可用的场景(游戏循环),请在运行游戏循环测试时执行以下操作之一:

    • 要选择特定场景,请使用 --scenario-numbers 标记来指定一个场景编号列表(例如,--scenario-numbers=1,3,5)。
    • 要选择所有带有特定标签的场景,请使用 --scenario-labels 标记指定一个或多个场景标签(例如,--scenario-labels=performance,gpu)。

如需详细了解如何将 gcloud CLI 与测试实验室结合使用,请参阅从 gcloud 命令行使用 Firebase Android 测试实验室

可选功能

本部分将介绍如何使用可选功能,例如将数据写入输出文件、支持多个游戏循环,以及为相关循环加标签以便轻松地在单个测试矩阵中测试相关循环。

写入输出数据

您的游戏循环可以将输出结果写入到使用 launchIntent.getData() 方法提供的某个文件中。测试实验室可以在测试结果页面上显示这些输出数据。如需查看数据输出文件的示例,请参阅游戏循环测试输出文件示例

测试实验室遵循共享文件中描述的在应用之间共享文件的最佳做法。在您的 Activity 的 onCreate() 方法中,您在获取 intent 的同时,还可以使用以下代码检查是否存在共享的文件:

Uri logFile = launchIntent.getData();
if (logFile != null) {
   Log.i(TAG, &quot;Log file &quot; + logFile.getEncodedPath());
   // ...
}
如果要在游戏应用的 C++ 代码中向该文件写入内容,您需要传递文件描述符,而不是文件路径,如以下示例代码中所示:

Java:

Uri logFile = launchIntent.getData();
int fd = -1;
if (logFile != null) {
   Log.i(TAG, &quot;Log file &quot; + logFile.getEncodedPath());
   try {
       fd = getContentResolver()
               .openAssetFileDescriptor(logFile, &quot;w&quot;)
               .getParcelFileDescriptor()
               .getFd();
   } catch (FileNotFoundException e) {
       e.printStackTrace();
       fd = -1;
   } catch (NullPointerException e) {
       e.printStackTrace();
       fd = -1;
   }
}
native_function(fd);  // C++ code invoked here.
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);
}

多个游戏循环

您还可以在自己的游戏应用中支持多个游戏循环。例如,如果您的游戏中有多个关卡,建议您最好针对每个关卡分别使用一个游戏循环来启动,而不是用一个循环来遍历所有的关卡。

这样一来,如果您的应用在第 32 关崩溃,您可以直接启动相应的游戏循环,尝试重现崩溃问题并对问题修复代码进行测试。

例如,如果您的应用中有 5 个游戏循环,则只需要在该应用的清单文件的 <application> 元素中添加一行代码:

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

然后,当您启动 Test Loop Manager 时,就可以使用一个选择屏幕来选择要启动的循环。如果您选择了多个要启动的循环,它将在前一个循环完成后依次启动每个循环。使用测试实验室,您可以选择要启动哪些循环。

启动 intent 中以整型参数的形式包含了目标循环,范围从 1 到支持的最大循环数。

您可以从 intent 中读取 extra,如以下 Java 示例代码中所示:

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

然后,您可以将此 extra 传递给您的原生 C++ 代码,以根据生成的 int 值更改循环的行为。

给游戏循环加标签

您可以使用一个或多个场景标签来标注游戏循环,以便您的质量保证团队能够轻松启动一组相关的游戏循环(例如“所有兼容性游戏循环”)。为此,您需要在应用的清单文件中添加一个 meta-data 行,类似于以下示例:

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

您可以创建自己的标签,我们也提供了 4 种预定义的标签:

  • com.google.test.loops.player_experience:用于在玩游戏时重现真实用户体验的循环。使用这些循环进行测试的目标是找出真实用户在玩游戏时会遇到的问题。
  • com.google.test.loops.gpu_compatibility:用于测试 GPU 相关问题的循环。使用这些循环进行测试的目标是执行在正式环境中可能无法正常运行的 GPU 代码,以暴露出硬件和驱动程序的问题。
  • com.google.test.loops.compatibility:用于测试各种各样的兼容性问题(包括 I/O 问题和 OpenSSL 问题)的循环。
  • com.google.test.loops.performance:用于测试设备性能的循环。例如,游戏可能会在最复杂的图形设置下运行,以了解新设备的性能。

应用许可支持

测试实验室支持使用 Google Play 应用许可服务的应用。在通过测试实验室测试您的应用时,要成功检查许可,您必须将该应用发布到 Play 商店中的正式版渠道。要使用测试实验室在 Alpha 或 Beta 渠道中测试您的应用,请在将该应用上传到测试实验室之前取消许可检查。

已知问题

测试实验室中的游戏循环测试存在以下已知的问题:

  • 对于 Khronos Vulkan API 的支持有限。测试实验室中只有以下设备支持 Vulkan API:Samsung Galaxy S7(API 级别 24)、Google Pixel(API 级别 25)。
  • 部分崩溃不支持回溯。例如,某些正式版本可能会使用 prctl(PR_SET_DUMPABLE, 0) 来抑制 debuggerd 进程的输出。如需了解详情,请参阅 debuggerd
  • 由于文件权限错误,因此目前不支持 API 级别 19。

游戏循环测试输出文件示例

您可以使用如以下示例中所示格式的输出数据文件,在 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
}

发送以下问题的反馈:

此网页
需要帮助?请访问我们的支持页面