【Unreal Engine】UEの自動テスト入門:直したつもりが壊れていた、を防ぐ

作成: 2026-07-25

機能が10個になると、1つ直すたびに10個確認することになります。UEのFunctional Test(レベルにActorを置いて動かして判定する仕組み)の作り方、Assertノードでの判定、Session Frontendでの実行を図解。攻撃でHPが100→80になることをテストにし、わざと赤くしてから直す実践つき。

弾の当たり判定を直した。動くようになった。ところが後で気づくと、扉が開かなくなっている。触ってもいないはずの場所が壊れています。

機能が10個あるゲームでは、1つ直すたびに10個を手で確認しないと安心できません。20個になれば20個です。この繰り返しを機械にやらせる仕組みが 自動テスト で、UEには標準で入っています。この記事では、Blueprintだけで書ける Functional Test を作り、走らせ、わざと赤くしてから直すところまでを扱います。

チェックリストが自動で緑になっていく様子を見ているソフトブルーのクレイ人形

この記事でわかること

  • 手で確認することの限界
  • UEのテストは 2種類(Blueprint勢は Functional Test から)
  • Functional Test を親にした Blueprintを作る
  • Assert 系ノードでの 判定の書き方
  • Session Frontend で走らせる
  • 実践: HPが100→80になることをテストにし、一度赤くする

Sponsored

手で確認する限界

小さな試作なら、手で確認するほうが速いです。機能が3つなら3つ触るだけです。

問題は、機能の数と確認の手間が掛け算になることです。

機能が増えるほど、1つ直すたびに確認すべき箇所が増えていくことを示した図
機能の数1つ直したときに確認すべき数現実
33手でやれる
1010だんだん省き始める
2020もう全部は見ない

そして省いたところが壊れます。「触っていないから大丈夫」と思った場所が、共有している変数や共通の親クラス経由で影響を受けているからです。

自動テストの価値は、 「壊れていないことを、毎回タダで確認できる」 ことです。1度書けば、何回でも走らせられます。

この記事集では「わざと壊して直す」実践を何度もやってきました。 その裏返しが自動テストです。壊れていないことを、毎回確認する側の道具です。


UEのテストは2種類

UEには2種類のテストがあります。どちらから入るかで難易度が大きく変わります。

Functional Testはレベルに置いたActorが実際に動いて判定し、C++テストは関数単位で検証することを対比した図
種類何をするか向いているもの必要なもの
Functional Testテスト用レベルにActorを置き、実際に動かして結果を判定ゲームプレイの検証(弾が当たる、扉が開く)Blueprintだけ
C++のテスト関数単位で検証する計算ロジック(ダメージ計算式など)C++

Blueprintだけで作っているなら、Functional Test から入るのが正解です。

Functional Testは、UEらしい独特な形をしています。テストそのものがレベルに置くActorなのです。

  • テスト用のレベルを1つ作る
  • そこに、テスト用のActor(Functional Testを親にしたBlueprint)を置く
  • そのActorが自分でゲームを操作して、結果を判定する

「テストコードを書く」というより、 「テスト用のステージを作る」 感覚に近いです。ゲームを作る作業とほとんど同じなので、Blueprintに慣れているなら入りやすいはずです。


最初のFunctional Test

作り方は3ステップです。

Functional Testを親にBlueprintを作り、テスト用レベルに置き、Start TestからFinish Testまでを書く3ステップの図
  1. テスト用レベルを作るL_Test_Damage など)。テスト専用なので、床とライトだけの最小構成で構いません
  2. Blueprintを作る。親クラスに Functional Test を指定します(クラス一覧で「すべてのクラス」から検索)
  3. そのBlueprintをテスト用レベルに置く

Functional Testを親にすると、専用のイベントが使えるようになります。

イベント / ノード役割
Event Start Testテストの開始。ここから検証を書く
Finish Testテストの終了。成功か失敗を渡す
Assert 系期待値と比べる(次の節)

大事なのは、Finish Test を必ず呼ぶことです。呼ばないとテストは終わらず、タイムアウトで失敗扱いになります。

Finish TestTest Result に渡す値で結果が決まります。

  • Succeeded — 成功
  • Failed — 失敗
  • Invalid — 前提が満たされずテストにならなかった

