Pour changer de rythme, j'aimerais faire un petit journal de développement. Il y a quelque temps, j'ai participé à un game jam et j'ai créé ce jeu – Of Mice and Bad Choices – un petit jeu de réflexion dans lequel vous placez du fromage dans le labyrinthe pour attirer les souris. C'était amusant, mais il y avait évidemment quelques défauts.
L’un des principaux problèmes est que le comportement des souris n’est pas intuitif. Les joueurs ont mentionné qu'ils s'attendraient à ce que les souris soient repoussées par un fromage qu'elles n'aiment pas, et pas seulement par le gel. De plus, la mise en œuvre de cette mécanique permettrait une conception de puzzle beaucoup plus riche.
Je pense donc que c'est une bonne opportunité pour savoir comment effectuer des tests automatisés dans Godot.
Il existe quelques frameworks de test disponibles pour Godot 4, mais celui qui m'a attiré est Godot Unit Test (GUT) . GUT est assez simple :
test_
et écrivez quelques assertions – structure typique de test unitaire.
Pour ce cas particulier, je voulais avoir un moyen de définir des scénarios complexes, de la même manière que je définis les niveaux du jeu – dans l'éditeur du moteur plutôt que dans le code (de cette façon, les tests seraient plus proches de la réalité). Par conséquent, je veux faire ces choses:
Alors, déballons ça.
Définissons une nouvelle classe `MouseTestCase.` Nous voulons qu'elle hérite Node2D
(car nous voulons le placer sur une scène. Et nous voulons qu'elle trouve l'un de ses enfants (que nous placerons nous-mêmes sur une scène) : une souris et sa position finale attendue (en tant que marqueur)
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)
Maintenant, nous pouvons le mettre en scène, et c’est bon ! Nous savons où commence une souris, où elle doit aboutir et en combien d'étapes.
Maintenant, créons-en davantage et créons une carte pour tester notre comportement répulsif.
Ce comportement est quelque peu complexe, c'est pourquoi nous souhaitons couvrir de nombreux cas légèrement différents :
La carte résultante définissant 12 cas de test pour couvrir ce comportement est présentée ci-dessus (imaginez à quel point il pourrait être fastidieux de coder en dur toutes ces coordonnées dans le code).
La seule chose qui reste à faire est la fonction Test Runner. La fonction doit :
Le code est assez simple.
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)
J'imagine que cela va évoluer, mais la mise en œuvre actuelle est suffisante pour le moment. J'ai écrit les tests, implémenté la mécanique, et les tests confirment en fait que la mécanique est correctement implémentée !
Ici, j'ai montré une façon d'aborder les tests dans les jeux. Évidemment, il y a beaucoup plus de choses à améliorer ici, et j'encourage les lecteurs à prendre le code et le framework et à les adapter à leurs besoins.
Comme toujours, le code est disponible sur GitHub : https://github.com/d-lowl/of-mice-and-bad-choices Vous pouvez également consulter le PR spécifique qui introduit les tests. Pour les points bonus, si quelqu'un peut le faire travailler chez CI, ce serait génial. Acclamations.