Testons, testons

En général, tout le monde s'accorde à dire qu'une suite de tests de régression est nécessaire pour chaque fonctionnalité d'un programme.
En général, personne n'a envie d'écrire ni de maintenir des tests.

Dans le petit monde de Blood Bowl, les choses pourraient être un peu différentes. Il n'est pas (encore) question de tester toutes les fonctionnalités, mais une des principales, le fonctionnement correct des règles du jeu par rapport au LRB 5.0. Comme les non-développeurs sont plus nombreux que les développeurs, et préssés d'avoir un joujou (la 0.7M1), on pourrait leur refiler cette tâche ingrate pour les faire patienter. La seule condition étant qu'ils puissent le faire sans manipuler de code, mais éventuellement du texte ou des fichiers de description.

Deux gros avantages:

  • Quelqu'un repère un bug : plutôt que de dire aux développeurs : « Heu, ça bug quand je prends la balle en bloquant et déplacant un joueur vers le fond et quand mon chat remue la queue », il rajoute un test qui met en évidence ce bug (et fait gagner environ 75% du temps aux développeurs)
  • Quand on modifie le code, tout casser est super rapide (suivez des yeux mon regard...). Au moins, ça permet de s'en apercevoir plus vite.

Voilà pour le pourquoi du comment. Maintenant, voyons comment ça se manipule en pratique.

Keskikouille ?

En realité, vous allez vite vous en apercevoir, le « framework » de test des règles est loin d'être la panacée. Vous n'aviez pas aimé le client en mode console ? Et bien attendez vous à pire. L'idée de base est justement de reprendre ce client en mode console, mais au lieu de taper les commandes avec nos petites paluches, les mettre dans un fichier et dire à ce client console d'aller lire ce fichier. De là, on peut lancer automatiquement des parties, et comparer ensuite le résultat à un résultat de référence. Le travail reste donc d'écrire les fichiers de commandes et les sorties de référence.

Il y a deux fichiers de commandes à faire pour chaque test, un pour chaque coach. Il se présente sous la forme d'un fichier texte, avec, ligne par ligne, toutes les commandes que vous auriez normalement tapé dans le client console, plus la commande « wait » pour attendre un événement. Dans les commandes, vous pouvez faire afficher des données en cours de jeu. Mises entre des balises spéciales, elles seront comparées à une sortie de référence à la fin de l'exécution.

Par exemple:

print BEGIN DIFF
print global
print us 1
print END DIFF

Vous devez aussi écrire la sortie de référence. Mettez ce que ça devrait faire. Quand vous écrivez le test, vous devriez connaître le comportement de votre cas. Sur ce dernier exemple, il faudrait mettre la sortie de 'print global' telle qu'attendue, ainsi que la sortie de 'print us 1'.

Tous les tests à effectuer sont dans le fichier : bb5/rules_test/test_pool.yml. Le format de ce fichier est, espérons le, suffisamment simple à comprendre pour ne pas devoir l'expliquer. Il faut ensuite ajouter le nom du test dans le fichier : bb5:rules_test/Makefile.am

Pour lancer la procédure de test (notez que vous devez avoir installé TBT avant, ie: make install):

$ make installcheck

Déterminisme

Blood Bowl est un jeu qui laisse un peu de place au hasard. Cela ne nous aide pas beaucoup, vu que nous déroulons une séquence de commande prédéterminée qui ne peut pas varier. Et selon que la balle roule à gauche ou à droite, en réalité chaque éxécution peut-être totalement différente.

Nous allons contourner le problème, en fixant les jets de dés à des valeurs prédéterminées, comme le reste des commandes. Cela revient à choisir à l'avance les résultats des jets de dés, de la triche en quelque sorte. Mais on n'est plus a cela près. Pour cela, une magnifique commande a été introduite: 'cheat', qui prend en paramètre une liste de résultats que l'on souhaite obtenir :

cheat 2 6 4

Les résultats des 3 prochains jets de dés seront, dans l'ordre 2, 6, puis 4. Les suivants seront de nouveau aléatoire, à moins qu'une autre commande 'cheat' n'ai été réutilisée d'ici là.

Au coup d'envoi, le premier jet de dé est un JD6 pour déterminer la distance de dispersion du ballon. Vient ensuite un JD8 pour la direction de dispersion, interprété selon le modèle suivant :

123
8X4
765

Remarques en vrac

  • Ne pas mettre de tabulation dans test_pool.yml (c'est du YAML !).
  • Le coach 2 a toujours le choix de tirer le kick-off ou de recevoir.
  • Toujours mettre un 'wait' en début du premier coach.
  • Bien placer ses 'wait', sinon ça part vite en vrille.
  • Ne faire 'quit' que d'un client, l'autre partira tout seul.
  • De manière générale, regarder les tests qui existent déjà et s'en inspirer.
  • Ne pas chercher a tester le framework de test. Ça part trop vite en vrille.

Exemple de fichiers de commandes pour les deux joueurs

Coach 1:

wait               <-- on attend la phase de placement de l'équipe.
place end          <-- on ne modifie pas le placement par défaut.

wait               <-- on attend le 1er tour de jeu (apres le kick-off)
cheat 5            <-- pour réussir son 'move'
move 1 10 1
accept             <-- on accepte le résultat (même les jets de dé réussis peuvent être relancés)
print BEGIN DIFF
print us 1         <-- affiche la position du joueur, qui sera vérifiée par
print END DIFF     <--   rapport a une référence.
quit               <-- on a fini de bouger, on quitte (fin tour 1)

Coach 2:

wait               <-- on attend le choix initial
choose kickoff     <-- on choisit de tirer le kick-off

wait               <-- on attend la phase de placement de l'équipe
place end          <-- on ne modifie pas le placement par défaut

wait               <-- on attend le début du kick-off
cheat 1 1 1        <-- 3 jets de dés pour que la balle ne rebondisse dans le terrain et sur aucun joueur
kickoff 4 4        <-- on jette la balle (termine la phase de kick-off)
wait               <-- on attend le 1er tour de jeu (du coach 2), en réalité
                   <--   attend le 'quit' de l'autre.

Diff 1:

Player '1' (team 0) - Mary-Jean
  position      : [row/y:10 col/x:1]
  carateristics :  ma: 6 | st: 3 | ag: 3 | av: 7
  ma_remain     : 4
  status        : Standing

Diff 2:

(vide)

Récapitulatif pour créer un nouveau test

  • Faire deux fichier de commandes (et éventuellement d'autre fichiers team.xml et formation.xml), les tester a la main.
  • Faire deux fichier de sortie de référence.
  • Remplir le fichier bb5/rules_test/test_pool.yml.
  • Rajouter une ligne dans bb5/rules_test/Makefile.am, dans la variable MY_TEST.
  • Prier, et lancer make installcheck.
  • Une fois que ça marche, rajouter tous les nouveaux fichiers au dépôt svn, et commiter.

Notes pour les développeurs

Faites:

$ export DEBUG=1
$ make installcheck

Et il vous gardera le répertoire temporaire où il a effectué son test (<name>-test-rules), avec dedans les fichiers qui ont servi à faire le test et les fichiers de sortie. De là, vous pouvez relancer ./debug_me.sh, qui relance la partie (mais ne fait pas le diff), pratique pour voir rapidement ce qui a foiré.

Le fichier de log (<name>.log) dans bb5/test_rules/ est aussi une bonne indication de ce qui a fonctionné ou non, n'hésitez pas à aller le voir ou à le réclamer à quelqu'un chez qui les tests foirent.