UE4 lambdaを使って自動テストを楽に書く
UE4は開発環境としてテストをサポートしており、別途ツールを使わなくても自動テストが書けるようになっています。
またLatent コマンドを使うことで、複数フレームにまたがるテストも記述できこれはかなり便利です。
ただ複数のLatentコマンドを使って遅延評価させようと思うと、 やりたい評価の種別だけDEFINE_LATENT_AUTOMATION_COMMAND マクロを定義しなくてはいかず面倒だなあとずっと思っていました。
たとえば以下のような感じ。
DEFINE_LATENT_AUTOMATION_COMMAND_TWO_PARAMETER(FHogeObjCommand, FAutomationTestBase*, Test, UMyObject*, Obj); bool FHogeObjCommand::Update() { check(Test); check(Obj); Test->TestEqual(TEXT("check"), Obj->Property, 1); return true; } DEFINE_LATENT_AUTOMATION_COMMAND_TWO_PARAMETER(FHogeObjCommand2, FAutomationTestBase*, Test, UMyObject*, Obj); bool FHogeObjCommand2::Update() { check(Test); check(Obj); Obj->Hoge(); return true; } IMPLEMENT_SIMPLE_AUTOMATION_TEST(FHogeTest, "Hoge.HogeTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter) bool FHogeTest::RunTest(const FString& Parameters) { auto obj = NewObject<UMyObject>(); ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(1.0f)); ADD_LATENT_AUTOMATION_COMMAND(FHogeObjCommand(this, obj)); ADD_LATENT_AUTOMATION_COMMAND(FHogeObjCommand2(this, obj)); ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(1.0f)); ADD_LATENT_AUTOMATION_COMMAND(FHogeObjCommand(this, obj)); }
なので、毎回複数定義するのは疲れるため以下のようなLatentコマンドを定義したところ、ほぼこれでいけるようになりました。
DEFINE_LATENT_AUTOMATION_COMMAND_ONE_PARAMETER(FLambdaCommand, TFunction<void()>, InWork); bool FLambdaCommand::Update() { InWork(); return true; }
このLatentコマンドをつかって先ほどのテストを書くと
IMPLEMENT_SIMPLE_AUTOMATION_TEST(FHogeTest, "Hoge.HogeTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter) bool FHogeTest::RunTest(const FString& Parameters) { auto obj = NewObject<UMyObject>(); ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(1.0f)); ADD_LATENT_AUTOMATION_COMMAND(FLambdaCommand([this, &obj]() { TestEqual(TEXT("check"), obj->Property, 1); }); ADD_LATENT_AUTOMATION_COMMAND(FLambdaCommand([&obj]() { obj->Hoge(); }) ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(1.0f)); ADD_LATENT_AUTOMATION_COMMAND(FLambdaCommand([this, &obj]() { TestEqual(TEXT("check"), obj->Property, 1); }) }
こちらのほうが処理の流れも追いやすく気に入っています。
ただふとEngineのソースを眺めていたところ、わざわざ作らなくても同様のものがありました。 他のLatentコマンドはAutomationCommon.hにまとまっていたので、見逃してました。 以前からあったのかな。。。
AutomationTest.h class FFunctionLatentCommand : public IAutomationLatentCommand { public: FFunctionLatentCommand(TFunction<bool()> InLatentPredicate) : LatentPredicate(MoveTemp(InLatentPredicate)) { } virtual ~FFunctionLatentCommand() { } virtual bool Update() override { return LatentPredicate(); } private: TFunction<bool()> LatentPredicate; };