paint-brush
Godot でのテスト: 私個人のアプローチ方法@dlowl
730 測定値
730 測定値

Godot でのテスト: 私個人のアプローチ方法

D. Lowl4m2024/03/07
Read on Terminal Reader

長すぎる; 読むには

Godot Unit Test (GUT) は、AssetLib からワンクリックでインストールできます。これは、テスト スクリプト用に拡張できるクラスを提供します。 Godot のデバッガーを使用して個別のテストを実行できる優れた UI を備えています。 CLI および CI から実行できます (ただし、これについては後ほど説明します)。
featured image - Godot でのテスト: 私個人のアプローチ方法
D. Lowl HackerNoon profile picture

気分を変えて、開発ログを少し書いてみたいと思います。少し前に、私はゲーム ジャムに参加し、このゲーム「 Of Mice and Bad Choices 」を作成しました。これは、迷路の周りにチーズを置いてネズミをおびき寄せる短いパズル ゲームです。楽しかったですが、明らかに欠点もいくつかありました。


主な問題の 1 つは、マウスの行動が直感的ではないことです。選手らは、ネズミがただ凍るのではなく、嫌いなチーズによって忌避されることを期待していると述べた。さらに、このメカニズムを実装すると、より豊かなパズルのデザインが可能になります。


したがって、これは Godot で自動テストをどのように実行できるかについて説明する良い機会だと思います。

予想される動作の図: マウスはブルーチーズから離れるはずです

テストツール

Godot 4 で利用できるテスト フレームワークはいくつかありますが、私の印象に残ったのはGodot Unit Test (GUT)です。 GUT は非常にシンプルです。


  • AssetLib からワンクリックでインストールできます。


  • これは、テスト スクリプト用に拡張できるクラスを提供しますtest_で始まる関数を追加し、典型的な単体テスト構造であるアサーションを記述するだけです。


  • Godot のデバッガを使用して個別のテストを実行できる優れた UI を備えています。


  • CLI および CI から実行できます (ただし、これについては後ほど説明します)。

私のテストフレームワーク

この特定のケースでは、ゲームのレベルを定義するのと同じ方法で、コードではなくエンジン エディターで複雑なシナリオを定義する方法が必要でした (この方法により、テストがより現実に近づきます)。したがって、私はこれらのことをしたいと思います:


  • マップを取り込んでテストを実行する単一のランナー関数を用意します。


  • マップのコレクションを用意し、それぞれに実行する一連のシナリオ (テスト ケース) を含めます。


  • ドラッグ アンド ドロップの方法でテスト ケースを定義する方法を用意します。マウスを配置し、N ターンで配置する場所を設定します。


それでは、これを開封してみましょう。

テストケースの定義

新しいクラス `MouseTestCase` を定義しましょう。(シーン上に配置したいので) Node2Dを継承させたいと思います。そして、その子 (シーン上に自分たちで配置する) を見つけられるようにしたいと思います: マウスと予想される最終位置 (マーカーとして)

 extends Node2D class_name MouseTestCase @export var steps_left = 0 # How many steps to simulate @export var done = false @onready var mouse: Mouse = $Mouse @onready var expected_position = SnapUtils.get_tile_map_position($TestMarker.position)


これで、シーンに置くことができます。これで問題ありません。私たちはマウスがどこから始まり、どこで終了するのか、そして何ステップで終わるのかを知っています。

テストケースを定義するためのノードツリー

地図上では次のように見えます。テスト対象のマウスは緑色、ターゲット マーカーは赤色です。

テストマップ

さて、さらにたくさんのそれらを作成し、忌避動作をテストするためのマップを作成しましょう。

「反発」メカニックテストの結果として得られるテストマップ

この動作はやや複雑であるため、わずかに異なる多くのケースを取り上げたいと思います。

  • ネズミは嫌いなチーズから離れたいと思っています/


  • マウスは移動方向を維持したい(つまり、方向転換を避けたい)


  • ネズミは右折やUターンより左折を好む


この動作をカバーするための 12 のテスト ケースを定義した結果のマップを上に示します (これらすべての座標をコードにハードコーディングすることがどれほど面倒か想像してみてください)。

テストランナー

あとはテストランナー機能だけです。関数は次のことを行う必要があります。

  • 上で定義したマップをロードします。


  • すべてのテスト ケースが完了するまでゲームのステップをシミュレートします。


  • 各ステップで、すべてのテスト ケースを繰り返し、完了したら、予想される位置に到達したかどうかを確認します。


コードは非常にシンプルです。

 func run_level_with_mouse_test_cases(map_path: String): var level = load(map_path) map.load_level(level) var cases = MouseTestCase.cast_all_cases(get_tree().get_nodes_in_group(MouseTestCase.MTC_GROUP_NAME)) while (cases.any(func(case): return not case.done)): map.move_mice() for case in cases: if not case.done: case.steps_left -= 1 if case.steps_left == 0: case.done = true assert_eq(case.get_mouse_position(), case.expected_position, case.get_parent().name+"/"+case.name)

これは進化すると思いますが、今のところは現在の実装で十分です。私はテストを作成し、メカニズムを実装しました。そして、そのメカニズムが正しく実装されていることをテストで実際に確認しました。

成功したテスト実行を示す GUT のペイン

ディスカッション

ここでは、ゲームでテストに取り組む 1 つの方法を示しました。明らかに、ここには改善すべき点が他にもたくさんあります。読者には、コードとフレームワークを入手して、ニーズに合わせて調整することをお勧めします。


いつものように、コードは GitHub で入手できます: https://github.com/d-lowl/of-mice-and-bad-choicesまた、テストを紹介する特定の PRを確認することもできます。ボーナス ポイントとして、誰かがそれらを CI で動作させることができれば、それは素晴らしいことです。乾杯。