M4.2 — Configuration & context¶
What you'll learn
- How
UnrealTestConfigurationdeclares the roles and arguments a test needs. - What
UnrealTestContextprovides at runtime (build, devices, options). - The split between declaring intent (config) and reacting to reality (context).
How it applies (QA)
This is where the role layout you designed on paper in M3.2 becomes code. The configuration is the single most edited part of a real test — adding a client, changing a server arg, bumping the timeout. Reading and writing it fluently is most of day-to-day Gauntlet authoring.
Concepts¶
UnrealTestConfiguration — declaring intent¶
Your test exposes its configuration by overriding GetConfiguration(). The returned
UnrealTestConfiguration (your TConfig) declares what the session must contain:
- Roles — request each participant and its type (client, server, editor). Requesting a role hands you back a role object whose command line and options you can tune.
- Per-role arguments — append game args to a specific role (the server gets the host switch and map; clients get the connect target).
- Global test options — most importantly
MaxDuration(the timeout after which the run is abandoned), plus other knobs the base exposes.
This is the declare intent step from M3.1: you describe the UnrealSession you want; the base
class builds and launches it.
public class MyBootTestConfig : UnrealTestConfiguration { }
public class MyBootTest : UnrealTestNode<MyBootTestConfig>
{
public MyBootTest(UnrealTestContext context) : base(context) { }
public override MyBootTestConfig GetConfiguration()
{
var Config = base.GetConfiguration();
// Declare one client role and tune it.
var Client = Config.RequireRole(UnrealTargetRole.Client);
Client.CommandLine += " -windowed -resx=1280 -resy=720";
// Global: give boot up to 120s before declaring a timeout.
Config.MaxDuration = 120;
return Config;
}
}
For the 2-clients + 1-server layout, you'd RequireRole a Server and two Clients and set each
one's args. Verify on a real build: the exact role-request API (RequireRole, the
UnrealTargetRole names) and config property names vary by version; the structure — request roles,
set args, set duration — is stable.
UnrealTestContext — the reality handed to you¶
Where the configuration says what you want, the UnrealTestContext (passed to your
constructor) carries what you actually got for this run:
- The build to run (resolved by
UnrealBuildSource). - The device(s) the roles will run on.
- The options/parameters the run was invoked with.
The base class uses the context to realize your configuration into a live
UnrealSessionInstance. You read the context when your logic needs to know about the concrete run —
which build, which platform, which device — rather than the abstract intent.
Intent vs. reality, side by side¶
UnrealTestConfiguration |
UnrealTestContext |
|
|---|---|---|
| Answers | "What does this test need?" | "What did this run actually get?" |
| You | write it (declare roles/args/duration) | read it (build/devices/options) |
| Timing | before launch | at/through the run |
| Analogy | the blueprint | the site survey |
Pitfall: a too-short MaxDuration reads as a product bug
If MaxDuration is shorter than the legitimate boot/load time on a slow target (a cold console,
a big map), the run times out and goes red while the game was fine, just slow. Before filing
"boot is broken on PS5," check whether the timeout is realistic for that device/build. Set
durations against the slowest target you run, not your dev PC.
Worked example — declaring the 1-server/2-client layout¶
public override MyMatchTestConfig GetConfiguration()
{
var Config = base.GetConfiguration();
var Server = Config.RequireRole(UnrealTargetRole.Server);
Server.CommandLine += " /Game/Maps/TestArena?listen";
var Client0 = Config.RequireRole(UnrealTargetRole.Client);
var Client1 = Config.RequireRole(UnrealTargetRole.Client);
// Clients connect to the server; Gauntlet wires the address (M3.2).
Config.MaxDuration = 300; // a full short match on the slowest target
return Config;
}
This is M3.2's table expressed in code: three roles requested, the server given a map + listen switch, a duration sized for a real match. The base class turns it into the launched session.
Exercise 1 — Config or context?
For each need, say whether you'd write it into UnrealTestConfiguration or read it from
UnrealTestContext:
- "This test needs a dedicated server and two clients."
- "Which platform am I actually running on right now?"
- "The server should host
TestArenawith?listen." - "Where is the build that got resolved for this run?"
- "Abandon the run after 5 minutes."
Lab — Turn your M3.3 layout into a GetConfiguration()
Take the scaled layout from the M3.3 lab (server on host, clients on devices). Write the
GetConfiguration() for it: request the roles, give the server its map/listen args, set a
MaxDuration justified for the slowest device. Mark every line you're unsure of with verify on
a real build.
Self-check — answers
Exercise 1: 1 config (declare roles), 2 context (the run's actual platform), 3 config (server
args), 4 context (resolved build location), 5 config (MaxDuration).
Lab: Expect three RequireRole calls (1 Server, 2 Client), the server's
CommandLine += " /Game/Maps/...?listen", and Config.MaxDuration set generously for the
console clients (e.g. 300+). The device placement itself comes from the run/pool config, not
GetConfiguration() — a good thing to have flagged as verify on a real build, since how a role
is pinned to a specific device is studio-/version-specific.
Done when
- [ ] You can write a
GetConfiguration()that requests roles, sets per-role args, and setsMaxDuration. - [ ] You can explain what
UnrealTestContextcarries and when you read it. - [ ] You can sort a given need into config (intent) vs. context (reality).
- [ ] You can explain how a bad
MaxDurationmasquerades as a product failure.