2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

UE5 自動化テストコードを書いてみるメモ

2
Posted at

概要

UnrealEngine5 にて AutomationTestを書いたメモです。
テストケースとしてナイアガラアセットのナイアガラパラメータの有無をテストしてみました。

更新履歴

日付 内容
2026/11/11 初版

参考

以下を参考にさせて頂きました、ありがとうございます。
UE公式:自動化テクニカルガイド
UE5.8 AIエージェント向けToolset 全まとめ
UE5のC++に自動テストを入れた記録:モジュールを分けない最小構成
UE5のテストコード入門:CQTest・Automation Spec・Functional Testを実務で使い分ける
【UE5】自動テストツールを使ってみよう!

環境

Windows11
Visual Studio 2022
UnrealEngine 5.8

AutomationTestとは

UEにはいくつかテスト機能があり、そのうちの1つです。
シンプルテスト(単体)とコンプレックステスト(複合)があり、エディタから任意に実行したり、コンソールコマンドから実行したりできます。

シンプルテスト

テストコードを用意する

テスト用のコードは .cppファイルのみで置き場所は Build.cs直下の Private\Testsフォルダ以下が推奨されているようです。

ナイアガラのパラメータと型を調べるテストを書いてみます。
#if WITH_DEV_AUTOMATION_TESTSで囲うことと、IMPLEMENT_SIMPLE_AUTOMATION_TESTのマクロの定義が必要で、このマクロの第2引き数がテスト名になるようです。
またC++でのナイアガラ関数を使うため Build.cs の PrivateDependencyModuleNamesに Niagaraの追加が必要になります。

NiagaraParamSimpleTest.cpp
#if WITH_DEV_AUTOMATION_TESTS

#include "Misc/AutomationTest.h"
#include "NiagaraSystem.h"
#include "NiagaraTypes.h"
#include "NiagaraUserRedirectionParameterStore.h"

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FNiagaraParameterValidationTest,
	"Game.Niagara.ParameterValidation",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::ProductFilter
)

// ナイアガラアセットのパラメータの存在と型を調べるテスト
bool FNiagaraParameterValidationTest::RunTest(const FString& Parameters)
{
	// ナイアガラシステムをロード
	const UNiagaraSystem* _System = LoadObject<UNiagaraSystem>(
		nullptr,
		TEXT("/Game/Effect/NS_Sample00.NS_Sample00")
	);

	if (!TestNotNull(TEXT("Niagara System"), _System))
	{
		return(false);
	}

	// 想定しているナイアガラパラメータ名を定義
	const TArray<FNiagaraVariable> _ExpectedVariables =
	{
		{
			FNiagaraTypeDefinition::GetFloatDef(),
			TEXT("User.Length")
		},
		{
			FNiagaraTypeDefinition::GetFloatDef(),
			TEXT("User.LifeTime")
		},
		{
			FNiagaraTypeDefinition::GetVec3Def(),
			TEXT("User.Velocity")
		}
	};

	// ナイアガラアセットが公開するパラメータを取得
	TArray<FNiagaraVariable> ActualVariables;
	_System->GetExposedParameters().GetUserParameters(ActualVariables);

	// 名前と型を検証
	for (const FNiagaraVariable& _Expected : _ExpectedVariables)
	{
		const bool _bFound = ActualVariables.ContainsByPredicate(
			[&_Expected](const FNiagaraVariable& Actual)
			{
				return( Actual.GetName() == _Expected.GetName()
					&& Actual.GetType() == _Expected.GetType() );
			}
		);

		TestTrue( FString::Printf(TEXT("Parameter: %s"), *_Expected.GetName().ToString()), _bFound);
	}

	return(true);
}

#endif

RunTest() でテストするコードを実行し、TestEqual()、TestTrue()、TestFalse()、TestNotNull() といったメソッドでエラーの記録を行います。

テストを実行する

コンソールコマンドで実行するか、UEエディタから実行できます。

コンソールコマンド例
Automation RunTests Game.Niagara.ParameterValidation

ツール -> セッションフロントエンド の [オートメーション]タブにあるリストからチェックボックスにテストしたい項目を選んで実行を押下するとテストが走ります。

Example00.png

テストに成功すると以下のようなログが出力されます。
エラーの場合はエラーの項目と一緒にエラーログが表示されます。

▼エラーなし
Example01.png

▼エラーあり
Example03.png

コンプレックステスト

テストコードを用意する

複数テストをまとめるためにテスト対象の定義を用意し、アセット毎にテストケースが取得できるように GetTests() を用意します。またマクロ名が IMPLEMENT_COMPLEX_AUTOMATION_TEST に代わっています。

NiagaraParamComplexTest.cpp
#if WITH_DEV_AUTOMATION_TESTS

#include "Misc/AutomationTest.h"
#include "NiagaraSystem.h"
#include "NiagaraTypes.h"
#include "NiagaraUserRedirectionParameterStore.h"
#include "Misc/PackageName.h"

namespace NiagaraParameterTests
{
	struct FTestCase
	{
		FString AssetPath;
		TArray<FNiagaraVariable> ExpectedParameters;
	};

