Engine C++ tests: running and diagnosing
tests=yes builds, doctest filters, regression cases and separation from project tests.
Engine C++ tests
This guide covers engine source tests, not C# game tests. The built-in runner uses doctest and a separate entry point. Run project tests and exported-game checks separately.
Prepare a build
You need the source tree, a C++ toolchain and SCons. Work from the Source root containing SConstruct and tests/data. A normal installed editor may lack tests. C# support does not enable them.
Example for Windows x64; toolchain preparation is covered in Windows builds:
scons platform=windows target=editor arch=x86_64 tests=yes
./bin/reckfell.windows.editor.x86_64.console.exe --test --helpThe filename depends on build options: use the binary actually produced. tests defaults to off. dev_mode=yes enables it alongside additional strict checks, but an explicit tests=no can override this. Do not enable all of dev_mode just for one test. A disable_2d=yes profile disables tests; keep the ordinary editor configuration for this workflow.
With tests available, --test --help lists doctest options. A binary without support returns a nonzero exit code and compiled without support for unit tests. That is a refused launch, not a successful run containing zero tests.
Run a selected regression
List names first, then run the selected cases:
./bin/reckfell.windows.editor.x86_64.console.exe --test --list-test-cases --test-case="*[Color]*"
./bin/reckfell.windows.editor.x86_64.console.exe --test --test-case="*[Color]*"
./bin/reckfell.windows.editor.x86_64.console.exe --test --source-file="*test_color.cpp" --successQuote filter patterns so the shell does not expand *. [Color] markers are part of case names, not a separate tag field. --success adds passing assertions to output and is usually only useful while diagnosing a problem. Confirm that the filter selected tests: exit code 0 with an empty selection does not prove the feature was checked.
For an XML report:
./bin/reckfell.windows.editor.x86_64.console.exe --test --test-case="*[Color]*" --reporters=xml --out=color-tests.xml
if ($LASTEXITCODE -ne 0) { throw "C++ tests failed" }Retain the report with build options and binary identity. A selected group passing does not prove the entire suite, export template or another platform passes. Use --test without filters to run the available suite. Skipped cases can be enabled separately with --no-skip; do not add that flag unnecessarily.
Add a check
Create, for example, tests/core/math/test_color_clamp_regression.cpp. This is a new engine source file, not a game-project file. The TEST_FORCE_LINK name must match the filename without .cpp and be unique:
#include "tests/test_macros.h"
#include "core/math/color.h"
TEST_FORCE_LINK(test_color_clamp_regression)
namespace TestColorClampRegression {
TEST_CASE("[ColorClampRegression] Clamp all RGBA channels") {
const Color input(2.0f, -1.0f, 0.5f, 2.0f);
const Color result = input.clamp();
CHECK(result.is_equal_approx(Color(1.0f, 0.0f, 0.5f, 1.0f)));
CHECK(input.is_equal_approx(Color(2.0f, -1.0f, 0.5f, 2.0f)));
}
} // namespace TestColorClampRegressionThis checks clamping of every RGBA channel and preservation of the input value. Rebuild your test editor and select *[ColorClampRegression]*. The example was reviewed against current C++ source; a separate engine build containing this new file was not performed here.
tests/SCsub gathers nested .cpp files and generates references to their TEST_FORCE_LINK symbols. Module tests use separate registration: see C++ modules. Do not create another file with the same force-link name.
Write useful assertions
| Macro | Use |
|---|---|
REQUIRE | A prerequisite for continuing the current case, such as successful object creation. Failure aborts the current case. |
CHECK | A result check. Failure allows later assertions to continue but makes the run unsuccessful. |
WARN | Warning only. Do not use it instead of checking required behavior. |
SUBCASE | An alternative branch sharing setup. The test body runs again for each branch. |
Check the normal result, a boundary and reproduction of the fixed error. Use suitable approximate comparisons for floats. Reproduce the error before applying the fix: a test that also passes with the old behavior may miss the regression.
Cases requiring an Entity tree or editor use special names [EntityTree] and [Editor]; [Audio] creates an audio server with a dummy driver. This is current runner behavior, not universal doctest attributes. Inspect tests/test_main.cpp for the exact environment; a mock window or audio driver does not validate a real GPU or output device.
Diagnose a failed launch
- No test support: you launched an ordinary editor or built without
tests=yes. Check the actual binary path. - Test data not found: the working directory lacks
tests/data. Run from the Source root; some data is also located relative tobin. - Zero tests found: check case names, filters, rebuilding and unique
TEST_FORCE_LINKregistration. - Failed assertion: retain the exit code, exact assertion and build options. Do not change
CHECKtoWARNjust to make the result green. - Expected errors clutter logs: temporary
ERR_PRINT_OFF/ERR_PRINT_ONchanges global output. Restore it before any possible early return; aREQUIREfailure inside the muted section can bypass restoration.
The runner uses a reckfell_test directory in the system cache and clears its contents at startup. Do not store your own data there. It is not the project working directory.