The Low-Level Tests (LLTs) framework recognizes two different types of tests:
- Explicit: Self-contained tests defined by a module build-target pair.
- Implicit: Tests that live inside the tested module and do not require a build-target pair.
Explicit Tests
Explicit Tests are self-contained tests defined by a module build-target pair. Explicit tests are designed to be lightweight in terms of compilation time and run time. They are called explicit because they require explicit UE module build and target files, as opposed to implicit tests, which do not require them. This means explicit tests require both a .Build.cs
and a .Target.cs
file while implicit tests do not. For more information about the distinction between explicit and implicit tests, see the Implicit Tests section.
Create an Explicit Test
Follow these steps to create your explicit test:
-
In the
Source/Programs
directory, create a new directory with the same name as the module you want to test and add the.Build.cs
file in this directory.To see an example, the directory
Engine/Source/Programs/LowLevelTests
contains an explicit test target named Foundation Tests. - Inherit your module class from
TestModuleRules
.- If you are writing a test for a plugin, place the new module inside a
Tests
directory at the same level as the plugin'sSource
directory. - If you are building a test module that does not use Catch2, inherit the base constructor with the second parameter set to false:
base(Target, false)
.
- If you are writing a test for a plugin, place the new module inside a
- Call
UpdateBuildGraphPropertiesFile
with a newMetadata
object argument.- This information is used to generate BuildGraph script test metadata.
- For more information about BuildGraph script generation, see the Generate BuildGraph Script Metadata section.
-
Suppose that you have an explicit test module titled
UEModuleTests
. Your explicit test.Build.cs
file should look similar to this:UEModuleTests/UEModuleTests.Build.cs
public class UEModuleTests : TestModuleRules { public UEModuleTests(ReadOnlyTargetRules Target) : base(Target) { PrivateIncludePaths.AddRange( // Any private include paths ); PrivateDependencyModuleNames.AddRange( // Any private dependencies to link against ); // Other types of dependencies or module specific logic UpdateBuildGraphPropertiesFile(new Metadata("UEModule", "UE Module")); } }
- Add a test target file (
.Target.cs
) with a class that inherits fromTestTargetRules
. - Override the default compilation flags if necessary.
- Aim for a minimal, testable module free of default features that don't add value to low-level testing.
- You can specify the supported platforms individually. The default platforms are: Win64, Mac, Linux, and Android.
- You can enable project-specific global definitions and set Catch2 definitions, such as those needed for benchmarking support.
-
Your explicit tests
.Target.cs
file should look similar to this:UEModuleTests/UEModuleTests.Target.cs
[SupportedPlatforms(UnrealPlatformClass.All)] public class UEModuleTestsTarget : TestTargetRules { public UEModuleTestsTarget(TargetInfo Target) : base(Target) { // Setup like any other target: set compilation flags, global definitions etc. GlobalDefinitions.Add("CATCH_CONFIG_ENABLE_BENCHMARKING=1"); } }
Next Steps
Now you can write C++ test files in the Private
folder of the module and write Catch2 tests in these files. For testing tips and best practices, see the Write Low-Level Tests documentation. Lastly, learn how to build and run your tests. There is more than one way to build and execute low-level tests. See the Build and Run Low-Level Tests documentation to select the best method for your development needs.
Generate BuildGraph Script Metadata Files
If you want to build and run your tests with BuildGraph, you need to enable generation of BuildGraph script metadata files for explicit tests. When generating the IDE solution via GenerateProjectFiles.bat
, the explicit test modules generate BuildGraph .xml
files.
An engine configuration setting conditions this generation. You can set this configuration in Engine/Config/BaseEngine.ini
:
[LowLevelTestsSettings]
bUpdateBuildGraphPropertiesFile=true
When you run GenerateProjectFiles.bat
, test metadata .xml
files are generated in the Build/LowLevelTests/<TEST_NAME>.xml
folder for each test target, where <TEST_NAME>
is the name of your test target. For NDA platforms, these files are generated under Platforms/<PLATFORM_NAME>/Build/LowLevelTests/<TEST_NAME>.xml
. An additional General.xml
file is optionally present next to the test files containing global properties.
If the files already exist, they are updated according to the C#-described Metadata
object. The folders and files that are accessed by project file generation must be writable. Typically, these files are read-only when under source control, so check them out or make them writeable before generation.
To see an example, the directory Engine/Build/LowLevelTests
contains an .xml
file named Foundation. This is the generated BuildGraph metadata for the Foundation Tests.
Explicit Tests Reference
Test Module Rules Reference
The TestModuleRules
class extends ModuleRules
with UpdateBuildGraphPropertiesFile
. UpdateBuildGraphPropertiesFile
accepts a Metadata
object which generates BuildGraph test metadata .xml
files. With a Metadata
object, you can set the following properties:
Field | Description |
---|---|
TestName |
The name of your tests used by the BuildGraph script to generate test-specific properties. This field cannot contain spaces. |
TestShortName |
The short name of your tests used for display in the build system. This field can contain spaces. |
ReportType |
The Catch2 report type. The most common report types are console and xml. For more information about Catch2 report types, see the external Catch2 documentation. |
Disabled |
Whether the test is disabled. If true, this test is excluded from the BuildGraph graph. |
InitialExtraArgs |
Command-line arguments that are prepended in front of other arguments for the RunLowLevelTests Gauntlet command. These are typically Gauntlet feature-enabling arguments that only apply to some tests. For example, -printreport , which prints the report to stdout at the end of test execution. |
HasAfterSteps |
If true, tests must provide a BuildGraph Macro with the name <TEST_NAME>AfterSteps that include any cleanup or steps necessary to run after the test execution. For example, this could be running a database script that cleans up any leftover test data. |
UsesCatch2 |
This property allows you to choose your test framework. Some tests don't use Catch2; they might use GoogleTest for example. If you choose your own test framework, ensure that you implement support for reporting and other features in the RunLowLevelTests Gauntlet command. |
PlatformTags |
Platform-specific list of tags. For example, use this to exclude unsupported tests on a given platform. |
PlatformCompilationExtraArgs |
Any extra compilation arguments that a platform might require. |
PlatformsRunUnsupported |
Add an exception and can serve as a compilation safety net in the BuildGraph script until running support is implemented. For example, if a platform only supports compilation but lacks low-level test running capabilities. |
TestModuleRules
overrides many default UBT flags from its base class ModuleRules
. This reduces compilation bloat and minimizes compilation times for most tests out of the box. You can always override these defaults in your TestModuleRules
derived class, but they should not be changed in TestModuleRules
directly.
Test Target Rules Reference
The TestTargetRules
class extends TargetRules
with the following:
Flag | Description |
---|---|
bUsePlatformFileStub |
This causes the platform-dependent FPlatformFile runtime instance to be replaced with a mock that disables IO operations. Use this to disable asset loading when testing against the engine module. Setting this property changes the value of |
bMockEngineDefaults |
When testing with the engine module, certain resources are managed by default or loaded from asset files. These operations require cooking assets. Use this for tests that don't need to load assets; the effect is to mock engine default materials, world objects, and other resources. Setting this property changes the value of |
bNeverCompileAgainstEngine |
The default behavior of the LLT Framework is to automatically set bCompileAgainstEngine = true whenever the engine module is in the build dependency graph. This property can stop this behavior such that we're not compiling with the engine even if the engine module is in the graph. |
bNeverCompileAgainstCoreUObject |
Same as bNeverCompileAgainstEngine , but for CoreUObject . |
bNeverCompileAgainstApplicationCore |
Same as bNeverCompileAgainstEngine , but for ApplicationCore . |
bNeverCompileAgainstEditor |
Same as bNeverCompileAgainstEngine , but for UnrealEd . |
bWithLowLevelTestsOverride |
Set this to include implicit tests from dependent modules. It forces the WITH_LOW_LEVEL_TESTS macro to be true , which is normally reserved for implicit tests. |
Just like TestModuleRules
, TestTargetRules
sets default UBT flags. Notably it disables UE features such as UObjects, localizations, stats, and others.
Engine tests
In this type of explicit test, the LLT framework compiles and runs explicit tests that include the engine module. Because loading assets requires cooking for most platforms, the engine module cannot be used, so engine tests only work with the following flags set in the .Target.cs
file:
public UEModuleTestsTarget(TargetInfo Target) : base(Target)
{
bUsePlatformFileStub = true;
bMockEngineDefaults = true;
}
Implicit Tests
Implicit Tests reside in the same module that you want to test. All implicit tests are conditionally compiled through the WITH_LOW_LEVEL_TESTS
definition. While they can be placed anywhere in the module, for example, in the Private folder, it can be hard to distinguish them from module source code. To ensure that your tests are discoverable, follow these conventions:
- Create a Tests folder in your module at the same level as the Public and Private folders.
- Mirror the module's folder structure inside Tests whenever there's a matching test for a source file.
Because there isn't an explicit target like explicit tests require, these tests need an existing target to be built with. This requires implicit tests to use Unreal Build Tool to produce test executables for implicit tests. For more information, see the Build Implicit Tests section of the Build and Run Low-Level Tests documentation.
Directory Structure
Consider the following example with a module called SampleModule and the following directory structure:
.
└── SampleModule/
├── Public/
│ └── SampleCode.h
└── Private/
├── SampleCode.cpp
└── SampleModuleSubDirectory/
├── MoreSampleCode.h
└── MoreSampleCode.cpp
To add implicit tests to this module, create a directory titled Tests at the same level as the Public and Private directories and mirror the directory structure of the Private directory. For each C++ file, create a corresponding test file in the same relative location. The resulting structure looks like this:
.
└── SampleModule/
├── Public/
│ └── SampleCode.h
├── Private/
│ ├── SampleCode.cpp
│ └── SampleModuleSubDirectory/
│ ├── MoreSampleCode.h
│ └── MoreSampleCode.cpp
└── Tests/
├── SampleCodeTests.cpp
└── SampleModuleSubDirectory/
└── MoreSampleCodeTests.cpp
With this structure, the file SampleCodeTests.cpp
contains tests for the SampleCode.cpp
file, and MoreSampleCodeTests.cpp
contains tests for the MoreSampleCode.cpp
file.
Next Step
Once you have decided which test is right for your needs, see the Write Low-Level Tests documentation to learn how to write Low-Level Tests in Unreal Engine.