	// テストするアセットとパラメータの定義
	static const TArray<FTestCase>& GetCases()
	{
		static const TArray<FTestCase> Cases =
		{
			{
				TEXT("/Game/Effect/NS_Sample00.NS_Sample00"),
				{
					{ FNiagaraTypeDefinition::GetFloatDef(), TEXT("User.Length") },
					{ FNiagaraTypeDefinition::GetFloatDef(), TEXT("User.ScaleX") }
				}
			},
			{
				TEXT("/Game/Effect/NS_Sample00.NS_Sample01"),
				{
					{ FNiagaraTypeDefinition::GetFloatDef(), TEXT("User.Length") },
					{ FNiagaraTypeDefinition::GetVec3Def(), TEXT("User.Velocity") }
				}
			},
			{
				TEXT("/Game/Effect/NS_Sample00.NS_Sample02"),
				{
					{ FNiagaraTypeDefinition::GetFloatDef(), TEXT("User.Distance") }
				}
			}
		};

		return(Cases);
	}
}

IMPLEMENT_COMPLEX_AUTOMATION_TEST(
	FNiagaraParameterValidationTest2,
	"Game.Niagara.ParameterValidation2",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::ProductFilter
)

// 各アセットに対応するテストケースを登録
void FNiagaraParameterValidationTest2::GetTests(
	TArray<FString>& OutBeautifiedNames,
	TArray<FString>& OutTestCommands) const
{
	for (const auto& TestCase : NiagaraParameterTests::GetCases())
	{
		// アセットパスを一意なテストIDとして使う
		OutTestCommands.Add(TestCase.AssetPath);

		// UIに表示する名前
		OutBeautifiedNames.Add(FPackageName::GetShortName(TestCase.AssetPath));
	}
}

// アセットごとに実行される
bool FNiagaraParameterValidationTest2::RunTest(
	const FString& Parameters)
{
	const auto& TestCases = NiagaraParameterTests::GetCases();

	const auto* _TestCase = TestCases.FindByPredicate(
		[&Parameters](const auto& Case)
		{
			return( Case.AssetPath == Parameters );
		}
	);

	// テストするパラメータが存在するか
	if (!_TestCase)
	{
		AddError(FString::Printf(TEXT("Unknown test case: %s"), *Parameters));

		return(false);
	}

	// ナイアガラシステムのロード
	UNiagaraSystem* _System = LoadObject<UNiagaraSystem>(nullptr, *_TestCase->AssetPath);
	if (!TestNotNull(TEXT("Niagara System"), _System))
	{
		return(false);
	}

	// ナイアガラパラメータの取得
	TArray<FNiagaraVariable> _ActualParameters;
	_System->GetExposedParameters().GetUserParameters(_ActualParameters);

	// 名前と型を検証
	for (const FNiagaraVariable& _Expected : _TestCase->ExpectedParameters)
	{
		const FNiagaraVariable* _Actual =
			_ActualParameters.FindByPredicate(
				[&_Expected](const FNiagaraVariable& Variable)
				{
					return Variable.GetName() == _Expected.GetName();
				}
			);

		if (!_Actual)
		{
			AddError(FString::Printf(
				TEXT("[%s] Missing parameter: %s"),
				*_TestCase->AssetPath,
				*_Expected.GetName().ToString()
			));

			continue;
		}

		if (_Actual->GetType() != _Expected.GetType())
		{
			AddError(FString::Printf(
				TEXT("[%s] Type mismatch: %s"),
				*_TestCase->AssetPath,
				*_Expected.GetName().ToString()
			));
		}
	}

	return( true );
}

#endif

テストを実行する

シンプルテストと同様にセッションフロントエンドのオートメーションテストかコンソールコマンドで実行ができます。
コンプレックステストでは定義した複数のテストがツリー上で表示されるので個別でのテストも可能です。

Example03.png

テストしたい項目を選択して実行すると結果が返ってきます。

その他

ナイアガラパラメータをランタイム時にチェックする場合

アクターの動作やアビリティなどで使用しているナイアガラがあってそのパラメータが正しいことを調べる場合、実際にナイアガラアセットをロードする時に以下のようなコードで調べる方法が考えられます。

ランタイムでのナイアガラパラメータチェック例
bool IsValidNiagaraUserParameter(
	const UNiagaraSystem* _NiagaraSystem,			// ナイアガラシステム
	const FName _ParamName,							// パラメータ名
	const FNiagaraTypeDefinition& _ExpectedType		// パラメータの型
	)
{
	if (!IsValid(_NiagaraSystem)){
		return false;
	}

	const auto& _Store = _NiagaraSystem->GetExposedParameters();
	const FNiagaraVariable _ExpectedVariable(_ExpectedType, _ParamName);

	// 型を含めたパラメータの照合
	const bool _Ret = _Store.FindParameterVariable(_ExpectedVariable, false) != nullptr;

	return(_Ret);
}

これでもチェックは可能ですが、実際にアプリを起動して対応している機能を使わないとなりませんので、オートメーションテストよりは手間がかかると思います。

まとめ

実行部分にエラーチェックは入れてもしばらく気が付かないケースもあるためオートメーションテストが有用なのは間違いないのですが、テスト自体を書くこととそれを保守することが実際運用時の課題になるかと思います。
また、UE5.8の実験的機能で、AutomationTestToolset というToolsets が提供されており、自動テスト実行がAIにて実行ができるらしいのでエラー結果を受け取って検証をするという使い方もできるのかもしれません(未検証)。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?