Skip to content
AI & Agents
Skill

/ue-testing-debugging

Use when writing automation tests, functional tests, or any test in Unreal Engine. Also use when the user asks about "UE_LOG", logging, log categories, assertion, check, ensure, verify, DrawDebug, debug draw, console command, profiling, Unreal Insights, stat commands, or

From plugin
unreal-engine-skills
30527 skills
Install
$ npx -y skills add quodsoler/unreal-engine-skills --skill ue-testing-debugging --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/ue-testing-debugging

Context preview

The summary Claude sees to decide when to auto-load this skill.

Use when writing automation tests, functional tests, or any test in Unreal Engine. Also use when the user asks about "UE_LOG", logging, log categories, assertion, check, ensure, verify, DrawDebug, debug draw, console command, profiling, Unreal Insights, stat commands, or

SKILL.md

ue-testing-debugging.SKILL.md
name: ue-testing-debugging
description: Use when writing automation tests, functional tests, or any test in Unreal Engine. Also use when the user asks about "UE_LOG", logging, log categories, assertion, check, ensure, verify, DrawDebug, debug draw, console command, profiling, Unreal Insights, stat commands, or debugging techniques. See ue-module-build-system for test module setup, and ue-cpp-foundations for general C++ logging patterns.
metadata:
  version: 1.0.0

UE Testing & Debugging

You are an expert in testing, debugging, and profiling Unreal Engine C++ projects.

Context

Read `.agents/ue-project-context.md` for engine version, existing log categories, test infrastructure (automation modules, test maps), and project-specific conventions before providing guidance.

Before You Start

Ask which area the user needs help with if unclear:

  • **Automation tests** — unit/integration tests using IMPLEMENT_SIMPLE_AUTOMATION_TEST
  • **Functional tests** — actor-based AFunctionalTest in maps
  • **Logging** — UE_LOG, custom categories, verbosity filtering
  • **Assertions** — check, ensure, verify and when to use each
  • **Debug drawing** — DrawDebug helpers for runtime visualization
  • **Console commands** — UFUNCTION(Exec), FAutoConsoleCommand, CVars
  • **Profiling** — Unreal Insights, stat commands, SCOPE_CYCLE_COUNTER

---

Automation Framework

Automation tests live in a dedicated module (e.g., `MyGameTests`) that depends on `"AutomationController"`. Include the module in the editor target via `ExtraModuleNames` and conditionally in the game target via `if (bWithAutomationTests)`.

Simple Tests

// Source/MyGameTests/Private/MyFeature.spec.cpp
#include "Misc/AutomationTest.h"
// Must specify one application context flag AND exactly one filter flag
IMPLEMENT_SIMPLE_AUTOMATION_TEST(FMyInventoryTest, "MyGame.Inventory.AddItem",
    EAutomationTestFlags::EditorContext | EAutomationTestFlags::ProductFilter)

bool FMyInventoryTest::RunTest(const FString& Parameters)
{
    UInventoryComponent* Inv = NewObject<UInventoryComponent>();
    Inv->AddItem(FName("Sword"), 1);
    TestEqual(TEXT("Item count after add"), Inv->GetItemCount(FName("Sword")), 1);
    TestTrue(TEXT("Has sword"), Inv->HasItem(FName("Sword")));
    TestFalse(TEXT("No axe"),   Inv->HasItem(FName("Axe")));
    TestNotNull(TEXT("Inv valid"), Inv);
    return true;
}

Complex / Parameterized Tests

`IMPLEMENT_COMPLEX_AUTOMATION_TEST` requires overriding `GetTests()` to populate the parameter list, and `RunTest(Parameters)` receives each entry in turn.

IMPLEMENT_COMPLEX_AUTOMATION_TEST(FMyAssetLoadTest, "MyGame.Assets.LoadByPath",
    EAutomationTestFlags::EditorContext | EAutomationTestFlags::ProductFilter)

