Skip to content

M1.3 — The three-tier architecture (as a debugging map)

What you'll learn

  • Gauntlet's three layers: core interfaces + execution, platform implementations + session, and test implementation + UAT integration.
  • The key classes in each tier, and what each tier owns.
  • How to use the tiers as a fault-localization map: when a run fails, which layer to suspect.

How it applies (QA)

You will spend more time reading Gauntlet failures than writing Gauntlet tests. A failure is cheaper to diagnose when you can place it: "the device never connected" (tier 2) is a different investigation from "the test logic declared the wrong verdict" (tier 3). The architecture is less an engineering curiosity than a triage flowchart.

Concepts

Gauntlet is layered so that the same test logic runs unchanged across platforms. Each tier hides the one below it.

Tier 1 — Core interfaces & execution framework

Platform-independent low-level units. Pure abstractions plus the engine that runs tests.

  • Devices: ITargetDevice — "a thing a build can be installed on and launched."
  • Builds: IBuildSource, IBuild — "where builds come from" and "a specific build."
  • Apps: IAppInstall, IAppInstance — "an installed app" and "a running instance of it."
  • Tests: ITestNode (the interface every test implements) and TestExecutor (creates, queues, and monitors a set of tests; supports parallel execution).

This tier knows nothing about Windows, PS5, or even Unreal specifically — it is the contract.

Tier 2 — Platform implementations & session management

The concrete classes that satisfy tier 1 on real platforms, plus the classes that turn a set of roles into a running game.

  • Device implementations: TargetDeviceWindows, TargetDeviceMac, TargetDevicePS4, TargetDeviceXboxOne, TargetDeviceSwitch, TargetDeviceIOS, TargetDeviceAndroid, and so on — one per platform Unreal supports.
  • Session classes: UnrealAppConfig (how to launch one process), UnrealSessionRole (one participant — a client, server, or editor), UnrealSession (the whole arrangement of roles), and UnrealSessionInstance (a live, running session).

This is where "run the game" becomes real: install the build on TargetDeviceSwitch, launch each UnrealSessionRole with its UnrealAppConfig, hold them in a UnrealSessionInstance.

Tier 3 — Test implementation & UAT integration

The Unreal-aware, author-facing layer — the part you write and invoke.

  • UnrealBuildSource — the Unreal-specific IBuildSource: finds and describes cooked Unreal builds.
  • UnrealTestConfiguration — declares what a test needs: which roles, what arguments.
  • UnrealTestContext — the runtime context handed to a test (the build, the devices, the options it runs under).
  • UnrealTestNode — the base class real tests derive from; implements ITestNode largely by configuring a UnrealSession and reacting to it.
  • RunUnreal — the [UAT] BuildCommand that is the entry point: it parses parameters, builds the list of tests, and drives TestExecutor.

When you author a test (M4), you live almost entirely in tier 3, leaning on tiers 1–2 without touching them.

The map, drawn

Tier 3  RunUnreal ─▶ UnrealTestNode (your test) ─▶ UnrealTestConfiguration / UnrealTestContext
            │              │  uses UnrealBuildSource
            ▼              ▼
Tier 2  TestExecutor   UnrealSession ─▶ UnrealSessionRole(s) ─▶ UnrealAppConfig
                           │                                         runs on
                           ▼                                         ▼
Tier 1  ITestNode      IBuild / IBuildSource        ITargetDevice / IAppInstance

Worked example — failure localization

Read the symptom, name the suspect tier:

Symptom in the log Likely tier First thing to check
"No build found for platform Win64" Tier 3 (UnrealBuildSource) / upstream Was it cooked & staged? Is -build= pointing at the right path?
Devkit never reaches "connected"; launch times out Tier 2 (TargetDevice*) Device reservation, network, devkit state.
Server starts but clients never join Tier 2 (UnrealSessionRole config) Role args, ports, launch order.
Session ran fine but verdict is wrong Tier 3 (your UnrealTestNode) Your pass/fail logic.
Tests interfere when run together Tier 1 (TestExecutor) Parallelism / unique-port allocation.

The point: the same red X in CI has at least five different homes. Tiering tells you which door to open first.

Exercise 1 — Tier the class

For each class, give its tier (1/2/3) and one-line role: ITargetDevice, UnrealTestConfiguration, TargetDeviceAndroid, RunUnreal, IAppInstance, UnrealSessionInstance.

Exercise 2 — Localize the fault

Nightly Gauntlet job on PS5 fails. The log shows the build installed, the game launched, the main menu log line appeared — and then the job reports failed with no crash. Which tier owns this failure, and what's the most likely cause?

Lab — Draw your title's stack

Take a real (or imagined) test from your project: "boot the game on PC and confirm it reaches the main menu." On paper, fill the map for it:

  1. Tier 3: what UnrealTestNode subclass would own the verdict, and what's the verdict rule?
  2. Tier 2: how many UnrealSessionRoles, on which TargetDevice*?
  3. Tier 1: which IBuild/ITargetDevice concretes are in play?

Keep it — you'll extend this same sketch in M3 and M4.

Self-check — answers

Exercise 1:

  • ITargetDeviceTier 1, device abstraction.
  • UnrealTestConfigurationTier 3, declares roles/args a test needs.
  • TargetDeviceAndroidTier 2, Android device implementation.
  • RunUnrealTier 3, the UAT entry-point command.
  • IAppInstanceTier 1, a running app instance abstraction.
  • UnrealSessionInstanceTier 2, a live running session.

Exercise 2: Build installed + launched + menu reached, then "failed" with no crash → the session did its job; the verdict is wrong. That's Tier 3, your UnrealTestNode pass/ fail logic — most likely the success condition (e.g. the log string it waits for, or a timeout that fires before your "passed" marker). Not a device or session fault.

Done when

  • [ ] You can name the three tiers and what each owns.
  • [ ] You can place the core classes (ITargetDevice, UnrealSession*, UnrealTestNode, RunUnreal) in their tier.
  • [ ] Given a failure symptom, you can name the most likely tier before digging.
  • [ ] You've drawn the stack for one real test (the M1.3 lab) and kept it.

Next: M2.1 — RunUnreal & the UAT BuildCommand — the entry point, top of tier 3.