Hey so recently our project has grown to the point where I need to rely on automation tests to make sure that I do not break assets while working in parts of the game for the most part AI behaviour trees. As such I have implemented some Automation Tests for some of the core tasks for our ai, such as spawning in a world, some units suffering damage, and a single unit with the healing ability to test how he responds etc. I can easily perform situational testing then, debugging blueprints etc. and its fantastic. However after running a automation test the ability to save any assets does not work, neither the Ctrl+s shortcut nor the in editor save button. I am using the perforce plugin for my project, and my tests use the following to queue up the test environments
IMPLEMENT_COMPLEX_AUTOMATION_TEST(FHealingTest, "MyGame.HealingTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::ProductFilter )
DEFINE_LATENT_AUTOMATION_COMMAND( FCreateWorld );
DEFINE_LATENT_AUTOMATION_COMMAND( FSpawnHexLayout );
DEFINE_LATENT_AUTOMATION_COMMAND( FWaitForInitialResourceSpawn );
DEFINE_LATENT_AUTOMATION_COMMAND( FCreateBasicCamp);
DEFINE_LATENT_AUTOMATION_COMMAND( FCleanupWorkers );
DEFINE_LATENT_AUTOMATION_COMMAND_ONE_PARAMETER( FExecStringCommand, FString, ExecCommand );
DEFINE_LATENT_AUTOMATION_COMMAND_ONE_PARAMETER( FAssignWorkerStates, FString, ExecCommand );
DEFINE_LATENT_AUTOMATION_COMMAND_ONE_PARAMETER( FCheckForPassFail, FString, ExecCommand );
UWorld* g_world = nullptr;
AMyGameState* g_game_state = nullptr;
AMyGameMode* g_game_mode = nullptr;
void
FHealingTest::GetTests( TArray<FString>& OutBeautifiedNames, TArray<FString>& OutTestCommands ) const
{
OutBeautifiedNames.Add( FString( "Healing Sick" ) );
OutBeautifiedNames.Add( FString( "Healing Low Health" ) );
OutBeautifiedNames.Add( FString( "Healing Diseased" ) );
OutBeautifiedNames.Add( FString( "Cleansing Dead" ) );
OutTestCommands.Add( FString( "Sick" ) );
OutTestCommands.Add( FString( "Low" ) );
OutTestCommands.Add( FString( "Disease" ) );
OutTestCommands.Add( FString( "Cleanse" ) );
}
bool
FHealingTest::RunTest( const FString& Param )
{
SetSuppressLogs( true );
ADD_LATENT_AUTOMATION_COMMAND( FCreateWorld() );
ADD_LATENT_AUTOMATION_COMMAND( FSpawnHexLayout() );
ADD_LATENT_AUTOMATION_COMMAND( FWaitForInitialResourceSpawn() );
SetSuppressLogs( false );
ADD_LATENT_AUTOMATION_COMMAND( FCreateBasicCamp() );
ADD_LATENT_AUTOMATION_COMMAND( FAssignWorkerStates( Param ) );
ADD_LATENT_AUTOMATION_COMMAND( FWaitLatentCommand( 360.0f ) );
ADD_LATENT_AUTOMATION_COMMAND( FCheckForPassFail( Param ) );
ADD_LATENT_AUTOMATION_COMMAND( FCleanupWorkers );
ADD_LATENT_AUTOMATION_COMMAND( FExecStringCommand( TEXT( "quit" ) ) );
return true;
}
bool
FCreateWorld::Update()
{
AutomationOpenMap( TEXT( "Procedural/BaseMap" ) );
if ( GEngine == nullptr )
{
UE_LOG( LogEngineAutomationTests, Log, TEXT( "GEngine pointer is null" ) );
return false;
}
const TIndirectArray<FWorldContext>& WorldContexts = GEngine->GetWorldContexts();
for ( const FWorldContext& Context : WorldContexts )
{
if ( ( ( Context.WorldType == EWorldType::PIE ) || ( Context.WorldType == EWorldType::Game ) ) && ( Context.World() != NULL ) )
{
g_world = Context.World();
break;
}
}
if ( g_world == nullptr )
{
UE_LOG( LogEngineAutomationTests, Log, TEXT( "Cannot find a valid Game World." ) );
return false;
}
g_game_state = Cast<AMyGameState>( g_world->GetGameState() );
if ( g_game_state == nullptr )
{
UE_LOG( LogEngineAutomationTests, Log, TEXT( "Incorrect game state loaded" ) );
return false;
}
g_game_mode = Cast<AMyGameMode>( g_world->GetAuthGameMode() );
if ( g_game_mode == nullptr )
{
UE_LOG( LogEngineAutomationTests, Log, TEXT( "Incorrect game mode loaded" ) );
return false;
}
return true;
}
For the most part the most complex thing I do is use the AutomationOpenMap() to open a map which launches a Standalone Editor window, then I use the GEngine world contexts to spawn some units in as I would normally. Atm I don’t SetSuccess on the tests (I really should but I’m currently not) and I will quite often stop tests midway manually once I identify a problem I need to resolve. Anyway I currently have to restart the editor apply a fix and retest, would love to know if theres anything I can do to remove the ‘restart the editor’ step from my bug fixing loop.
Thanks ahead of time.