0
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?

Godot 4のテストフレームワーク GdUnit4 でユニットテストを書く

0
Posted at

Godot 4でゲームを作っていると、コードが大きくなるにつれて「この関数、本当に正しく動いてる?」という不安が出てきます。Web開発ではテストを書くのが当たり前ですが、ゲーム開発では後回しになりがちです。

この記事では、Godot 4で最も成熟したテストフレームワーク GdUnit4 を使ったユニットテストの書き方を、実際に動くコード付きで解説します。

なぜゲームコードにテストが必要なのか

ゲームのバグは「動かない」より「変な動きをする」が多いです。プレイヤーHPが負の値になる、特定の順序でアイテムを取ると進行不能になる、敵が壁にめり込む。こうしたバグは目で見ても気付きにくく、リリース後にレビューで報告されてから初めて分かることが多いです。

ユニットテストは「特定のロジックが期待通りに動くか」を自動で検証してくれます。HP管理、インベントリ計算、ダメージ計算など、ロジックが独立している部分には特に効果的です。

GdUnit4のインストール

GdUnit4はAssetLibから直接インストールできます。

  1. Godotエディタで AssetLib タブを開く
  2. GdUnit4 を検索
  3. ダウンロードしてプロジェクトに追加
  4. プラグインメニューから GdUnit4 を有効化

有効化すると、エディタの下部に GdUnit4 パネルが追加されます。

最初のテストを書く

プロジェクトのルートに tests/ フォルダを作って、その中にテストファイルを置きます。例として、シンプルなプレイヤーステータスクラスをテストします。

# scripts/player_stats.gd
class_name PlayerStats
extends Resource

@export var hp: int = 100
@export var max_hp: int = 100

func take_damage(amount: int) -> void:
    hp = max(0, hp - amount)

func heal(amount: int) -> void:
    hp = min(max_hp, hp + amount)

func is_dead() -> bool:
    return hp <= 0

対応するテストファイル:

# tests/test_player_stats.gd
class_name TestPlayerStats
extends GdUnitTestSuite

var stats: PlayerStats

func before_test() -> void:
    stats = PlayerStats.new()

func test_take_damage_reduces_hp() -> void:
    stats.take_damage(30)
    assert_int(stats.hp).is_equal(70)

func test_take_damage_cannot_go_below_zero() -> void:
    stats.take_damage(200)
    assert_int(stats.hp).is_equal(0)

func test_heal_does_not_exceed_max_hp() -> void:
    stats.take_damage(30)
    stats.heal(100)
    assert_int(stats.hp).is_equal(100)

func test_is_dead_when_hp_is_zero() -> void:
    stats.take_damage(100)
    assert_bool(stats.is_dead()).is_true()

ポイント:

  • extends GdUnitTestSuite を継承する
  • before_test() でテストごとに状態をリセット
  • 各テスト関数は test_ で始める
  • assert_int(), assert_bool(), assert_str() などの fluent API を使う

テストを実行する

GdUnit4パネルでテストファイルを右クリック → Run Test で実行できます。コマンドラインからも実行可能です:

godot --headless -s addons/gdUnit4/bin/GdUnitCmdTool.gd -a tests/

CI/CDに組み込む場合はこのコマンドラインバージョンが必須です。

シグナルのテスト

Godotのシグナルは少し特殊ですが、GdUnit4にはシグナル用のアサーションも用意されています。

func test_signal_emitted_on_death() -> void:
    var monitor = monitor_signals(stats)
    stats.take_damage(100)
    await assert_signal(stats).is_emitted("died")

monitor_signals() でシグナルの発火を監視し、assert_signal().is_emitted() で検証します。

モックとスタブ

GdUnit4は mock() 関数でクラスのモックを作れます。

func test_save_manager_calls_resource_saver() -> void:
    var save_manager = SaveManager.new()
    var mock_saver = mock(ResourceSaver)
    save_manager.saver = mock_saver
    save_manager.save_game()
    verify(mock_saver, 1).save(any(), any())

これでファイルシステムに実際に書き込まずにテストできます。

AIにテストコードを書かせる時の落とし穴

ChatGPT や Claude にGodot用のテストコードを書いてもらうと、よく extends Node を使ったり、Godot 3のtest patternを使ったりします。Godot 4 + GdUnit4 では extends GdUnitTestSuite が正解です。

実際にプロジェクトの依存関係を見られないAIには、こうしたバージョン違いの判別が難しいのです。Godotエディタの中で動作するAIエージェントの Ziva は、プロジェクトのGodotバージョンとインストール済みプラグインを実際に確認した上でテストコードを生成するので、こうしたミスを起こしません。

まとめ

ゲーム開発でもテストは書くべきですし、GdUnit4があれば書ける環境は整っています。最初は HP/インベントリのようなロジック中心の部分から始め、徐々にカバレッジを増やしていくのが現実的です。

Godot公式のテストフレームワーク統合はまだ無いので、GdUnit4は事実上の標準になっています。AssetLibから5分でセットアップできるので、まずは小さいテストから書いてみましょう。

0
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
0
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?