Dans mon projet actuel (un jeu, en C ++), j'ai décidé d'utiliser Test Driven Development 100% pendant le développement.
En termes de qualité de code, cela a été formidable. Mon code n'a jamais été aussi bien conçu ni aussi sans bug. Je ne grince pas quand je lis le code que j'ai écrit il y a un an au début du projet et j'ai maintenant beaucoup mieux compris comment structurer les choses, non seulement pour être plus facilement testable, mais pour être plus simple à implémenter et à utiliser .
Cependant ... cela fait un an que j'ai commencé le projet. Certes, je ne peux y travailler que pendant mon temps libre, mais le TDD me ralentit encore considérablement par rapport à ce que je suis habitué. J'ai lu que la vitesse de développement plus lente s'améliorait avec le temps, et je pense vraiment aux tests beaucoup plus facilement qu'auparavant, mais je le fais depuis un an et je travaille toujours au pas de l'escargot.
Chaque fois que je pense à la prochaine étape qui nécessite du travail, je dois m'arrêter à chaque fois et réfléchir à la manière dont j'écrirais un test pour lui permettre d'écrire le code lui-même. Je suis parfois bloqué pendant des heures, sachant exactement quel code je veux écrire, mais ne sachant pas le décomposer assez finement pour le couvrir complètement avec des tests. D'autres fois, j'imagine rapidement une douzaine de tests et passe une heure à rédiger des tests pour couvrir un minuscule morceau de code qui, autrement, aurait pris quelques minutes à écrire.
Ou, après avoir terminé le 50ème test pour couvrir une entité particulière du jeu et tous les aspects de sa création et de son utilisation, je regarde ma liste de tâches à faire et vois la prochaine entité à coder et grincant de peur à l'idée d'écrire 50 autres tests similaires pour le mettre en œuvre.
Nous en sommes arrivés au point où, considérant les progrès de l’année écoulée, j’envisage d’abandonner le TDD dans le but de "terminer ce foutu projet". Cependant, abandonner la qualité du code qui l'accompagne n'est pas quelque chose que je suis impatient de voir. Je crains que si j'arrête d'écrire des tests, alors je ne prendrai pas l'habitude de rendre le code aussi modulaire et testable.
Suis-je peut-être en train de faire quelque chose de mal pour être toujours aussi lent à ça? Existe-t-il des alternatives qui accélèrent la productivité sans perdre complètement les avantages? TAD? Moins de couverture de test? Comment les autres personnes survivent-elles au TDD sans nuire à la productivité et à la motivation?
la source
Réponses:
Permettez-moi de commencer par vous remercier de partager votre expérience et d'exprimer vos préoccupations ... ce que je dois dire, ce n'est pas inhabituel.
Et cela m'amène à la dernière question: comment puis-je aller mieux? Ma réponse (ou réponse) est Lecture, réflexion et pratique.
Par exemple, dernièrement, je garde un œil sur
la source
Vous n'avez pas besoin d'une couverture de test de 100%. Soyez pragmatique.
la source
a = x + y
et bien que toutes les lignes du code aient été exécutées lors de tests, les tests n'ont été testés que dans le cas où y = 0, de sorte que le bogue (il aurait dû l'êtrea = x - y
) n'a jamais été trouvé dans les tests.C'est en fait faux.
Sans TDD, vous passez quelques semaines à écrire du code qui fonctionne généralement et passez l'année suivante à "tester" et à corriger beaucoup (mais pas tous) des bogues.
Avec TDD, vous passez une année à écrire du code qui fonctionne réellement. Vous effectuez ensuite les tests d'intégration finaux pendant quelques semaines.
Le temps écoulé sera probablement le même. Le logiciel TDD sera nettement de meilleure qualité.
la source
Cela me fait me demander combien de temps vous suivez l'étape "Refactor" de TDD.
Lorsque tous vos tests sont réussis, il est temps de refactoriser le code et de supprimer les doublons. Bien que les gens se souviennent généralement de cela, ils oublient parfois qu'il est également temps de refactoriser leurs tests , de supprimer les doublons et de simplifier les choses.
Si vous avez deux entités qui fusionnent en une seule pour permettre la réutilisation du code, envisagez également de fusionner leurs tests. Vous n'avez vraiment besoin que de tester les différences incrémentielles dans votre code. Si vous n'effectuez pas régulièrement la maintenance de vos tests, ceux-ci peuvent rapidement devenir difficiles à manier.
Quelques points philosophiques sur le TDD qui pourraient être utiles:
EDIT: Au sujet de la philosophie des tests unitaires, je pense que cela pourrait vous intéresser de lire: The Way of Testivus
Et un point plus pratique, sinon nécessairement très utile:
la source
Question très intéressante.
Ce qui est important à noter, c’est que le C ++ n’est pas très facile à tester et que le jeu, en général, est également un très mauvais candidat pour le TDD. Vous ne pouvez pas tester si OpenGL / DirectX dessine facilement un triangle rouge avec le pilote X et jaune avec le pilote Y. Si le vecteur normal de la texture en relief n'est pas inversé après la transformation du shader. Vous ne pouvez pas non plus tester les problèmes de découpage sur les versions de pilotes avec des précisions différentes, etc. Un comportement de dessin non défini en raison d'appels incorrects ne peut également être testé qu'avec une vérification précise du code et du SDK. Le son est également un mauvais candidat. Le multithreading, qui est encore une fois assez important pour les jeux, est pratiquement inutile pour les tests unitaires. Donc c'est dur.
Fondamentalement, le jeu comporte beaucoup d’interfaces graphiques, de sons et de threads. L'interface graphique, même avec des composants standard auxquels vous pouvez envoyer WM_, est difficile à tester.
Donc, ce que vous pouvez tester, ce sont les classes de chargement de modèle, les classes de chargement de texture, les bibliothèques de matrices et autres, ce qui n’est pas beaucoup de code et, bien souvent, pas très réutilisable, si ce n’est que votre premier projet. En outre, ils sont regroupés dans des formats propriétaires. Il est donc peu probable que les entrées de tierces parties diffèrent beaucoup, sauf si vous publiez des outils de modification, etc.
Là encore, je ne suis ni un gourou ni un évangéliste du TDD, alors prenez tout cela avec un grain de sel.
J'écrirais probablement des tests pour les principaux composants principaux (par exemple, une bibliothèque de matrices, une bibliothèque d'images). Ajouter un tas d'
abort()
entrées inattendues dans chaque fonction. Et surtout, concentrez-vous sur un code résistant / résilient qui ne casse pas facilement.En ce qui concerne les erreurs off-one, l'utilisation intelligente de C ++, RAII et d'une bonne conception est un moyen efficace de les éviter.
En gros, il vous reste beaucoup à faire pour couvrir les bases si vous voulez sortir le jeu. Je ne suis pas sûr si TDD aidera.
la source
Je suis d'accord avec les autres réponses, mais je souhaite également ajouter un point très important: les coûts de refactoring !!
Avec des tests unitaires bien écrits, vous pouvez réécrire votre code en toute sécurité. Premièrement, des tests unitaires bien rédigés fournissent une excellente documentation sur l'intention de votre code. Deuxièmement, tous les effets secondaires malheureux de votre refactoring seront pris en compte par la suite de tests existante. Ainsi, vous avez garanti que les suppositions de votre ancien code sont également vraies pour votre nouveau code.
la source
C'est complètement différent de mes expériences. Vous êtes incroyablement intelligent et écrivez du code sans bogues (par exemple, une erreur) ou vous ne réalisez pas que votre code contient des bogues qui empêchent votre programme de fonctionner et qui ne sont donc pas terminés.
TDD consiste à avoir l’humilité de savoir que vous (et moi!) Commettez des erreurs.
Pour moi, le temps d'écriture avec unittests est bien plus qu'un gain de temps de débogage réduit pour les projets réalisés depuis le début avec TDD.
Si vous ne faites pas d'erreur, alors peut-être que TDD n'est pas aussi important pour vous que pour moi!
la source
Je n'ai que quelques remarques:
Il semble que vous essayez de tout tester . Vous ne devriez probablement pas, juste les cas à haut risque et les cas extrêmes d'un morceau de code / méthode particulier. Je suis à peu près sûr que la règle des 80/20 s'applique ici: vous passez 80% de votre temps à écrire des tests pour les 20% restants de votre code ou des cas qui ne sont pas couverts.
Prioriser. Lancez-vous dans le développement logiciel agile et dressez une liste de ce que vous devez vraiment faire pour sortir dans un mois. Puis relâchez, juste comme ça. Cela vous fera penser à la priorité des fonctionnalités. Ouais, ce serait cool si votre personnage pouvait faire un backflip, mais a-t-il une valeur commerciale ?
TDD est bon, mais seulement si vous ne visez pas une couverture de test à 100%, et non pas si cela vous empêche de générer de la valeur commerciale réelle (c'est-à-dire des fonctionnalités, des éléments qui ajoutent quelque chose à votre jeu).
la source
Oui, l'écriture de tests et de code peut prendre plus de temps que d'écrire du code - mais écrire du code et des tests unitaires associés (à l'aide de TDD) est beaucoup plus prévisible que d'écrire du code et de le déboguer.
Le débogage est presque éliminé lors de l'utilisation de TDD - ce qui rend tous les processus de développement beaucoup plus prévisibles et finalement plus rapides - sans doute.
Refactorisation constante - il est impossible de procéder à une refactorisation sérieuse sans une suite complète de tests unitaires. Le moyen le plus efficace de construire ce filet de sécurité basé sur les tests unitaires est la période de TDD. Un code bien refactorisé améliore de manière significative la productivité globale du concepteur / de l’équipe qui gère le code.
la source
Pensez à réduire la portée de votre jeu et à le placer là où quelqu'un peut le jouer ou le relâcher. Maintenir vos normes de test sans attendre trop longtemps avant de publier votre jeu pourrait être un moyen terme pour rester motivé. Les commentaires de vos utilisateurs peuvent offrir des avantages à long terme et vos tests vous permettent de vous sentir à l'aise avec les ajouts et les modifications.
la source