57 votes

Les tests unitaires sont-ils viables dans la programmation de jeux ?

J'aime beaucoup l'idée des tests unitaires, mais j'ai du mal à l'appliquer à la programmation de jeux. Les jeux sont très évolutifs et souvent le code ne se décompose pas en unités distinctes. D'après mon expérience, la plupart des fonctions modifient l'état plutôt que de renvoyer des valeurs.

Prenons l'exemple d'une action simple comme playerJump(height) . J'aimerais avoir une suite de tests qui vérifie une grande variété de cas pour s'assurer que le saut fonctionne toujours comme prévu. Cependant, cette fonction ne renverra probablement aucune valeur et aura l'effet secondaire de , player.velocity.y = -height y checkCollisions(player) . Je n'arrive pas à trouver un test unitaire clair à construire autour de cela.

Les tests unitaires ne sont-ils tout simplement pas viables dans les applications à état élevé comme les jeux ? Les avantages des tests unitaires sont-ils si importants qu'il vaille la peine de programmer les jeux de manière fonctionnelle ?


Mise à jour :

Games from Within propose une série d'articles détaillés sur l'utilisation du développement piloté par les tests dans les jeux. Je les recommande vivement à toute personne intéressée par ce sujet. Voici le premier article :

http://gamesfromwithin.com/stepping-through-the-looking-glass-test-driven-game-development-part-1

0 votes

Pour UnitTest++, allez sur github.com/unittest-cpp/unittest-cpp. Tout le reste est obsolète.

37voto

S.Lott Points 207588

Souvent, le code ne se décompose pas en unités distinctes.

C'est tout simplement une mauvaise conception. Le code ne se décompose pas en quoi que ce soit. En tant que concepteur, vous devez imposer une structure au code afin de pouvoir démontrer qu'il fonctionne réellement.

Cependant, cette fonction ne renverra probablement aucune valeur...

Et alors ?

...et ont pour effet secondaire de.., player.velocity.y = -height y checkCollisions(player) .

Il s'agit alors d'un test.

Je ne vois pas de test unitaire clair à construire autour de cela.

Pourquoi pas ? Vous venez de donner une excellente spécification pour les résultats de la fonction.

Vous pourriez avoir besoin de quelques objets fictifs pour remplacer le lecteur complet par un MockPlayer simplifié, plus facile à tester.

Mais votre spécification du comportement était parfaite. Il suffit de tester les choses que vous avez décrites.

7 votes

Ah, je vois. Je pense que j'interprète les "tests unitaires" trop littéralement. J'imagine que je teste les entrées et les sorties de chaque fonction. Le test pourrait plutôt valider les contraintes sur l'ensemble du système après l'appel d'une fonction. Merci, c'est toujours agréable de sortir de ma vision d'entonnoir de programmation :)

0 votes

@Kai : Puisque le changement d'état du système est le effet secondaire de la fonction, vous effectuez toujours des tests unitaires car la fonction est testée de manière isolée. Il est très facile de tester avec les Mock Objects. Je ne vois pas très bien pourquoi vous prétendez que les tests unitaires sont en quelque sorte limités aux entrées et sorties des fonctions appropriées.

7 votes

Le problème que je rencontre avec cette idée est que le test pourrait finir par être aussi compliqué et sujet à des bogues que l'unité testée. Prenons l'exemple des changements d'état basés sur le tic-tac, comme la vitesse, où aucune valeur paramétrable n'est modifiée alors que les valeurs paramétrables changent à chaque tic-tac. Il faudrait créer une émulation du comportement de la vélocité pour la vérifier, en réimplémentant le code original de la vélocité, mais si le test échoue, est-ce l'unité qui est défectueuse ou le test ?

24voto

Kylotan Points 14114

Les tests unitaires peuvent être utiles pour un grand nombre de bibliothèques de bas niveau que vous pouvez utiliser avec le code du jeu, mais je doute sérieusement qu'ils soient d'une grande utilité pour les choses de plus haut niveau. Les jeux sont généralement des simulations et s'appuient sur des quantités massives d'états partagés qui ne peuvent pas être modélisés et testés de manière significative de manière isolée. Souvent, les fonctions des jeux ne renvoient pas de valeur que l'on puisse vérifier instantanément, mais déclenchent un processus qui doit s'achever à un moment donné dans le futur. Tester un tel comportement est intéressant, mais nécessite une approche très différente de l'idée du test unitaire, qui consiste à tester des morceaux de code de manière isolée.