判定の書き方

検証の中身は Assert 系のノードで書きます。「期待値と実際の値が一致するか」を確かめるノードです。

ノード確かめること
Assert True条件が true
Assert False条件が false
Assert Equal (Int)整数が期待値と一致するか
Assert Equal (Float)小数が期待値と一致するか(許容誤差を指定できる)
Assert Is Valid参照が有効か

どのノードにも Message ピンがあります。ここに書いた文字が、失敗したときにログへ出ます

Assert Equalが期待値と実際の値を比べ、一致しなければMessageの内容がログに出ることを示した図

Message は必ず書いてください。 「テストが失敗した」だけ分かっても、何が違ったのか分からなければ調べ直しになります。「ダメージ適用後のHPが期待値と違う」のように、読んだ瞬間にどこを見るか分かる文にしてください(→ Print StringとOutput Log)。

小数の比較には注意。 Assert Equal (Float) には許容誤差(Tolerance)があります。小数の計算はごく小さな誤差が出るので、0.0001 程度の余裕を持たせるのが普通です。Integer なら誤差はないので、そのまま比べて構いません。

Sponsored

走らせる

テストの実行は Session Frontend から行います。

Session FrontendのAutomationタブでテストを選び、実行ボタンを押すと結果が一覧で出ることを示した図
  1. メニューの ツール(Tools)→ Session Frontend を開く(日本語UIでは「セッションフロントエンド」)
  2. Automation タブを選ぶ(日本語UIでは「自動化」)
  3. ツリーからテストを探してチェックを入れる。Functional Testは Project の下に並びます
  4. 実行(Start Tests) を押す

すると、テスト用レベルが自動で読み込まれ、テストが走り、結果が一覧に出ます。緑が成功、赤が失敗です。

失敗した行を開くと、AssertMessage に書いた文が出ます。ここを読めば、どこを直すかが分かります。

一覧に自分のテストが出てこないときは、テスト用レベルにActorを置き忘れています。 Functional Testは「レベルに置かれていること」で発見されるので、Blueprintを作っただけでは一覧に現れません。


実践:HPが100→80になることをテストにする

ローグライクのダメージ計算、対戦ゲームのコンボ補正、RPGの属性倍率。数値が合っていることは、遊んで見ても気づきにくい部分です。ここでは ダメージ処理 の検証をテストにし、一度わざと赤くしてから直します

用意するもの

項目内容
BP_Enemy変数 MaxHealth(Float / 100.0)、CurrentHealth(Float / 100.0)。Event AnyDamageCurrentHealth から Damage を引く
テスト用レベルL_Test_Damage(床とライトのみ)
テストActorBP_Test_Damage(親クラス: Functional Test

テストの中で使う値を先に決めます。

変数名
TestDamageFloat20.0
ExpectedHealthFloat80.0(100 − 20)
テストを実行すると赤く失敗し、原因を直すと緑になるまでの流れを示した実例図

テストの中身

BP_Test_DamageEvent Start Test に、4ステップで書きます。

  1. Spawn Actor from ClassBP_Enemy をテスト用レベルに出す(位置は原点で構いません)
  2. Apply Damage(Damaged Actor: 生成した敵、Base Damage: TestDamage = 20.0)を呼ぶ
  3. Assert Equal (Float) で、敵の CurrentHealthExpectedHealth80.0)を比べる。Tolerance0.01Message「ダメージ適用後のHPが期待値と違う」
  4. Finish TestTest Result = Succeeded)を呼ぶ
上段「敵を出して殴る」でEvent Start Test→Spawn Actor from Class→Apply Damage、下段「期待値と比べて終わる」でGet CurrentHealth→Assert Equal (Float)→Finish Testへ折り返す2段組みの完成ノードグラフ
BP_Test_Damage(イベントグラフ)
Event Start Test
  → enemy = SpawnActorFromClass(Class = BP_Enemy, Transform = 原点)
  → ApplyDamage(
        DamagedActor = enemy,
        BaseDamage   = TestDamage)          // 20.0
  → AssertEqual_Float(
        Actual    = enemy.CurrentHealth,
        Expected  = ExpectedHealth,         // 80.0
        Tolerance = 0.01,
        Message   = "ダメージ適用後のHPが期待値と違う")
  → FinishTest(TestResult = Succeeded, Message = "")

