Automated Testing February 2026

Automated Visual Proof: Integrating Video Recording with Unreal Gauntlet

Transform abstract test logs into undeniable visual evidence.

The Missing Piece in Automation

Unreal Engine's Gauntlet automation framework is powerful for running tests at scale. It launches your game, runs scripts, and reports pass/fail status. But when a test fails, you're often left with a text log:

Error: Expected actor 'BP_Enemy_C_21' to be destroyed. Found active.
... 500 lines of callstacks ...

Why wasn't it destroyed? Did the projectile miss? Did the animation fail? Did it fall through the floor? Logs can't tell you. Video can.

The Solution: Gauntlet + RVR

By integrating Runtime Video Recorder (RVR) directly into your Gauntlet controllers, you can automatically capture a video for every test session. Because RVR works headless (without a monitor) and uses hardware acceleration, it adds minimal overhead to your CI pipeline.

Implementation Guide

The cleanest way to integrate is by creating a custom UGauntletTestController. This allows you to control exactly when recording starts and stops during your test lifecycle.

// MyGauntletController.h
#pragma once
#include "GauntletTestController.h"
#include "RuntimeVideoRecorder.h"
#include "MyGauntletController.generated.h"

UCLASS()
class UMyGauntletController : public UGauntletTestController
{
    GENERATED_BODY()

protected:
    // Called when the map finishes loading
    virtual void OnPostMapChange(UWorld* World) override
    {
        Super::OnPostMapChange(World);

        // Access the RVR subsystem
        if (URuntimeVideoRecorder* Recorder = GEngine->GetEngineSubsystem<URuntimeVideoRecorder>())
        {
            // Start recording automatically
            // %auto% generates a timestamped filename
            // We use a specific prefix to easily find it later
            Recorder->StartRecording(TEXT("GauntletTest_%auto%"));
            
            UE_LOG(LogGauntlet, Display, TEXT("Started Gauntlet Video Recording"));
        }
    }
    
    // Check for test completion
    virtual void OnTick(float DeltaTime) override
    {
        Super::OnTick(DeltaTime);

        // Your logic to determine if the test is done
        if (IsTestComplete()) 
        {
            if (URuntimeVideoRecorder* Recorder = GEngine->GetEngineSubsystem<URuntimeVideoRecorder>())
            {
                 // Ensure we close the file properly before exiting
                 Recorder->StopRecording_NativeAPI();
                 UE_LOG(LogGauntlet, Display, TEXT("Stopped Gauntlet Video Recording"));
            }
            
            EndTest(0);
        }
    }
    
    // Helper to determine if test finished (example)
    bool IsTestComplete() const
    {
        // ... Check your test state ...
        return false; 
    }
};

Running with Gauntlet

Once compiled, you can instruct Gauntlet to use your controller via the command line or your C# build script.

# Command Line Example

RunUAT.bat BuildCookRun -project="MyProject" -platform=Win64 -client -gauntlet -GauntletTestController="MyGauntletController"

Why This Changes Everything

Headless Recording

Most recorders (OBS, ShadowPlay) require a monitor. RVR works on headless servers, Docker containers, and cloud instances.

Cross-Platform

The same code works for Windows, Android, and iOS tests. Validate mobile touch inputs and gestures visually.

Artifact Collection

Gauntlet automatically collects saved files from the Saved/ directory. Your videos appear right next to your logs in the build report.

Zero Flakiness

RVR runs inside the Unreal Engine process. It starts when the engine starts. No "forgot to press record" or "recorder crashed" external issues.