Unreal Tests In Rider

[ ue4  tdd  ]
Written on January 26, 2023

Unreal Engine has some decent support for automated testing, and my IDE of choice, JetBrains Rider allows you to run the tests from the Unit Tests tab.

Unreal Engine is a bit of a beast, so turnaround time for iterating on code is somewhat long for an ideal TDD cycle, but it still might be an acceptable way to work on some core components.

Let’s take a look at some tests for this incredibly simple component (see here for accompanying source):

UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class UNREALAUTOMATEDTESTS_API USimpleComponent : public UActorComponent
{
	GENERATED_BODY()

public:
	bool bDidSomething = false;

	void DoSomething()
	{
	    bDidSomething = true;
	}
};

When starting out, I like to make sure that I can create a test with the test framework:

constexpr int32 Flags = EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter;

IMPLEMENT_SIMPLE_AUTOMATION_TEST(DummyTest, "Tests.DummyTest", Flags);
bool DummyTest::RunTest(const FString& Parameters)
{
	// Make the test pass by returning true, or fail by returning false.
	return true;
}

See the Unreal Engine documentation for a description of the IMPLEMENT_SIMPLE_AUTOMATION_TEST macro.

I put this code in a file under a Tests folder, named SimpleComponentTest.cpp.

ProjectStructure

When I bring up the Unit Tests tab in Rider (Alt+8), I see the tests I have defined.

UnitTestsTab

The tests can be run with the buttons on the left. The top one runs all the tests shown (the double Play button), the single Play button runs the selected test, and finally you can run the selected test under the debugger.

A slightly more useful test is shown here:

IMPLEMENT_SIMPLE_AUTOMATION_TEST(DoSomething, "Tests.DoSomething", Flags);
bool DoSomething::RunTest(const FString& Parameters)
{
	UWorld* World = FAutomationEditorCommonUtils::CreateNewMap();
	AActor* Actor = World->SpawnActor<AActor>();
	USimpleComponent* Comp = NewObject<USimpleComponent>(Actor);

	Comp->DoSomething();
	TestTrue("Did something", Comp->bDidSomething);

	return true;
}

This test creates a new world, spawns an actor into it and gives it an instance of our component.

I prefer always relying on the Test methods (TestTrue, TestEqual, and so on) rather than the return value of the RunTest function. The test will correctly be flagged as failing if any of them fail even if the final return value is true.

Running in the Unreal Editor

The tests can also be run from the Session Frontend in the Unreal Editor. This may or may not be more convenient - once I’m working with more complicated tests that may require setting up something in an Unreal level it is convenient to stay within the editor, and rely on the Live Coding feature to iterate on the code without having to restart the editor every time.

SessionFrontEndSessionFrontEnd

Note that if you add a test while using Live Coding, you have to press the Refresh Tests button in the session frontend to have it show up in the list of tests.

Spec tests

The Spec approach has some clear advantages over the simple automation test shown above - unfortunately, they do not work with Live Coding when running in the editor. Any change you make to a test, or adding new tests, do not show up in the editor after recompiling - you have to kill the editor and restart it. In my mind, this makes them not usable. On top of that, I always seem to get an error when running them in Rider - every other time, that is. Rerunning the test then succeeds in running the test. Nice as they are they simply don’t work with my workflow.

See also

The source for my test project for this is on GitHub: https://github.com/snorristurluson/UnrealAutomatedTests

Some blogs I’ve found on testing in Unreal:

  • https://blog.jetbrains.com/dotnet/2021/10/06/testing-with-rider-for-unreal-engine/
  • https://zuru.tech/blog/unit-testing-with-unreal-engine-4
  • https://benui.ca/unreal/unreal-testing-introduction/