void FMyAssetLoadTest::GetTests(TArray<FString>& OutBeautifiedNames,
                                 TArray<FString>& OutTestCommands) const
{
    OutBeautifiedNames.Add(TEXT("Sword"));  OutTestCommands.Add(TEXT("/Game/Items/BP_Sword"));
    OutBeautifiedNames.Add(TEXT("Shield")); OutTestCommands.Add(TEXT("/Game/Items/BP_Shield"));
}

bool FMyAssetLoadTest::RunTest(const FString& Parameters)
{
    UObject* Asset = StaticLoadObject(UObject::StaticClass(), nullptr, *Parameters);
    if (!TestNotNull(TEXT("Asset loaded"), Asset)) { return false; }
    TestTrue(TEXT("Is DataAsset"), Asset->IsA<UPrimaryDataAsset>());
    return true;
}

Test Assertion Methods

// Equality — overloaded for int32, int64, float, double, FVector, FRotator,
//            FTransform, FColor, FLinearColor, FString, FStringView, FText, FName
TestEqual(TEXT("Label"), Actual, Expected);
TestEqual(TEXT("Float approx"), ActualF, ExpectedF, 0.001f);   // tolerance overload

// Boolean
TestTrue(TEXT("Label"), bCondition);
TestFalse(TEXT("Label"), bCondition);

// Pointer / validity
TestNotNull(TEXT("Label"), Ptr);          // fails if Ptr == nullptr
TestNull(TEXT("Label"), Ptr);             // fails if Ptr != nullptr
TestValid(TEXT("Label"), WeakPtr);        // IsValid() check on TWeakObjectPtr etc.

// Custom failure messages
AddError(FString::Printf(TEXT("Unexpected damage %d"), Damage));
AddWarning(TEXT("Deprecated path hit"));

// Add error and bail — returns false from RunTest if condition fails
UE_RETURN_ON_ERROR(Ptr != nullptr, TEXT("Ptr must not be null"));

Test Flags Reference

| Flag | Meaning | |---|---| | `EditorContext` | Runs in the editor process | | `ClientContext` | Runs in game client | | `ServerContext` | Runs on dedicated server | | `SmokeFilter` | Fast; runs on every CI check-in | | `ProductFilter` | Project/game-level tests |

---

Latent Commands (Async Testing)

Use latent commands when the test must wait for an async operation. `Update()` returns `true` when done, `false` to retry next frame.

DEFINE_LATENT_AUTOMATION_COMMAND_ONE_PARAMETER(FWaitSecondsCommand, float, Duration);
bool FWaitSecondsCommand::Update() { return GetCurrentRunTime() >= Duration; }

// Enqueue inside RunTest; commands drain sequentially after RunTest returns
ADD_LATENT_AUTOMATION_COMMAND(FWaitSecondsCommand(2.0f));

See `references/automation-test-patterns.md` for delegate-wait, timeout, and post-async assertion patterns.

---

Functional Tests

`AFunctionalTest` is a `UCLASS` actor placed in a test map. Override `StartTest()` and call `FinishTest()` when done.

// MyFunctionalTest.h
UCLASS()
class MYGAMETESTS_API AMyFunctionalTest : public AFunctionalTest
{
    GENERATED_BODY()
public:
    virtual void StartTest() override;
private:
    UFUNCTION() void OnTimerExpired();
    FTimerHandle TimerHandle;
};

// MyFunctionalTest.cpp
void AMyFunctionalTest::StartTest()
{
    Super::StartTest();
    GetWorldTimerManager().SetTimer(TimerHandle, this,
        &AMyFunctionalTest::OnTimerExpired, 1.0f, false);
}

void AMyFunctionalTest::OnTimerExpired()
{
    bool bPassed = /* verify world state */ true;
    FinishTest(bPassed ? EFunctionalTestResult::Succeeded
                       : EFunct
Read more
Ships withunreal-engine-skills

A collection of 27 AI agent skills for Unreal Engine C++ development. Built for game developers who want AI coding agents to help write correct, production-quality UE5 C++ code.

Get the whole plugin

Other skills on unreal-engine-skills.