UE4 C++ (21) 自动化系统(AutoTest)

  • Post author:
  • Post category:其他


06/05/2021



自动化系统

别名自动测试(AutoTest),由UE4提供的。首先看一下UE4的例子。打开Window->DeveloperTool->SessionFrontend->Automation。

自动测试

可以选择System->Engine->FileSystem 和Attachment选项,然后开始测试



创建自动的自动化


UE4官网



UE4官网技术指南

此系统存在于”UObject”生态系统之外,所以它对

蓝图

或引擎的

反射系统

不可见



简单测试

创建一个空的[Name]Test.cpp文件

//UE4官方例子
#include "Misc/AutomationTest.h"

IMPLEMENT_SIMPLE_AUTOMATION_TEST(FPlaceholderTest, "TestGroup.TestSubgroup.Placeholder Test", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter)
bool FPlaceholderTest::RunTest(const FString& Parameters)
{
    // 通过返回"真(true)"使测试通过,或者返回"假(false)"使测试失败。
    return true;
}

打开Session Frontend可以看到测试函数,因为

EAutomationTestFlags::EditorContext


Session Frontend

//在Console command 也可以运行自动化,按照下面写法
automation runtest TestGroup.TestSubgroup.Placeholder Test

下面列子存在Runtime\Engine\Private\Tests\EngineAutomationTests.cpp,和官网提供的一致

IMPLEMENT_SIMPLE_AUTOMATION_TEST(FSetResTest, "System.Windows.Set Resolution", EAutomationTestFlags::ClientContext | EAutomationTestFlags::EngineFilter)
bool FSetResTest::RunTest(const FString& Parameters)
{

	//Gets the default map that the game uses.
	const UGameMapsSettings* GameMapsSettings = GetDefault<UGameMapsSettings>();
	const FString& MapName = GameMapsSettings->GetGameDefaultMap();

	//Opens the actual default map in game.
	GEngine->Exec(GetSimpleEngineAutomationTestGameWorld(GetTestFlags()), *FString::Printf(TEXT("Open %s"), *MapName));

	//Gets the current resolution.
	int32 ResX = GSystemResolution.ResX;
	int32 ResY = GSystemResolution.ResY;
	FString RestoreResolutionString = FString::Printf(TEXT("setres %dx%d"), ResX, ResY);

	//Change the resolution and then restore it.
	ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(2.0f));
	ADD_LATENT_AUTOMATION_COMMAND(FExecStringLatentCommand(TEXT("setres 640x480")));
	ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(2.0f));
	ADD_LATENT_AUTOMATION_COMMAND(FExecStringLatentCommand(RestoreResolutionString));
	return true;
}



复杂测试

复杂测试可以用来测试多个重复的任务,相当于简单测试中有一个for-loop,GetTests需要获取每张地图的名字并加入到OutBeautifiedNames和OutTestCommands,然后每一张地图都会传给RunTests.

//加载所有地图并获取 性能报告 

IMPLEMENT_COMPLEX_AUTOMATION_TEST(FLoadAllMapsInGameTest, "Project.Maps.Load All In Game", EAutomationTestFlags::ClientContext | EAutomationTestFlags::PerfFilter)

/** 
 * Requests a enumeration of all maps to be loaded
 */
void FLoadAllMapsInGameTest::GetTests(TArray<FString>& OutBeautifiedNames, TArray <FString>& OutTestCommands) const
{
	TArray<FString> FileList;
#if WITH_EDITOR
	FEditorFileUtils::FindAllPackageFiles(FileList);
#else
	// Look directly on disk. Very slow!
	FPackageName::FindPackagesInDirectory(FileList, *FPaths::ProjectContentDir());
#endif

	// Iterate over all files, adding the ones with the map extension..
	for (int32 FileIndex = 0; FileIndex < FileList.Num(); FileIndex++)
	{
		const FString& Filename = FileList[FileIndex];

		// Disregard filenames that don't have the map extension if we're in MAPSONLY mode.
		if (FPaths::GetExtension(Filename, true) == FPackageName::GetMapPackageExtension())
		{
			if (FAutomationTestFramework::Get().ShouldTestContent(Filename))
			{
				OutBeautifiedNames.Add(FPaths::GetBaseFilename(Filename));
				OutTestCommands.Add(Filename);
			}
		}
	}

	//也可以使用AssetRegistry 模块代码获取地图类信息
}

