Get started with Game Loop tests for iOS

With Game Loop tests, you can write tests native to your game engine and then run them in Test Lab on devices you choose. This way, you don't need to worry about writing for different UI or testing frameworks. A Game Loop test simulates the actions of a real player, and when you run it on Test Lab, it provides a fast and scalable way to verify that your game performs well for your users.

This page shows you how to run a Game Loop test, then view and manage your test results in the Test Lab page of the Firebase console. You can also further customize your tests with optional features, such as writing custom test results or ending your test early.

What is a Game Loop Test?

A loop is a full or partial run-through of your test on your gaming app. You can run a Game Loop test locally on a simulator or on a set of devices in Test Lab. Game Loop tests can be used to:

Step 1: Register Test Lab’s custom URL scheme

First, you must register Firebase Test Lab's custom URL scheme in your app:

  1. In Xcode, select a project target.

  2. Click the Info tab, then add a new URL type.

  3. In the URL Schemes field, enter firebase-game-loop. You can also register the custom URL scheme by adding it to your project’s Info.plist configuration file anywhere within the <dict> tag:

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

Your app is now configured to run a test using Test Lab.

Step 2 (optional): Configure your app to run multiple loops

If your app has multiple custom URL schemes registered and you plan to run multiple loops (aka scenarios) in your test, you must specify which loops you want to run in your app at launch time.

In your app delegate, override the application(_:open:options:) method:

Swift

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
}

Objective-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:).
  }
}

When you run multiple loops in your test, the current loop is passed as a parameter to the URL used to launch the app. You can also obtain the current loop number by parsing the URLComponents object used to fetch the custom URL scheme:

Swift

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

Objective-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).
        }
    }
}

Step 3: Create and run a test

After you register Test Lab's custom URL scheme, you can run your test in the Firebase console or with the gcloud beta CLI. If you haven't already, generate an IPA file for your app (you'll need to locate it later).