paint-brush
Tests dans Godot : comment je l'aborde personnellementpar@dlowl
603 lectures
603 lectures

Tests dans Godot : comment je l'aborde personnellement

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

Trop long; Pour lire

Godot Unit Test (GUT) peut être installé depuis AssetLib en un clic. Il fournit une classe que nous pouvons étendre pour nos scripts de test. Il possède une interface utilisateur agréable avec la possibilité d'utiliser le débogueur de Godot et d'exécuter des tests individuels. Il peut être exécuté depuis CLI et en CI (mais j'en parlerai plus tard)
featured image - Tests dans Godot : comment je l'aborde personnellement
D. Lowl HackerNoon profile picture

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.

Illustration d'un comportement attendu : la souris doit s'éloigner du fromage bleu

Outils de test

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 :


  • Il peut être installé depuis AssetLib en un clic.


  • Il fournit une classe que nous pouvons étendre pour nos scripts de test : ajoutez simplement des fonctions commençant par test_ et écrivez quelques assertions – structure typique de test unitaire.


  • Il possède une interface utilisateur agréable avec la possibilité d'utiliser le débogueur de Godot et d'exécuter des tests individuels.


  • Il peut être exécuté à partir de CLI et en CI (mais j'en parlerai plus tard).

Mon cadre de test

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:


  • Avoir une fonction d'exécution unique qui prend une carte et exécute les tests.


  • Avoir une collection de cartes, chacune ayant un ensemble de scénarios (cas de test) à exécuter.


  • Ayez un moyen de définir des cas de test par glisser-déposer : placez une souris et définissez où elle doit être en N tours.


Alors, déballons ça.

Définitions des cas de test

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.

Une arborescence de nœuds pour définir un scénario de test

Voilà à quoi cela ressemble sur la carte : la souris à tester en vert, le marqueur cible en rouge

Cartes de test

Maintenant, créons-en davantage et créons une carte pour tester notre comportement répulsif.

La carte de test résultante pour les tests mécaniques de « répulsion »

Ce comportement est quelque peu complexe, c'est pourquoi nous souhaitons couvrir de nombreux cas légèrement différents :

  • Une souris veut s'éloigner du fromage qu'elle n'aime pas/


  • Une souris veut garder la direction du mouvement (c'est-à-dire éviter les virages)


  • Une souris préfère les virages à gauche aux virages à droite et aux demi-tours


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).

Testeur

La seule chose qui reste à faire est la fonction Test Runner. La fonction doit :

  • Chargez la carte que nous avons définie ci-dessus.


  • Simulez les étapes du jeu jusqu'à ce que tous les cas de test soient terminés.


  • À chaque étape, parcourez tous les cas de test et, s’ils sont terminés, vérifiez si la position attendue est atteinte.


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 !

Le volet de GUT affichant le test réussi

Discussions

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.