paint-brush
Testen in Godot: Wie ich persönlich daran herangehevon@dlowl
593 Lesungen
593 Lesungen

Testen in Godot: Wie ich persönlich daran herangehe

von D. Lowl4m2024/03/07
Read on Terminal Reader

Zu lang; Lesen

Godot Unit Test (GUT) kann mit einem Klick von AssetLib installiert werden. Es stellt eine Klasse bereit, die wir für unsere Testskripte erweitern können. Es verfügt über eine schöne Benutzeroberfläche mit der Möglichkeit, den Debugger von Godot zu verwenden und individuelle Tests auszuführen. Es kann über CLI und in CI ausgeführt werden (aber darauf gehe ich später ein)
featured image - Testen in Godot: Wie ich persönlich daran herangehe
D. Lowl HackerNoon profile picture

Zur Abwechslung würde ich gerne ein kleines Entwicklerprotokoll erstellen. Vor einiger Zeit habe ich an einem Game Jam teilgenommen und dieses Spiel – Of Mice and Bad Choices – gemacht, ein kurzes Puzzlespiel, bei dem man Käse um das Labyrinth legt, um die Mäuse herauszulocken. Es hat Spaß gemacht, aber es gab offensichtlich einige Mängel.


Einer der Hauptgründe ist, dass das Verhalten von Mäusen nicht intuitiv ist. Die Spieler erwähnten, dass sie damit rechnen würden, dass Mäuse von einem unbeliebten Käse abgestoßen werden und nicht nur erfrieren. Darüber hinaus würde die Implementierung dieser Mechanik ein viel reichhaltigeres Puzzle-Design ermöglichen.


Daher denke ich, dass dies eine gute Gelegenheit ist, automatisierte Tests in Godot durchzuführen.

Eine Veranschaulichung eines erwarteten Verhaltens: Die Maus sollte sich vom Blauschimmelkäse entfernen

Testwerkzeuge

Es gibt einige Test-Frameworks, die für Godot 4 verfügbar sind, aber dasjenige, das mich überzeugt hat, ist Godot Unit Test (GUT) . GUT ist ziemlich einfach:


  • Es kann mit einem Klick von AssetLib installiert werden.


  • Es stellt eine Klasse bereit, die wir für unsere Testskripte erweitern können: Fügen Sie einfach Funktionen hinzu, die mit test_ beginnen, und schreiben Sie einige Behauptungen – typische Unit-Test-Struktur.


  • Es verfügt über eine schöne Benutzeroberfläche mit der Möglichkeit, den Debugger von Godot zu verwenden und individuelle Tests auszuführen.


  • Es kann über CLI und in CI ausgeführt werden (aber darauf werde ich später noch eingehen).

Mein Test-Framework

Für diesen speziellen Fall wollte ich eine Möglichkeit haben, komplexe Szenarien zu definieren, genauso wie ich Levels für das Spiel definiere – im Engine-Editor und nicht im Code (auf diese Weise wären die Tests näher an der Realität). Daher möchte ich diese Dinge tun:


  • Verfügen Sie über eine einzelne Runner-Funktion, die eine Karte aufnimmt und die Tests ausführt.


  • Verfügen Sie über eine Sammlung von Karten, von denen jede eine Reihe auszuführender Szenarien (Testfälle) enthält.


  • Sie haben die Möglichkeit, Testfälle per Drag-and-Drop zu definieren: Platzieren Sie eine Maus und legen Sie fest, wo sie sich in N Runden befinden soll.


Also, packen wir das aus.

Testfalldefinitionen

Definieren wir eine neue Klasse „MouseTestCase“. Wir möchten, dass sie Node2D erbt (da wir sie in einer Szene platzieren möchten. Und wir möchten, dass sie eines ihrer Kinder findet (die wir selbst in einer Szene platzieren): eine Maus und seine erwartete Endposition (als Marker)

 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)


Jetzt können wir es in Szene setzen, und wir sind gut! Wir wissen, wo eine Maus anfängt, wir wissen, wo sie enden soll und in wie vielen Schritten.

Ein Knotenbaum zum Definieren eines Testfalls

So sieht es auf der Karte aus: die zu testende Maus in Grün, die Zielmarkierung in Rot

Testkarten

Jetzt machen wir noch ein paar davon und erstellen eine Karte, um unser Abwehrverhalten zu testen.

Die resultierende Testkarte für das Testen der „Abwehr“-Mechanik

Dieses Verhalten ist etwas komplex, daher möchten wir viele leicht unterschiedliche Fälle abdecken:

  • Eine Maus möchte sich vom unbeliebten Käse entfernen/


  • Eine Maus möchte die Bewegungsrichtung beibehalten (d. h. Wendungen vermeiden)


  • Eine Maus bevorzugt Linkskurven gegenüber Rechtskurven und Kehrtwendungen


Die resultierende Karte, die 12 Testfälle zur Abdeckung dieses Verhaltens definiert, ist oben dargestellt (stellen Sie sich vor, wie mühsam es sein könnte, alle diese Koordinaten fest im Code zu codieren).

Testläufer

Es bleibt nur noch die Test-Runner-Funktion übrig. Die Funktion muss:

  • Laden Sie die Karte, die wir oben definiert haben.


  • Simulieren Sie die Spielschritte vorwärts, bis alle Testfälle abgeschlossen sind.


  • Iterieren Sie bei jedem Schritt alle Testfälle und überprüfen Sie, ob die erwartete Position erreicht ist, wenn sie abgeschlossen sind.


Der Code ist recht einfach.

 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)

Ich kann mir vorstellen, dass sich das weiterentwickeln wird, aber die aktuelle Implementierung ist vorerst gut genug. Ich habe die Tests geschrieben, die Mechanik implementiert und die Tests bestätigen tatsächlich, dass die Mechanik korrekt implementiert ist!

Der Bereich von GUT zeigt den erfolgreichen Testlauf

Diskussionen

Hier habe ich eine Möglichkeit gezeigt, die Tests in Spielen anzugehen. Offensichtlich gibt es hier noch viel mehr zu verbessern, und ich ermutige die Leser, den Code und das Framework zu nehmen und an ihre Bedürfnisse anzupassen.


Der Code ist wie immer auf GitHub verfügbar: https://github.com/d-lowl/of-mice-and-bad-choices Sie können sich auch die spezifische PR ansehen, die das Testen vorstellt. Für Bonuspunkte wäre es großartig, wenn jemand sie dazu bringen könnte, in CI zu arbeiten. Prost.