Get started with Game Loop tests

It can be hard to automate game testing when gaming apps are built on differentUI frameworks. Game Loop tests allow you to integrate your native tests withTest Lab and easily run them on devices you select. A Game Loop test runs yourtest through your gaming app while simulating the actions of a real player. Thisguide shows you how to run a Game Loop test, then view and manage your testresults in theFirebase console.

Depending on your game engine, you can implement tests with single or multipleloops. A loop is a full or partial run-through of your teston your gaming app. Game loops can be used to:

  • Run a level of your game the same way an end user would play it. You caneither script the input of the user, let the user be idle, or replace theuserwith an AI if it makes sense in your game (e.g., say you have a race cargaming app and already have an AI implemented. You can easily put an AIdriverin charge of the user's input).
  • Run your game at the highest quality setting to see if devices support it.
  • Run a technical test (compile multiple shaders, execute them, check that theoutput is as expected, etc).

You can run a Game Loop test on a single test device, a set of test devices, oronTest Lab. However, we don't recommend running Game Loop tests on virtualdevices because they have lower graphics frame rates than physical devices.

Note:Test Lab offers additional features to help you customize yourGame Loop tests, such as the ability to run multiple loops at once, or toorganize your loops with labels. For more information on these features, seeOptional features.

Before you begin

To implement a test, you must first configure your app for Game Loop tests.

  1. In your app manifest, add a new intent filter to youractivity:

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

    This allowsTest Lab to launch your game by triggering it with a specificintent.

    Note: Game loops require a separate, dedicated intent filter that is not usedfor other purposes. Your activity can include other intent filters. To learnmore about intent filters, see the<intent-filter> reference page.
  2. In your code (we recommend inside theonCreate method declaration), add thefollowing:

    Kotlin

    vallaunchIntent=intentif(launchIntent.action=="com.google.intent.action.TEST_LOOP"){valscenario=launchIntent.getIntExtra("scenario",0)// Code to handle your game loop here}

    Java

    IntentlaunchIntent=getIntent();if(launchIntent.getAction().equals("com.google.intent.action.TEST_LOOP")){intscenario=launchIntent.getIntExtra("scenario",0);// Code to handle your game loop here}

    This allows your activity to check the intent that launches it. You can alsoadd this code later if you prefer (e.g., after initially loading your gameengine).

  3. Recommended: At the end of the test, add:

    Kotlin

    yourActivity.finish()

    Java

    yourActivity.finish();

    This closes your app when the Game Loop test is complete. The test relies onyour app's UI framework to start the next loop, and closing your app tells itthat the test is finished.

Create and run a Game Loop test

After you configure your app for Game Loop tests, you can immediately create atest and run it in your gaming app. You can choose to run a test inTest Lab using either theFirebase console or thegcloudcommand line interface (CLI), or on alocal device using the Test LoopManager.

Run on a local device

Test Lab'sTest Loop Manager is an open source app that helps youintegrate Game Loop tests and run them on your local devices. It also allows yourQuality Assurance team to run the same game loops on their devices.

To run a test on a local device using the Test Loop Manager:

  1. Download theTest Loop Manageron a phone or tablet and install it by running:
    adb install testloopmanager.apk
  2. On your device, open theTest Loop Apps app on your phone ortablet. The app displays a list of apps on your device thatcan be run with game loops. If you don't see your gaming app here, make sureyour intent filter matches the one described in the first step of theBefore you begin section.
  3. Select your gaming app, then select the number of loops you want to run.Note: At this step, you can choose to run a subset of loops instead of justone loop. For more information onrunning multiple loops at once, seeOptional features.
  4. ClickRun test. Your test starts running immediately.
Note: Game Loop tests have a default timeout of three minutes. When the timeoutends, the test terminates and cancels all pending loops. To set a differenttimeout duration in theTest Loop Manager app, clickmenu >Settimeout, then change the timeout in the dialogue that appears.

Run inTest Lab

You can run a Game Loop test inTest Lab using either theFirebase console or thegcloud CLI. Before youbegin, if you haven't already, open theFirebase console and create a project.

Note: You can useTest Lab at no charge with the Spark pricing plan, whichcomes with a limited daily quota. For more information about other pricing plansand usage limits, seeFirebase Pricing Plans.

Use theFirebase console

  1. In theFirebase console, clickTest Lab from the left panel.
  2. ClickRun Your First Test (orRun a Test if your project haspreviously run a test).
  3. SelectGame Loop as the test type, and then clickContinue.
  4. ClickBrowse, and then browse to your app's.apk file.Note: At this step, you can choose to run a subset of loops instead of justone loop. For more information onrunning multiple loops at once, seeOptional features.
  5. ClickContinue.
  6. Select the physical devices to use to test your app.
  7. ClickStart Tests.

For more information on getting started with theFirebase console, seeStart testing with theFirebase console.

Use the gcloud command-line (CLI)

  1. If you haven't already, download and install theGoogle Cloud SDK

  2. Sign in to the gcloud CLI using your Google Account:

    gcloud auth login

  3. Set your Firebase project in gcloud, wherePROJECT_ID isthe ID of your Firebase project:

    gcloud config set project PROJECT_ID
  4. Run your first test:

    gcloud firebase test android run \ --type=game-loop --app=<var>path-to-apk</var> \ --device model=herolte,version=23
    Note: At this step, you can choose to run a subset of loops instead of justone loop. For more information on running multiple loops at once, seeOptional features.

For more information on getting started with the gcloud CLI, seeStart testing from the gcloud command line.

Optional features

Test Lab offers several optional features that let you further customize yourtests, including the ability to write output data, support for multiple gameloops, and labels for related loops.

Write output data

Your Game Loop test can write output to a file specified in thelaunchIntent.getData() method. After you run a test, you can access thisoutput data in theTest Lab section of theFirebase console (seeGame Loop test output file example).

Test Lab follows best practices for sharing a file between apps described inSharing a File.In your activity’sonCreate() method, where your intent is located, youcan check your data output file by running following code:

Kotlin

vallaunchIntent=intentvallogFile=launchIntent.datalogFile?.let{Log.i(TAG,"Log file${it.encodedPath}")// ...}

Java

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

If you want to write to the file from the C++ side of your game app, you canpass in the file descriptor instead of the file path:

Kotlin

vallaunchIntent=intentvallogFile=launchIntent.datavarfd=-1logFile?.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

IntentlaunchIntent=getIntent();UrilogFile=launchIntent.getData();intfd=-1;if(logFile!=null){Log.i(TAG,"Log file "+logFile.getEncodedPath());try{fd=getContentResolver().openAssetFileDescriptor(logFile,"w").getParcelFileDescriptor().getFd();}catch(FileNotFoundExceptione){e.printStackTrace();fd=-1;}catch(NullPointerExceptione){e.printStackTrace();fd=-1;}}// C++ code invoked here.// native_function(fd);

C++

#include<unistd.h>JNIEXPORTvoidJNICALLJava_my_package_name_MyActivity_native_function(JNIEnv*env,jclasstype,jintlog_file_descriptor){// The file descriptor needs to be duplicated.intmy_file_descriptor=dup(log_file_descriptor);}

Output file example

You can use output data files (formatted like the example below) to display gameloop test results in theTest Lab section of theFirebase console.Areas shown as/.../ can contain any custom fields that you need, as long asthey don't conflict with the names of other fields used in this file:

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

Multiple game loops

You might find it useful to run multiple game loops in your app. A loop is acomplete run-through of your game app from beginning to end. For example, if youhave multiple levels in your game, you might want to have one game loop tolaunch each level instead of having one loop that iterates through all of them.That way, if your app crashes on level 32, you can directly launch that gameloop to reproduce the crash and test bug fixes.

To enable your app to run multiple loops at once:

  • If you're running a test with the Test Loop Manager:

    1. Add the following line to your app's manifest, inside the<application> element:

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

      This launch intent contains the target loop as an integer parameter. Intheandroid:value field, you can specify an integer from 1 to 1024 (themaximum number of loops allowed for a single test). Notethat loops are indexed starting from 1, not 0.

    2. In the Test Loop Manager app, a selection screen appears thatallows you to select which loop(s) you want to run. If you select multipleloops, each loop is launched in sequence after the preceding loopcompletes.

  • If you're running a test with theFirebase console, enter a list or arange of loop numbers in theScenarios field.

  • If you're running a test with the gcloud CLI, specify a list of loop numbersby using the--scenario-numbers flag. For example,--scenario-numbers=1,3,5 runs loops 1, 3, and 5.

  • If you're writing C++ and want to change the behavior of your loop, pass thefollowing extra to your native C++ code:

    Kotlin

    vallaunchIntent=intentvalscenario=launchIntent.getIntExtra("scenario",0)

    Java

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

    You can now change the behavior of your loop based on the resultingintvalue.

Label game loops

When you label your game loops with one or more scenario labels, you and your QAteam can easily launch a set of related game loops (e.g., "all compatibilitygame loops") and test them in a single matrix. You can create your own labels oruse the predefined labels offered byTest Lab:

  • com.google.test.loops.player_experience: For loops used toreproduce a real user's experience when playing the game. The goal oftesting with these loops is to find issues that a real user would face whileplaying the game.
  • com.google.test.loops.gpu_compatibility: For loops used to testGPU-related issues. The goal of testing with these loops is to execute GPUcode that might not run properly run in production, to expose issues withhardware and drivers.
  • com.google.test.loops.compatibility: For loops used to test abroad range of compatibility issues, including I/O issues and OpenSSLissues.
  • com.google.test.loops.performance: For loops used to test theperformance of the device. For example, a game might run at the most complexgraphics settings to see how a new device behaves.

To enable your app to run loops with the same label:

  • If you're running a test with the Test Loop Manager:

    1. In your app's manifest, add the following meta-data line and replaceLABEL_NAME with a label of your choice:

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

      In theandroid:value field, you can specify a range or a set of integersfrom 1 to 1024 (the maximum number of loops allowed for a single test) thatrepresent the loops you want to label. Note that loops are indexed startingfrom 1, not 0. For example,android:value="1,3-5" appliesLABEL_NAME to loops 1, 3, 4, and 5.

    2. In the Test Loop Manager app, enter one or more labels in theLabelsfield.

  • If you're running a test with theFirebase console, enter one or morelabels in theLabels field.

  • If you're running a test with the gcloud CLI, specify one or more scenario labels by using the--scenario-labels flag (e.g.,--scenario-labels=performance,gpu).

App licensing support

Test Lab supports apps that use theApp Licensingservice offered by Google Play. To successfully check licensing when testingyour app withTest Lab, you must publish your app to the production channelin the Play store. To test your app in the alpha or beta channel usingTest Lab, remove the licensing check before uploading your app toTest Lab.

Known issues

Game Loop tests inTest Lab have the following known issues:

  • Some crashes do not support backtraces. For example, some release builds maysuppress the output of thedebuggerd process usingprctl(PR_SET_DUMPABLE, 0). To learn more, seedebuggerd.
  • API Level 19 is not currently supported due to file permission errors.

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025-12-11 UTC.