Quel est le côté négatif de votre expérience TDD? Trouvez-vous les petits pas (la solution la plus simple pour rendre le test vert) ennuyeux et inutile? Trouvez-vous des tests sans valeur (lorsque le test a un sens initialement, mais que la mise en œuvre finale vérifie la même logique que les autres tests), la maintenance est-elle critique? etc.
Les questions ci-dessus portent sur des choses avec lesquelles je suis mal à l'aise pendant mon expérience TDD. Je suis donc intéressé à savoir si d'autres développeurs ont des sentiments similaires et ce qu'ils en pensent.
Je serais reconnaissant pour les liens vers des articles décrivant les aspects négatifs de TDD (Google est rempli d'articles positifs et souvent fanatiques).
Réponses:
Comme tout ce qui se trouve sous la bannière "Agile", le TDD est quelque chose qui sonne bien en théorie, mais en pratique, on ne sait pas trop à quel point c'est bon (et comme la plupart des choses "Agiles", on vous dit que si vous ne le faites pas comme tu le fais mal).
La définition de TDD n’est pas gravée dans le marbre: des types comme Kent Beck exigent qu’un test de non-compilation soit écrit avant une seule ligne de code et que chaque ligne de code soit écrite pour réussir un test qui a échoué. La conception à l'avant est minimale et tout est guidépar les tests. Ça ne marche pas. J'ai vu une grande application d'entreprise développée à l'aide de cette méthodologie et j'espère que c'est le code pire que je vois dans ma carrière (ce ne sera pas très loin; malgré le fait que des développeurs talentueux y travaillaient). D'après ce que j'ai vu, il en résulte un grand nombre de tests mal pensés qui vérifient principalement que des appels de fonction se produisent, que des exceptions sont générées lorsque les variables sont nulles et que le cadre moqueur bénéficie d'un entraînement complet (whoop-de-whoop); votre code de production est fortement couplé à ces tests et le rêve d’une refactorisation constante et facile n’apparaît pas - en fait, les gens sont encore moins susceptibles de réparer un code incorrect en raison de tous les tests qu’il va entraîner.
À l'inverse, j'ai entendu des gens dire que TDD signifie concevoir les tests à un niveau élevé dans le cadre de la phase de planification, parallèlement à la conception architecturale. Ces tests peuvent changer au cours du développement à mesure que de nouvelles informations deviennent disponibles, mais ils ont été soigneusement examinés et constituent un bon guide quant à ce que le code devrait réellement faire. Pour moi, cela a du sens.
la source
Cette interview de Rich Hickey ( auteur de Clojure ) contient les éléments suivants. Je me sens à 100% sympathique:
Une autre déclaration similaire de Donald Knuth dans l' interview du livre de Coders at Work, copiée -collée à partir d' ici :
la source
Mon expérience négative avec TDD a été la première. TDD me semblait formidable, je faisais de l'assurance qualité depuis des années et j'avais encore les horreurs à l'esprit. Je voulais écraser chaque bogue avant qu'il ne devienne une version. Malheureusement, l'utilisation de TDD ne garantit pas que vous passerez de bons tests. En fait, ma prédisposition initiale était d'écrire des tests simples générant du code simple. Code vraiment simple qui contient peu d'abstractions. Des tests très simples, étroitement liés aux éléments internes de la classe. Et une fois que vous avez mis en place quelques milliers de tests itty bitty, vous n’avez sûrement pas l’impression que vous agissez plus rapidement lorsque vous devez en modifier une centaine pour refactoriser votre code afin d’utiliser le très important concept de domaine X.
La lumière s'est allumée pour moi - TDD n'est pas une compétence de test. C'est une compétence de conception. Cela ne peut que vous amener à un code bon, simple, exploitable, avec de la pratique et une conscience constante des instructions de conception dans lesquelles il vous conduit. Si vous écrivez des tests dans un souci de couverture de code, vous allez créer des tests fragiles. Si vous écrivez des tests pour vous aider à concevoir vos abstractions, c'est simplement une manière plus rigoureuse d'écrire du code descendant. Vous commencez par voir le code du point de vue de l'appelant, ce qui vous encourage à lui simplifier la vie, plutôt que de refléter les éléments internes d'une classe sur son bord extérieur.
Je pense que TDD est utile, mais je ne suis pas dogmatique à ce sujet. Si ces "tests sans valeur" rendent la maintenance difficile, supprimez-les! Je traite les tests de la même manière que le reste du code. Si cela peut être refait et simplifier les choses, alors faites-le!
Je ne l'ai pas vu personnellement, mais j'ai entendu dire que certains endroits font le suivi de la couverture du code et du nombre de tests. Donc, si la collecte de métriques est un effet secondaire du TDD, je pourrais aussi voir cela comme un effet négatif. Je supprimerai avec enthousiasme 1000 lignes de code, et si cela rend obsolètes 20 tests et abandonne ma couverture de code%, eh bien.
la source
Je vais me laisser aller ici et déclarer avec une brutale honnêteté que c'est littéralement une perte de temps rituelle. (Dans la majorité des situations.)
J'ai acheté un livre sur les tests unitaires qui traitait également du TDD. Bien que je sois d'accord avec les avantages de l'UT, après environ cent heures de test du TDD, j'ai abandonné le logiciel pour une multitude de raisons. Je suis un peu en train de poster ici, mais TDD:
Une autre préoccupation est le degré de perfection discuté auquel on doit faire TDD pour le faire avec succès. Certains insistent sur le fait que si le TDD n'est pas appliqué de manière persistante par tous les membres de l'équipe dès le début du projet, vous n'en souffrirez que. D'autres insistent sur le fait que personne ne fait jamais TDD à la livre. Si ces deux éléments sont vrais, il s'ensuit que les praticiens du TDD souffrent, qu'ils s'en rendent compte ou non.
Bien sûr, si on fait valoir qu'en faisant les choses comme à TDD, on arrivera à des conceptions qui fonctionnent facilement avec TDD, eh bien, il existe des moyens beaucoup plus rapides pour y parvenir - à savoir, en étudiant réellement les concepts de composabilité. Il y a beaucoup de ressources, beaucoup de théorie mathématique rigoureuse même (principalement dans la programmation fonctionnelle mais aussi dans d'autres domaines). Pourquoi ne pas passer tout votre temps à apprendre ?
Culturellement, le TDD présente les symptômes d’une pratique rituelle. Il monte sur la culpabilité; cela encourage la procédure par rapport à la compréhension; il contient des tonnes de doctrines et de slogans ("simulez-le jusqu'à ce que vous le fassiez" est vraiment alarmant si vous le regardez de manière objective). La définition du mot "rituel" par Wikipedia est en fait assez pertinente:
la source
Pour ajouter, un autre problème avec TDD que j'ai remarqué est:
TDD provoque un déplacement par inadvertance de l’attention de l’ équipe de développement du Code Qualité vers les Cas de Test et la Couverture de Code! Personnellement, je n'aimais pas le TDD car cela me rend moins créatif et rend le développement logiciel un processus mécanique ennuyeux ! Les unités de test unitaires sont utiles lorsqu'elles sont utilisées judicieusement, mais deviennent un fardeau lorsqu'elles sont traitées comme un objectif du développement logiciel.
Je connais un gars qui est un manager et techniquement ennuyeux, une fois obsédé par le TDD. C'était une chose tellement magique pour lui qu'il pensait apporter des solutions magiques à tous les problèmes de son logiciel mal architecturé avec du code le moins maintenable. Pour ne pas dire ce qui est arrivé à ce projet, il a lamentablement échoué entre ses mains, alors que tous ses tests étaient verts. J'imagine que TDD l'a aidé à obtenir des informations statistiques telles que "99/100 de mes cas sont verts", etc.
la source
Mon expérience négative principale consiste à utiliser TDD pour éditer le code d'un autre programmeur n'ayant pas de test, ou des tests d'intégration très basiques. Lorsque je vais ajouter une fonctionnalité ou résoudre un problème avec ledit code; Je préférerais d'abord écrire un test (à la manière de TDD). Malheureusement, le code est étroitement lié et je ne peux rien tester sans beaucoup de refactoring.
La refactorisation est quand même un bon exercice, mais il est nécessaire d’obtenir le code dans un état vérifiable. Et après cette étape, je n’ai plus de freins et contrepoids pour voir si mes changements ont brisé quoi que ce soit; à court d'exécuter l'application et d'examiner chaque cas d'utilisation.
D'autre part, l'ajout de fonctionnalités / la correction de bugs à un projet TDD devient très simple. Par nature, le code écrit avec TDD est généralement assez découplé avec de petits morceaux avec lesquels travailler.
Dans tous les cas, le TDD est une ligne directrice. Suivez-le jusqu'à ce que vous obteniez une efficacité maximale. Couverture de test décente et code découplé, code bien écrit.
la source
Je me suis rendu compte que parfois je me fie trop à mes tests pour concevoir le système. Je suis fondamentalement trop faible dans les détails de la mise en œuvre pour pouvoir prendre le recul pour regarder la situation dans son ensemble. Cela aboutit souvent à une conception inutilement complexe. Je sais que je suis censé refacturer le code, mais j'ai parfois l'impression de pouvoir gagner beaucoup de temps en prenant le pas en arrière plus souvent.
Cela étant dit, si vous avez un cadre tel que des rails où vos décisions architecturales sont très limitées, ces problèmes sont pratiquement inexistants.
Un autre problème est que vous faites confiance à vos tests aveuglément. La vérité est - comme tout autre code - vos tests peuvent aussi avoir des bugs. Soyez donc aussi critique vis-à-vis de vos tests que de votre implémentation.
la source
En tant que grand fan de TDD, je vois parfois ces inconvénients
Les coûts de maintenance du code de test pour des tests similaires, qui ne varient que légèrement (créés par la duplication de code (aka copier-coller-héritage)). Si vous en avez déjà un, il est facile d'en créer un similaire. Mais si vous ne refactorisez pas le code de test, en éliminant la duplication de code en méthodes d'assistance, vous aurez peut-être besoin de temps pour corriger les tests si les détails d'implémentation de votre code métier changent.
Si vous êtes pressé par le temps, vous pourriez être tenté d' éliminer les tests cassés (ou de les commenter) au lieu de les corriger . De cette façon, vous perdez l'investissement dans les tests
la source
En tant que développeur de jeux, je n'ai pas encore rencontré plus d'un scénario où TDD en valait la peine. Et l'instance dans laquelle il s'agissait était un morceau de code qui était de nature purement mathématique et qui nécessitait une approche solide pour tester simultanément un très grand nombre de cas extrêmes - un besoin rare.
Peut-être que quelque chose, un jour, changera d’idée, mais parmi les pratiques de XP, l’idée de refactoriser impitoyablement , et de faire évoluer le code de sa propre forme est bien plus importante et conduit à la plus grande productivité pour moi, cf. une citation d' un article de James Newkirk :
Les concepts de courage et de resserrement des boucles de rétroaction qu'il mentionne sont également, à mon sens, la clé de la productivité.
la source
Mon expérience négative de TDD, aussi limitée soit-elle, est simplement de savoir par où commencer! Par exemple, je vais essayer de faire quelque chose TDD et soit ont aucune idée où commencer sauf tester des choses insignifiantes (puis - je new un
Foo
objet, puis - je passer dansQuux
laBaz
, et autres. Les tests qui ne teste rien ), ou si je tente de l’implémenter dans un projet existant, j’aperçois qu’il me faudrait réécrire diverses classes pour pouvoir les utiliser dans TDD. Le résultat final est que j'abandonne rapidement la notion.Cela n'aide probablement pas si souvent que je suis la seule personne dans toute l'entreprise à savoir ce qu'est le test unitaire (TDD ou autre) et pourquoi c'est une bonne chose.
la source
Foo
avec Mock objets plutôt queQuux
etBaz
directement, vous pouvez appeler la fonction que vous voulez tester et vérifier que les simulacres ont été appelés avec les fonctions que vous attendez. Les objets factices constituent la technologie habilitante qui permet de découpler les unités et de les rendre testables. C'est pourquoi les singletons sont diaboliques, car vous ne pouvez souvent pas simplement vous moquer d' eux. * 8 ')Fanatiques de TDD.
Pour moi, ils ne sont que l'une des nombreuses lignées religieuses qui frappent à ma porte, essayant de prouver que ma façon de faire les choses est irrémédiablement brisée et que l'unique voie vers le salut est Jésus, Kent Back ou Unit Testing.
OMI, leur plus grand mensonge est que TDD vous mènera au
salut d'un meilleur design d'algorithme. Voir le célèbre solveur Soduku écrit en TDD: ici , ici , ici , ici et iciEt comparez le résolveur de sudoku Peter Norvig fait non pas en utilisant TDD, mais en utilisant une ingénierie à l'ancienne: http://norvig.com/sudoku.html
la source
Si vous utilisez TDD à partir de ces articles "fanatiques", vous aurez le sentiment que votre logiciel ne contient aucune erreur.
la source
TDD présente certains avantages:
TDD est un investissement à long terme. L'effort est rentable lorsque vous atteignez le mode de maintenance de votre application. Si l'application n'est pas planifiée pour atteindre ce point, vous ne pourrez jamais récupérer l'investissement.
Je considère le cycle rouge-vert du TDD avec les étapes de bébé comme une liste de contrôle pour un avion. Il est ennuyeux et fastidieux de vérifier chaque élément de l'avion avant le décollage, en particulier s'il est trivialement simple (les marches du TDD), mais il a été constaté qu'il accroît la sécurité. En plus de vérifier que tout fonctionne, il réinitialise essentiellement l'avion . En d'autres termes, un avion est redémarré avant chaque décollage.
la source
Mon expérience négative à propos du TDD est quelque chose que je ressens avec beaucoup de choses nouvelles et excitées. En fait, j'apprécie TDD car cela garantit la validité de mon code, et plus important encore: je peux reconnaître les tests ayant échoué après avoir ajouté un nouveau code ou n’importe quel type de refactoring.
Ce qui m'agace chez TDD, c'est qu'il y a beaucoup de règles ou de directives à ce sujet. Comme il est encore relativement nouveau, nous avons pour la plupart d’entre nous des débutants au TDD. Donc, ce qui fonctionne bien pour certains d’entre nous pourrait ne pas fonctionner pour d’autres. Ce que je veux dire, c’est qu’il n’existe pas vraiment de manière «fausse ou correcte» d’exécuter le TDD: c’est ce qui fonctionne pour moi - et mon équipe si j’en ai une.
Donc tant que vous écrivez des tests - avant ou après le code de production n'a pas d'importance IMHO - je ne suis pas sûr si piloté par les tests signifie vraiment que vous devez suivre toutes les directives qui sont énoncées en ce moment, car elles ne sont pas encore prouvées. la solution idéale pour le travail quotidien. Si vous trouvez un meilleur moyen d'écrire des tests, vous devez le publier sur un blog, en discuter ici ou écrire un article à ce sujet. Donc, dans dix ans environ, nous aurions peut-être partagé suffisamment d'expérience pour pouvoir déterminer quelle règle de TDD peut être considérée comme bonne ou non dans certaines situations.
la source
À plusieurs reprises, j’ai écrit un code que j’ai défait le lendemain, car il était maladroit. J'ai redémarré avec TDD et la solution était meilleure. Donc, je n'ai pas trop vécu l'expérience négative du TDD. Cependant, cela étant dit, j'ai passé du temps à réfléchir à un problème et à proposer une meilleure solution en dehors de l'espace TDD.
la source
J'ai constaté que le TDD fonctionne mal en ce qui concerne les systèmes émergents. Développeur de jeux vidéo, j'ai récemment utilisé TDD pour créer un système qui utilise plusieurs comportements simples afin de créer un mouvement réaliste pour une entité.
Par exemple, il existe des comportements qui vous obligent à vous éloigner de zones dangereuses de types différents et des comportements qui vous obligent à vous diriger vers des zones intéressantes de types différents. La fusion de la sortie de chaque comportement crée un mouvement final.
Les entrailles du système ont été mises en œuvre facilement, et TDD a été utile ici pour spécifier la responsabilité de chaque sous-système.
Cependant, j'ai eu des problèmes pour préciser comment les comportements interagissaient et, plus important encore, comment ils interagissaient au fil du temps. Souvent, il n’y avait pas de bonne réponse, et bien que mes tests initiaux aient été concluants, le contrôle de la qualité pouvait continuer à trouver des cas extrêmes dans lesquels le système ne fonctionnait pas. Pour trouver la bonne solution, je devais parcourir plusieurs comportements différents, et si je mettais à jour les tests chaque fois pour refléter les nouveaux comportements avant de vérifier qu'ils fonctionnaient dans le jeu, j'aurais peut-être fini par les rejeter à maintes reprises. J'ai donc supprimé ces tests.
J'aurais peut-être dû subir des tests plus rigoureux prenant en compte les cas critiques QA découverts, mais lorsque vous avez un système comme celui-ci qui repose sur de nombreux systèmes de jeu et de physique, et que vous traitez des comportements au fil du temps, cela devient un peu un problème. cauchemar pour spécifier exactement ce qui se passe.
J'ai presque certainement commis des erreurs dans mon approche et, comme je l'ai dit pour les entrailles du système, TDD a fonctionné de manière brillante et a même pris en charge quelques refacteurs d'optimisation.
la source