Assert が失敗した時点でテストは失敗扱いになるので、Finish TestSucceeded を渡しておけば問題ありません(Assertが通ればそのまま成功します)。

まず、わざと赤くする

ここが重要です。テストが本当に機能しているかを確かめます。

BP_EnemyEvent AnyDamage の減算を、わざと壊してくださいCurrentHealth - DamageCurrentHealth - 0 に変える、あるいは減算を丸ごと外します。

その状態で Session Frontend からテストを走らせると、赤く失敗します

行を開くと、Message に書いた 「ダメージ適用後のHPが期待値と違う」 が出ています。期待値 80.0 に対して実際は 100.0 だった、という情報も一緒に出ます。

この赤を見ることが、テストを書く目的の半分です。 最初から緑のテストは、何も検証していない可能性があります(Assertの繋ぎ忘れなど)。

直して、緑にする

減算を元に戻し(CurrentHealth - Damage)、もう一度テストを走らせてください。緑になります

これで、「攻撃でHPが20減る」という仕様が機械的に守られている状態になりました。今後どこを直しても、このテストを走らせればこの1点が壊れていないことを一瞬で確認できます

うまくいかないときの切り分けです。

  • テストが一覧に出てこないBP_Test_Damageテスト用レベルに置いていません。Blueprintを作っただけでは発見されません
  • タイムアウトで失敗するFinish Test を呼んでいません。すべての経路から必ず呼んでください
  • Assert Equal (Float) が微妙な差で失敗するTolerance0.0 です。0.01 程度を入れてください
  • 敵が生成されないSpawn Actor from ClassTransform が未設定か、Collision Handling の設定で生成が拒否されています

ポイントは2つです。

  • 一度赤くしてから緑にする: わざと壊して失敗を見ることで、そのテストが本当に効いていると確認できます。緑だけを見て安心しないでください
  • Message に「どこを見るか」を書く: 半年後の自分が読んで、すぐ調べ始められる文にします。失敗の一覧に並ぶのはこの文だけです

バグを見つけて直したときは、そのバグを再現するテストを1つ足すのが効果的です。Blueprint Debugger で原因を突き止めたら、同じ条件をテストに落として、二度と同じ場所で踏まないようにします。


おまけ:先に知っておくと良いこと

テストは増やしすぎない。 個人開発で「全部テストする」を目指すと、テストの保守にゲーム制作の時間を食われます。壊れると痛い所、一度壊れた所だけに絞ってください。目安は、ダメージ計算・セーブとロード・進行フラグの3つです。どれも壊れても見た目には気づきにくく、気づいたときの被害が大きい部分です。

コマンドラインから走らせられる。 Session Frontendを開かずに、実行ファイルの引数でテストを走らせることもできます。「毎晩自動で全テストを走らせる」といった運用(CI)に使えますが、個人開発ではまず手で走らせる習慣を付けるほうが先です。

日本語UIでは表記が変わる。 Session Frontend は「セッションフロントエンド」、Automation タブは「自動化」です。英語のチュートリアルを見ながら日本語UIで探すと迷うので、言語設定を英語にしておくと詰まりにくいです(→ 初期設定)。

パッケージ前に走らせる習慣を。 パッケージ化 の前にテストを一度走らせておくと、「配布してから気づく」を減らせます。テストが5個あれば、確認は数十秒です。


まとめ

  • 機能が増えると 手での確認は必ず省かれる 。省いた所が壊れる
  • UEのテストは2種類。 Blueprint勢は Functional Test から
  • Functional Testは テスト用レベルに置くActor 。作る感覚はゲーム制作と同じ
  • 判定は Assert 系ノードMessage に「どこを見るか」を書く
  • Finish Test を必ず呼ぶ 。忘れるとタイムアウトで失敗する
  • 一度わざと赤くしてから緑にする 。最初から緑のテストは疑う

全部をテストする必要はありません。壊れたら痛い1箇所から始めてください。あなたのゲームで、壊れても気づきにくいのはどこでしょうか。