UWorld* GetSimpleEngineAutomationTestGameWorld(const int32 TestFlags)
	{
		// Accessing the game world is only valid for game-only 
		check((TestFlags & EAutomationTestFlags::ApplicationContextMask) == EAutomationTestFlags::ClientContext);
		check(GEngine->GetWorldContexts().Num() == 1);
		check(GEngine->GetWorldContexts()[0].WorldType == EWorldType::Game);

		return GEngine->GetWorldContexts()[0].World();
	}



bool FLoadAllMapsInGameTest::RunTest(const FString& Parameters)
{
	FString MapName = Parameters;

	//Open the map
	GEngine->Exec(GetSimpleEngineAutomationTestGameWorld(GetTestFlags()), *FString::Printf(TEXT("Open %s"), *MapName));

	//if( FAutomationTestFramework::Get().IsScreenshotAllowed() )
	{
		//Generate the screen shot name and path
		FString ScreenshotFileName;
		const FString LoadAllMapsTestName = FString::Printf(TEXT("LoadAllMaps_Game/%s"), *FPaths::GetBaseFilename(MapName));
		ScreenshotFileName = AutomationCommon::GetLocalPathForScreenshot(AutomationCommon::GetScreenshotName(LoadAllMapsTestName));

		//Give the map some time to load
		ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(1.5f));
		//Take the screen shot
		ADD_LATENT_AUTOMATION_COMMAND(FTakeViewportScreenshotCommand(ScreenshotFileName));
		//Give the screen shot a chance to capture the scene
		ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(0.5f));
	}

	//Kick off any Automation matinees that are in this map
	ADD_LATENT_AUTOMATION_COMMAND(FEnqueuePerformanceCaptureCommands());

	return true;
}



ADD_LATENT_AUTOMATION_COMMAND 潜在指令

潜在指令用于辅助Runtests,让指令不在一帧完成,而是可以分为好几帧完成,需要通过DEFINE_LATENT_AUTOMATION_COMMAND声明,才能使用



执行命令

不光可以从Editor启动,也可以从命令控制台启动或者命令行启动



TestWorld.exe -execcmds="Automation runtests Project.Maps.Load All In Game;Quit"  //启动并完成后退出游戏

-execcmds="automation list;runtests [....]"			//查看定义过的Autotest,并执行某个
-execcmds="automation list;runall"					查看定义过的Autotest,并执行所有



其他潜在命令

ADD_LATENT_AUTOMATION_COMMAND(FExecStringLatentCommand(TEXT("stat game")));

//StartFPSChart
ADD_LATENT_AUTOMATION_COMMAND(FExecWorldStringLatentCommand(TEXT("StartFPSChart")));
ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(10.0f));
ADD_LATENT_AUTOMATION_COMMAND(FExecWorldStringLatentCommand(TEXT("StopFPSChart")));

//Start memory report



其他辅助命令

// NOTE: In the absence of "-ddc=noshared", a VPN connection can cause UE4 to take a long time to startup
// NOTE: Without '-CrashForUAT'/'-unattended' the auto-reporter can pop up
// NOTE: Without '-UseAutoReporter' the crash report executable is launched

-stdout -FullStdOutLogOutput -ddc=noshared -unattended -CrashForUAT -UseAutoReporter -NUTServer

-unattended: 设置为无人管理的状态。禁用需要从用户获得反馈的任何东西。
-crashreports 总是显示崩溃信息

-logcmds="logonline verbose,LogAutomationCommandLine verbose/display/log"


命令行参数



版权声明:本文为weixin_44200074原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。