1 votes

C'est une description plus claire du problème que je décrivais, merci. Il peut être intéressant de vérifier si le processus mis en route s'est effectivement terminé comme prévu, mais cela semble prendre plus de temps que de tester les entrées et sorties d'une simple fonction.

21voto

Jason Williams Points 31901

La programmation, c'est la programmation. Les tests unitaires sont utiles pour tout type d'application car ils vous aident à détecter et à corriger les erreurs (et souvent, plus important encore, les régressions introduites par inadvertance lors de la refonte du code) immédiatement et efficacement.

Il y a bien sûr des domaines de comportement de haut niveau qui sont difficiles à tester de manière unitaire, mais ce n'est pas vraiment à cela que servent les tests unitaires - ils servent avant tout à vérifier que des méthodes individuelles ou de petites parties de la base de code font ce qu'elles sont censées faire.

Pour les comportements de plus haut niveau, vous devez appliquer d'autres approches de test (tests de régression, par exemple : introduire une séquence fixe d'entrées dans le jeu et vérifier que vous obtenez les mêmes résultats à chaque fois, ou générer des vues de caméra à des endroits fixes dans un niveau et vérifier qu'elles génèrent toujours la même image (ou au moins une image raisonnablement similaire)).

Votre exemple de PlayerJump en est un. Vous pouvez effectuer des tests unitaires ou de régression en l'isolant avec des entrées constantes (placez par programme le personnage du joueur à un endroit fixe dans une scène de test simple et déclenchez l'événement de saut, puis vérifiez que ses collisions ou son lieu de repos final sont cohérents). En créant une bibliothèque d'objets différents sur lesquels le joueur peut sauter, vous pouvez couvrir un grand nombre de cas de test (par exemple, que le saut réussisse sur un espace de la distance maximale de saut prescrite).

En outre, les jeux nécessitent de nombreux tests de jouabilité (où de vrais utilisateurs jouent simplement). Cela permettra de trouver des cas bizarres que vous n'avez pas couverts avec les tests automatisés, mais surtout de répondre à une question à laquelle les tests automatisés ne répondront jamais : Est-ce que le jeu est "agréable" ? Est-ce que c'est "amusant" ? Ce sont des tests que seul un être humain peut effectuer.

4 votes

+1 Le test unitaire d'un moteur de rendu est pratiquement impossible. Certaines personnes utilisent la méthode Pixar et photographient la même scène de contrôle sous le même angle, avec le même éclairage et les mêmes shaders, et comparent les images.

0 votes

La programmation est la programmation, mais lorsqu'il s'agit de livrer quelque chose, l'économie, les équipes et le monde réel ne fonctionnent pas comme ça.

0 votes

@JohnStock : En effet, le coût/bénéfice de tout outil/technique doit être pris en compte. Tester tout à l'unité n'est pas pratique. Ne rien tester à l'unité est téméraire. La compétence consiste à trouver le meilleur compromis de test unitaire, en ciblant les endroits où il apporte le meilleur équilibre entre l'efficacité et le coût. L'efficacité peut également être influencée par l'expérience et les compétences du programmeur - un programmeur débutant commettra généralement plus d'erreurs et sera donc davantage aidé par les tests unitaires.

7voto

Mon expérience des tests unitaires et automatisés lors du développement de Crysis 2 est disponible ici : http://yetanothergameprogrammingblog.blogspot.com/2010/06/aaa-automated-testing.html J'espère que cela vous aidera.

Résumé :

L'automatisation des tests a permis d'améliorer la stabilité des produits livrés et d'accroître la productivité des créateurs de contenu et des ingénieurs. Les tests automatisés sont un outil efficace pour améliorer la qualité du code et réduire les risques de devoir faire des heures supplémentaires. L'industrie du jeu

0 votes

Le lien ne fonctionne pas et la question portait sur les tests unitaires et non sur les tests automatisés plus généraux.

2voto

nate dehaven Points 21

Je recommande vivement la méthode TDD. C'est l'un des moyens les plus sûrs de s'assurer que votre développement de jeux Le processus ne prend pas une tournure négative et ne s'engage pas dans une mauvaise voie sans s'en rendre compte.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X