Le cycle Rouge - Vert - Refactor pour TDD est bien établi et accepté. Nous écrivons un test unitaire en échec et le faisons passer aussi simplement que possible. Quels sont les avantages de cette approche par rapport à l'écriture de nombreux tests unitaires échouant pour une classe et à leur exécution simultanée?
La suite de tests vous protège toujours contre l'écriture de code incorrect ou les erreurs de refactoring, alors quel est le problème? Parfois, il est plus facile d'écrire d'abord tous les tests d'une classe (ou d'un module) sous forme de «vidage de cerveau» pour consigner rapidement tous les comportements attendus en une seule fois.
Réponses:
La conception pilotée par les tests consiste à obtenir votre API correcte, pas le code.
L’écriture des tests échoués les plus simples a pour avantage d’avoir votre API (que vous concevez à la volée) aussi simple que possible. À l'avant.
Toutes les utilisations futures (qui sont les prochains tests que vous écrivez) iront de la conception simple initiale au lieu d’une conception sous-optimale prenant en charge des cas plus complexes.
la source
Lorsque vous écrivez un test, vous vous concentrez sur une chose.
Avec de nombreux tests, vous étalez votre attention sur de nombreuses tâches. Ce n'est donc pas une bonne idée.
la source
L'une des difficultés rencontrées lors de l'écriture de tests unitaires est que vous écrivez du code, ce qui en soi peut être sujet à des erreurs. Il est également possible que vous deviez éventuellement avoir besoin de modifier vos tests ultérieurement à la suite d'un effort de refactoring lors de l'écriture de votre code d'implémentation. Avec TDD, cela signifie que vous risquez de vous perdre un peu trop avec vos tests et de constater que vous-même avez besoin de réécrire beaucoup de code de test essentiellement "non testé" à mesure que votre implémentation évolue au cours du projet. Une façon d'éviter ce genre de problème est simplement de se concentrer sur une seule chose à la fois. Cela vous assure de minimiser l'impact de tout changement sur vos tests.
Bien sûr, cela dépend en grande partie de la façon dont vous écrivez votre code de test. Rédigez-vous un test unitaire pour chaque méthode ou rédigez-vous des tests axés sur les fonctionnalités / exigences / comportements? Une autre approche pourrait consister à utiliser une approche axée sur le comportement avec un cadre approprié et à se concentrer sur la rédaction de tests comme s'il s'agissait de spécifications. Cela impliquerait soit d'adopter la méthode BDD, soit d'adapter le test BDD si vous souhaitez vous en tenir à la TDD de manière plus formelle. Sinon, vous pouvez vous en tenir entièrement au paradigme TDD, tout en modifiant la façon dont vous écrivez les tests afin qu'au lieu de vous concentrer uniquement sur les méthodes de test, vous testez les comportements de manière plus générale afin de satisfaire les spécificités des fonctionnalités que vous implémentez.
Indépendamment de l’approche spécifique que vous prenez, dans tous les cas que j’ai décrits ci-dessus, vous utilisez une approche test d’abord; alors, même si vous tentez de télécharger simplement votre cerveau dans une suite de tests ravissante, vous souhaitez également tentation de faire plus que ce qui est absolument nécessaire. Chaque fois que je suis sur le point de démarrer une nouvelle suite de tests, je commence à répéter YAGNI et parfois même à l'insérer dans un commentaire dans mon code afin de me rappeler de rester concentré sur ce qui est immédiatement important et de ne faire que le minimum exigences de la fonctionnalité que je suis sur le point d'implémenter. S'en tenir à Red-Green-Refactor aide à s'assurer que vous le ferez.
la source
Je pense qu'en faisant cela, vous ratez le processus du TDD. En écrivant simplement tous vos tests au début, vous ne suivez pas vraiment le processus de développement utilisant TDD. Vous devinez simplement quels tests vous aurez besoin. Ce sera un ensemble de tests très différent de ceux que vous finirez par écrire si vous les exécutez un par un au fur et à mesure que vous développez votre code. (À moins que votre programme ne soit de nature triviale.)
la source
Je «écris» tous les tests auxquels je peux penser dès le départ en «assaillant», mais j’écris chaque test sous la forme d’un commentaire décrivant celui-ci.
Je convertis ensuite un test en code et effectue le travail pour qu'il se compile et passe . Souvent, je décide que je n'ai pas besoin de tous les tests que je pensais avoir, ou que j'ai besoin de tests différents, cette information provient uniquement de l'écriture du code permettant de réussir les tests.
Le problème est que vous ne pouvez pas écrire de test dans le code tant que vous n'avez pas créé la méthode et les classes qu'il teste. Sinon, vous obtiendrez beaucoup d'erreurs du compilateur qui vous empêcheraient de travailler sur un seul test à la fois.
Maintenant, si vous utilisez un système tel que spec flow lorsque les tests sont écrits en «anglais», vous voudrez peut-être que les clients acceptent un ensemble de tests tant que vous en avez le temps, plutôt que de créer un seul test.
la source
L'idée derrière TDD est des itérations rapides.
Si vous avez un grand nombre de tests à écrire avant d'écrire votre code, il est difficile de refactoriser votre code de manière itérative.
Sans une refactorisation facile du code, vous perdez beaucoup des avantages de TDD.
la source
Grâce à mon expérience (limitée) avec le TDD, je peux vous dire que chaque fois que j'ai enfreint la discipline consistant à écrire un test à la fois, les choses se sont mal passées. C'est un piège facile à tomber. "Oh, cette méthode est triviale", vous vous dites, "alors je vais assommer ces deux autres tests et continuer à avancer." Bien devinez quoi? Rien n'est aussi trivial qu'il n'y paraît. Chaque fois que je suis tombé dans ce piège, je finissais par déboguer quelque chose que je trouvais facile, mais qui comportait des cas étranges. Et depuis que j'avais écrit plusieurs tests à la fois, c’était beaucoup de travail de localiser le bogue.
Si vous avez besoin d'une masse d'informations, vous avez beaucoup d'options:
Notez que le compilateur ne figure nulle part sur cette liste. :-)
la source
Vous supposez que vous savez à quoi ressemblera votre code avant de l'écrire. TDD / BDD est autant un processus de conception / découverte qu’un processus d’assurance qualité. Pour une fonctionnalité donnée, vous écrivez le test le plus simple permettant de vérifier que la fonctionnalité est satisfaite (cela peut parfois nécessiter plusieurs tests en raison de la complexité d'une fonctionnalité). Le premier test que vous écrivez est chargé avec des hypothèses sur l’aspect du code de travail. Si vous écrivez l'intégralité de la suite de tests avant d'écrire la première ligne de code pour la prendre en charge, vous formulez une litanie d'hypothèses non vérifiées. Au lieu de cela, écrivez une hypothèse et vérifiez-la. Puis écris le suivant. Lors du processus de vérification de la prochaine hypothèse, vous pouvez simplement casser une hypothèse antérieure. Vous devez donc revenir en arrière et changer cette première hypothèse pour qu'elle corresponde à la réalité ou la changer pour que la première hypothèse s'applique toujours.
Pensez à chaque test unitaire que vous écrivez comme une théorie dans un cahier scientifique. En remplissant le cahier, vous confirmez vos théories et en formez de nouvelles. Parfois, prouver une nouvelle théorie contredit une théorie antérieure, il faut donc la corriger. Il est plus facile de prouver une théorie à la fois plutôt que d'essayer de prouver 20 à la fois.
la source
TDD est une approche hautement itérative, qui (selon mon expérience) correspond mieux aux modes de développement du monde réel. Habituellement, ma mise en œuvre prend forme progressivement au cours de ce processus, et chaque étape peut amener de nouvelles questions, idées et idées à tester. Ceci est idéal pour garder mon esprit concentré sur la tâche réelle et est très efficace car je n'ai besoin que de garder un nombre limité de choses dans la mémoire à court terme à tout moment. Cela réduit la possibilité d'erreurs.
Votre idée est fondamentalement une approche Big Test Up Front, qui est plus difficile à gérer à mon humble avis et peut devenir une source de gaspillage. Et si vous réalisiez à mi-parcours de votre travail que votre approche n’est pas bonne, que votre API est défectueuse et que vous devez tout recommencer ou utiliser une bibliothèque tierce à la place? Ensuite, une grande partie du travail consacré à la rédaction de vos tests devient un effort inutile.
Cela dit, si cela fonctionne pour vous, bien. J'imagine que si vous travaillez à partir d'une spécification technique précise et détaillée, dans un domaine dans lequel vous êtes intimement familiarisé et / ou dans une tâche relativement petite, vous pouvez disposer de la plupart ou de la totalité des scénarios de test nécessaires et clarifier votre mise en œuvre dès la le début. Ensuite, il pourrait être judicieux de commencer par écrire tous les tests à la fois. Si votre expérience montre que cela vous rend plus productif à long terme, vous n'avez pas à vous soucier de la réglementation :-)
la source
Au-delà du simple fait de penser à une chose, l'un des paradigmes de TDD consiste à écrire le moins de code possible pour réussir le test. Lorsque vous écrivez un test à la fois, il est beaucoup plus facile de savoir comment écrire suffisamment de code pour que ce test réussisse. Avec toute une série de tests à réussir, vous n’allez pas au code par petites étapes, mais vous devez faire un grand saut pour les faire passer en une fois.
Maintenant, si vous ne vous limitez pas à écrire le code pour les faire passer tous «d'un coup», mais écrivez plutôt juste assez de code pour passer un test à la fois, cela pourrait quand même fonctionner. Cependant, il vous faudrait plus de discipline pour ne pas écrire et écrire plus de code que nécessaire. Une fois que vous commencez dans cette voie, vous vous permettez d'écrire plus de code que ne le décrivent les tests, ce qui peut ne pas être testé , du moins dans le sens où il n'est pas piloté par un test et peut-être même dans le sens où il n'est pas nécessaire. (ou exercé) par tout test.
Décrire ce que la méthode devrait faire, sous forme de commentaires, d'histoires, de spécifications fonctionnelles, etc., est parfaitement acceptable. J'attendrais cependant de les traduire en tests un à la fois.
L'autre chose que vous pouvez manquer en écrivant les tests en une seule fois est le processus de réflexion selon lequel le passage d'un test peut vous inciter à penser à d'autres cas de test. Sans une banque de tests existants, vous devez penser au prochain cas de test dans le contexte du dernier test de réussite. Comme je l'ai dit, avoir une bonne idée de ce que la méthode est censée faire est très bon, mais plusieurs fois je me suis trouvé à trouver de nouvelles possibilités que je n'avais pas envisagées à priori, mais qui ne se sont produites qu'au cours de l'écriture du texte. tests. Vous risquez de ne pas les voir, à moins que vous ne preniez l'habitude de penser aux nouveaux tests que je peux écrire et que je n'ai pas encore.
la source
J'ai travaillé sur un projet dans lequel les développeurs qui ont écrit les tests (qui échouaient) étaient différents de ceux qui implémentaient le code nécessaire pour les faire passer et je l'ai trouvé vraiment efficace.
Dans ce cas, seuls les tests liés à l'itération actuelle ont été écrits une fois. Donc, ce que vous suggérez est parfaitement possible dans ce genre de scénario.
la source
la source
Le cycle Red-Green-Refactor est une liste de contrôle destinée aux développeurs novices en TDD. Je dirais que c'est une bonne idée de suivre cette liste de contrôle jusqu'à ce que vous sachiez quand et où vous pouvez la suivre (c'est-à-dire, jusqu'à ce que vous ne soyez pas obligé de poser cette question sur stackoverflow :)
Ayant suivi TDD pendant près de 10 ans, je peux vous affirmer que j’écris rarement, voire jamais, de nombreux tests avant d’écrire du code de production.
la source
Vous décrivez BDD, où une partie prenante externe a une spécification exécutable. Cela peut être avantageux s'il existe une spécification initiale prédéterminée (par exemple, une spécification de format, une norme industrielle ou si le programmeur n'est pas l'expert du domaine).
L’approche normale consiste alors à couvrir progressivement de plus en plus de tests d’acceptation, ce qui correspond à la progression visible du chef de projet et du client.
Vous avez généralement ces tests spécifiés et exécutés dans un framework BDD tel que Cucumber, Fitnesse ou autre.
Cependant, ce n'est pas quelque chose que vous mélangez avec vos tests unitaires, qui sont beaucoup plus proches des détails de mise en œuvre de Nitty Gritty avec beaucoup de cas de pointe liées à l'API, les problèmes d'initialisation etc fortement concentrés sur l' objet sous test , qui est un artefact de mise en œuvre .
La discipline rouge-vert-refactor comporte de nombreux avantages, et le seul avantage que vous pouvez espérer en les tapant à l’avant est d’atteindre le seuil de rentabilité.
la source
Un test à la fois: le principal avantage est de se concentrer sur une chose. Pensez à la conception qui privilégie la profondeur: vous pouvez aller en profondeur et rester concentré avec une boucle de rétroaction rapide. Vous risquez cependant de manquer l'étendue du problème! C'est le moment (le grand) refactoring entre en jeu. Sans cela, le TDD ne fonctionne pas.
Tous les tests: l'analyse et la conception peuvent vous révéler plus de la portée du problème. Pensez à la conception d'abord large. Vous analysez le problème sous plusieurs angles et ajoutez des données d'expérience. C'est intrinsèquement plus difficile, mais peut générer des avantages intéressants - moins de refactorisation - si vous en faites «juste assez». Méfiez-vous, il est facile de sur-analyser et de rater complètement la cible!
Je trouve difficile de recommander généralement de préférer l'un ou l'autre, car les facteurs sont nombreux: expérience (surtout avec le même problème), connaissances et compétences du domaine, convivialité du code de refactorisation, complexité du problème ...
J'imagine que si nous nous focalisions plus étroitement sur les applications métier classiques, alors TDD avec son approche de test rapide et d'erreur la plus rapide en terme d'efficacité serait de gagner.
la source
En supposant que votre infrastructure de test le supporte, je suggérerais qu'au lieu d' implémenter les tests que vous voulez braindump, écrivez plutôt des tests descriptifs en attente que vous implémenterez plus tard. Par exemple, si votre API doit faire foo and bar mais pas biz, ajoutez simplement le code suivant (cet exemple est en rspec) pour votre suite de tests, puis attaquez-les un par un. Vous obtenez vos idées rapidement et pouvez résoudre tous vos problèmes, un par un. Lorsque tous les tests seront réussis, vous saurez quand vous aurez résolu tous les problèmes que vous avez rencontrés pendant votre braindump.
la source