Join us for Firebase Summit on November 10, 2021. Tune in to learn how Firebase can help you accelerate app development, release with confidence, and scale with ease. Register

运行游戏循环测试

当游戏应用程序构建在不同的 UI 框架上时,游戏测试自动化可能很困难。游戏循环测试允许您将本机测试与测试实验室集成,并在您选择的设备上轻松运行它们。本指南介绍了如何使用 Firebase 测试实验室准备要运行的游戏循环测试。

关于游戏循环测试

什么是游戏循环测试?

游戏循环测试模拟真实玩家的动作,以快速且可扩展的方式验证您的游戏是否对用户表现良好。循环是对游戏应用程序测试的全部或部分运行。您可以在模拟器或测试实验室中的一组设备上本地运行游戏循环测试。游戏循环测试可用于:

  • 像最终用户一样运行您的游戏。您可以编写用户输入的脚本,让用户空闲,或者用 AI 替换用户(例如,如果您在赛车游戏中实现了 AI,则可以让 AI 驱动程序负责用户的输入) .
  • 以最高质量设置运行您的游戏,以找出哪些设备可以支持它。
  • 运行技术测试,例如编译多个着色器、执行它们并检查输出是否符合预期。

第1步:注册测试实验室的自定义URL方案

  1. 在 Xcode 中,选择一个项目目标。

  2. 单击信息选项卡,然后添加一个新的URL类型

  3. URL方案字段中输入firebase-game-loop 。您也可以通过将其添加到项目的注册自定义URL方案Info.plist的内部配置文件中的任何地方<dict>标签:

    <key>CFBundleURLTypes</key>
     <array>
         <dict>
             <key>CFBundleURLName</key>
             <string></string>
             <key>CFBundleTypeRole</key>
             <string>Editor</string>
             <key>CFBundleURLSchemes</key>
             <array>
                 <string>firebase-game-loop</string>
             </array>
         </dict>
     </array>
    

您的应用现已配置为使用测试实验室运行测试。

第2步:可选配置应用

运行多个循环

如果您计划在测试中运行多个循环(也称为场景),则必须指定要在启动时在应用程序中运行的循环。

在您的应用程序的委托,重写application(_:open:options:)方法:

迅速

func application(_app: UIApplication,
                 open url: URL
                 options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    let components = URLComponents(url: url, resolvingAgainstBaseURL: true)!
    if components.scheme == "firebase-game-loop" {
        // ...Enter Game Loop Test logic to override application(_:open:options:).
    }
    return true
}

目标-C

- (BOOL)application:(UIApplication *)app
            openURL:(NSURL *)url
            options:(NSDictionary &lt;UIApplicationOpenURLOptionsKey, id&gt; *)options {
  if ([url.scheme isEqualToString:(@"firebase-game-loop")]) {
      // ...Enter Game Loop Test logic to override application(_:open:options:).
  }
}

当您在测试中运行多个循环时,当前循环将作为参数传递给用于启动应用程序的 URL。您也可以通过分析获得的电流回路数URLComponents对象用于获取自定义URL方案:

迅速

if components.scheme == "firebase-game-loop" {
    // Iterate over all parameters and find the one with the key "scenario".
    let scenarioNum = Int(components.queryItems!.first(where: { $0.name == "scenario" })!.value!)!
    // ...Write logic specific to the current loop (scenarioNum).
}

目标-C

if ([url.scheme isEqualToString:(@"firebase-game-loop")]) {
    // Launch the app as part of a game loop.
    NSURLComponents *components = [NSURLComponents componentsWithURL:url
                                             resolvingAgainstBaseURL:YES];
    for (NSURLQueryItem *item in [components queryItems]) {
        if ([item.name isEqualToString:@"scenario"]) {
            NSInteger scenarioNum = [item.value integerValue];
            // ...Write logic specific to the current loop (scenarioNum).
        }
    }
}

提前结束测试

默认情况下,游戏循环测试会继续运行,直到达到五分钟的超时,即使所有循环都已执行。达到超时后,测试结束并取消任何挂起的循环。您可以加快您的测试或致电测试实验室的自定义URL方案,提前结束其firebase-game-loop-complete应用程式的AppDelegate中。例如:

迅速

/// End the loop by calling our custom url scheme.
func finishLoop() {
    let url = URL(string: "firebase-game-loop-complete://")!
    UIApplication.shared.open(url)
}

目标-C

- (void)finishLoop {
  UIApplication *app = [UIApplication sharedApplication];
  [app openURL:[NSURL URLWithString:@"firebase-game-loop-complete://"]
      options:@{}
completionHandler:^(BOOL success) {}];
}

您的游戏循环测试会终止当前循环并执行下一个循环。当没有更多的循环运行时,测试结束。

