Comment fait-on des tests unitaires dans un moteur de jeu?

23

À ma grande honte, je n'ai jamais écrit un test unitaire approprié, seulement de petits programmes de test non organisés dont je disposerais alors après le test. Je n'ai pas vraiment une idée claire de la façon dont les tests unitaires doivent être effectués dans un projet de jeu. (Mon langage est C ++.)

Dois-je avoir un projet distinct pour chaque sous-système de mon moteur et un test associé avec celui-ci, puis avoir un projet / solution plus grand qui construit le moteur réel? Disons par exemple que j'ai le eventmodule dans mon moteur; comment dois-je gérer cela?

Paul Manta
la source
question intéressante, lorsque vous développez votre moteur, il est assez facile de tester la fonctionnalité, mais qu'en est-il du grand projet dans le test de jeu?
Yevhen
2
Pas dommage: les tests unitaires ne sont pas automatiquement une bonne chose.
o0 '.
1
Si vous n'avez jamais essayé d'utiliser des tests unitaires, c'est vraiment dommage.
Kristopher Johnson

Réponses:

18

Tout d'abord, vous auriez besoin d'un cadre de tests unitaires. Dans le passé, j'ai utilisé UnitTest ++ et Google Test . Le premier est très léger et le second est plus en vedette mais un peu plus encombrant. Il s'intègre bien avec Google Mock si vous avez besoin de ce genre de chose. Il y a bien sûr de nombreuses autres options: voir cette liste (par l'auteur éventuel de UnitTest ++) et Wikipedia par exemple.

Les tests unitaires consistent à écrire des tests ciblés pour souligner des bits de code indépendants ("unités") particuliers isolés dans divers scénarios. Bien que dans certains cas, vous puissiez tout tester unitaire, il n'est généralement pas pratique d'atteindre une couverture à 100% et, en particulier dans les jeux, peut être assez difficile - on peut se demander si le test unitaire de votre sortie de rendu est significatif, utile ou un "vrai" test unitaire malgré tout.

Il est important de se rappeler que tout test (automatisé) est préférable à aucun test (automatisé). Vous ne devriez donc pas trop insister sur le fait que vos tests ne sont pas de "vrais tests unitaires" et être fier que vous ayez simplement des tests. Les cadres de tests unitaires sont généralement utiles pour créer des tests plus lâches et "non unitaires", car ils incluent des fonctionnalités permettant de regrouper les tests et de signaler les défaillances de manière uniforme.

Je vous encourage à ressusciter vos anciens tests et à les intégrer dans un projet de test en utilisant l'un des cadres disponibles - quelque chose que vous pouvez facilement exécuter de temps en temps (ou automatiquement dans le cadre d'une version ou d'une build d'intégration) qui exécute tous vos tests. Écrivez de nouveaux tests pour les bits de code car il devient évident qu'ils vous seraient utiles, par exemple si vous découvrez un bug subtil que vous auriez pu détecter avec un test, vous pouvez en ajouter un pour attraper toutes les régressions que vous pourriez faire à l'avenir.

Vous constaterez probablement que c'est principalement votre code utilitaire de niveau inférieur qui se prête aux tests unitaires, dans les jeux. C'est bien - c'est le code de base qui pourrait perturber beaucoup de couches supérieures s'il se casse.

Vous n'irez pas au purgatoire du programmeur pour ne pas avoir de tests pour chaque petite fonction et porte logique dans votre base de code, alors ne passez pas plus de temps que nécessaire pour écrire des tests. Si vous devez réfléchir plus longuement ou passer beaucoup plus de temps à rédiger les tests d'un module qu'il ne vous en a fallu pour créer le module, vous perdez peut-être votre temps. Les tests unitaires - les tests en général - sont un outil que vous apprenez à utiliser de manière appropriée pour vous aider, pas une corvée que vous devez effectuer pour tout.


la source
3
If you have to [...] spend significantly more time writing the tests [...] than it took you to author the module... Alors votre module est trop complexe. Simplifiez-le maintenant, vous vous remercierez à l'avenir!
Jess Telford
3
@Jess Un module disproportionnellement difficile à tester n'a pas nécessairement besoin d'être simplifié. Il existe de nombreux domaines où les tests unitaires ne sont tout simplement pas une bonne utilisation du temps. Cela inclut les graphiques, où la sortie peut varier considérablement tout en étant acceptable; code qui ne changera probablement pas à l'avenir; ou code où le type de conception abstraite et découplée qui serait nécessaire pour faciliter les tests unitaires est beaucoup plus laid, plus sujet aux erreurs, moins performant ou moins intuitif.
Casey Rodarmor
@rodarmor - d'accord. Il y a une échelle mobile de ce qui est approprié et de ce qui ne l'est pas. Comme avec tous ces types de réponses, une taille unique ne convient pas à tous :)
Jess Telford
Pour UnitTest ++, accédez à github.com/unittest-cpp/unittest-cpp . Tout le reste est obsolète.
Markus
4

Une «unité» est le plus petit morceau de code testable, généralement une seule fonction ou classe. Un test unitaire est un autre morceau de code qui exerce cette unité de code pour s'assurer qu'il se comporte comme prévu. Une unité de code unique peut avoir de nombreux tests, afin de couvrir tous les cas.

En règle générale, les tests ne sont pas inclus dans la version principale d'un projet. Au lieu de cela, il existe une configuration de génération distincte pour les tests qui inclut tout le code de test et produit un programme qui exécute tous les tests et rapporte les résultats. Un cadre de test fournira tous les échafaudages pour cela et est recommandé, mais pas strictement nécessaire. Si vous êtes totalement nouveau dans les tests, il est préférable de commencer par écrire votre propre banc de test ad hoc, pour vous assurer de comprendre tout ce qui se passe.

Couvrez autant de code que possible avec des tests, en priorisant le code dont vous n'êtes pas sûr ou le code fragile et susceptible d'être rompu par de futurs changements. Vous devez exécuter les tests souvent, idéalement après chaque changement de code.

jedediah
la source