编写自定义测试结果

您可以配置游戏循环测试以将自定义测试结果写入设备的文件系统。这样一来,当测试开始运行,测试实验室保存的结果文件GameLoopsResults目录您的测试设备上(你必须自己创建)。当测试结束后,测试实验室从移动所有文件GameLoopResults目录到项目的水桶。设置测试时请记住以下几点:

  • 无论文件类型、大小或数量如何,都会上传所有结果文件。

  • 在测试中的所有循环都完成运行之前,测试实验室不会处理您的测试结果,因此如果您的测试包含多个写入输出的循环,请确保将它们附加到唯一的结果文件或为每个循环创建一个结果文件。这样,您可以避免覆盖先前循环的结果。

要设置测试以编写自定义测试结果:

  1. 在您的应用程序的Documents目录下创建一个名为GameLoopResults

  2. 从您应用程序代码的任何位置(例如,您的应用程序委托),添加以下内容:

    迅速

    /// Write to a results file.
    func writeResults() {
      let text = "Greetings from game loops!"
      let fileName = "results.txt"
      let fileManager = FileManager.default
      do {
    
      let docs = try fileManager.url(for: .documentDirectory,
                                     in: .userDomainMask,
                                     appropriateFor: nil,
                                     create: true)
      let resultsDir = docs.appendingPathComponent("GameLoopResults")
      try fileManager.createDirectory(
          at: resultsDir,
          withIntermediateDirectories: true,
          attributes: nil)
      let fileURL = resultsDir.appendingPathComponent(fileName)
      try text.write(to: fileURL, atomically: false, encoding: .utf8)
      } catch {
        // ...Handle error writing to file.
      }
    }
    

    目标-C

    /// Write to a results file.
    - (void)writeResults:(NSString *)message {
        // Locate and create the results directory (if it doesn't exist already).
        NSFileManager *manager = [NSFileManager defaultManager];
        NSURL* url = [[manager URLsForDirectory:NSDocumentDirectory
                                      inDomains:NSUserDomainMask] lastObject];
        NSURL* resultsDir = [url URLByAppendingPathComponent:@"GameLoopResults"
                                                 isDirectory:YES];
        [manager createDirectoryAtURL:resultsDir
          withIntermediateDirectories:NO
                           attributes:nil
                                error:nil];
    
        // Write the result message to a text file.
        NSURL* resultFile = [resultsDir URLByAppendingPathComponent:@"result.txt"];
        if ([manager fileExistsAtPath:[resultFile path]]) {
            // Append to the existing file
            NSFileHandle *handle = [NSFileHandle fileHandleForWritingToURL:resultFile
                                                                     error:nil];
            [handle seekToEndOfFile];
            [handle writeData:[message dataUsingEncoding:NSUTF8StringEncoding]];
            [handle closeFile];
        } else {
            // Create and write to the file.
            [message writeToURL:resultFile
                     atomically:NO
                       encoding:NSUTF8StringEncoding error:nil];
        }
    }
    

第3步:您打包用于上传应用程序

最后,为您的应用生成一个 IPA 文件(稍后您需要找到它)。

  1. 在 Xcode 中,为目标应用程序选择一个配置文件。

  2. 从下拉菜单中出现,单击产品>存档。选择最新的归档,然后单击分发应用程序

  3. 在出现的窗口中,单击开发>下一步

  4. 可选:要获得更快的构建,取消选项位码重建,然后单击下一步。测试实验室不需要精简或重建您的应用程序来运行测试,因此您可以安全地禁用此选项。

  5. 单击导出,然后输入要下载你的应用程序的IPA文件的目录。

第4步:运行在本地测试

在使用测试实验室运行之前,您可以在本地运行测试以检查其行为。要在本地进行测试,请在模拟器中加载您的游戏应用程序并运行:

xcrun simctl openurl SIMULATOR_UDID firebase-game-loop://
  • 您可以通过运行找到你的模拟器的UDID instruments -s devices命令。

  • 如果只有一个模拟器中运行,进入特殊字符串"booted"代替SIMULATOR_UDID

如果您的测试包含多个循环,你可以通过回路数到指定要运行该循环scenario标志。请注意,在本地运行测试时,一次只能运行一个循环。例如,如果要运行循环 1、2 和 5,则必须为每个循环运行单独的命令:

xcrun simctl openurl SIMULATOR_UDID firebase-game-loop://?scenario=1
xcrun simctl openurl SIMULATOR_UDID firebase-game-loop://?scenario=2
xcrun simctl openurl SIMULATOR_UDID firebase-game-loop://?scenario=5

下一步

运行使用您的测试火力地堡控制台gcloud CLI