Le développement piloté par les tests (TDD) a-t-il réellement profité à un projet du monde réel?

36

Je ne suis pas nouveau en codage. Je code (sérieusement) depuis plus de 15 ans maintenant. J'ai toujours eu des tests pour mon code. Cependant, au cours des derniers mois, j'ai appris la conception / développement piloté par les tests (TDD) en utilisant Ruby on Rails . Jusqu'ici, je ne vois pas l'avantage.

Je vois des avantages à écrire des tests pour certaines choses, mais très peu. Et bien que j'aime l'idée d'écrire le test en premier, je constate que je passe beaucoup plus de temps à essayer de déboguer mes tests pour les amener à dire ce que je veux dire vraiment que de déboguer le code réel. Ceci est probablement dû au fait que le code de test est souvent beaucoup plus compliqué que le code qu’il teste. J'espère que ce n'est que le manque d'expérience avec les outils disponibles ( RSpec dans ce cas).

Cependant, je dois dire que pour le moment, le niveau de frustration associé au manque décevant de performances est inacceptable. Jusqu'à présent, la seule valeur que je vois de TDD est une bibliothèque croissante de fichiers RSpec qui servent de modèles pour d'autres projets / fichiers. Ce qui n’est pas beaucoup plus utile, peut-être moins utile, que les fichiers de code de projet réels.

En lisant la littérature disponible, je remarque que le TDD semble être une perte de temps considérable, mais porte ses fruits à la fin. Je me demande s'il existe des exemples concrets. Est-ce que cette frustration massive porte ses fruits dans le monde réel?

J'espère vraiment que je n'ai pas manqué cette question ailleurs. J'ai cherché, mais toutes les questions / réponses ont plusieurs années maintenant. C'était une occasion rare quand j'ai trouvé un développeur qui dirait n'importe quoi sur TDD, c'est pourquoi j'ai consacré autant de temps à ce sujet que moi. Cependant, j'ai remarqué que personne ne semble citer des exemples concrets du monde réel. J'ai lu une réponse disant que le responsable du débogage du code en 2011 vous remercierait de disposer d'une suite complète de tests unitaires (je pense que ce commentaire a été fait en 2008).

Donc, je me demande simplement, après toutes ces années, avons-nous enfin des exemples montrant que le gain est réel? Quelqu'un a-t-il réellement hérité du code conçu / développé avec TDD ou en est-il revenu et a-t-il réalisé un ensemble complet de tests unitaires et a-t-il réellement perçu un gain? Ou avez-vous trouvé que vous passiez tellement de temps à essayer de comprendre ce que le test testait (et pourquoi il était important) que vous veniez de jeter tout le gâchis et de creuser dans le code?

James
la source
1
Cela m'a épargné plusieurs fois: parce que nous sommes plusieurs personnes sur le même projet, parce que les mises à jour de gemmes peuvent avoir des effets secondaires inconnus, car si tout est vert et que j'ai un bogue, je sais où il n'est pas digne de trouver sa racine.
apneadiving
4
Bonne
3
butunclebob.com/ArticleS.UncleBob.JustTenMinutesWithoutAtest Voici une histoire d'Oncle Bob sur une situation réelle à laquelle il a été confronté.
Hakan Deryal
1
Au début, j’imaginais que les tests seraient très utiles pour savoir où les bugs n’étaient pas, mais j’ai vite appris, comme @Hakan l’a souligné dans l’article de Oncle Bob, que c’est généralement parce que vous avez manqué un cas de test. Ce qui rend ces tests plutôt inutiles. En fait, cet article souligne que le développement incrémental est ce qui fonctionne.
James
1
"Je trouve que je passe beaucoup plus de temps à essayer de déboguer mes tests pour les amener à dire ce que je veux vraiment dire qu'à déboguer le code réel" : mais n'est-ce pas justement l'avantage? Après cela, trouvez-vous toujours que vous passez beaucoup de temps à déboguer le "code actuel"? Les partisans de TDD soutiennent que le temps passé à trouver un moyen de rendre votre code testable est en réalité un effort de conception qui bénéficiera à votre code.
Andres F.

Réponses:

26

Cet article démontre que TDD ajoute 15 à 35% de temps de développement en contrepartie d'une réduction de 40 à 90% de la densité de défauts sur des projets par ailleurs identiques.

L'article se réfère à l'article complet (pdf) - Nachiappan Nagappan, E. Michael Maximilien, Thirumalesh Bhat et Laurie Williams. «Réaliser l'amélioration de la qualité grâce au développement piloté par les tests: résultats et expériences de quatre équipes industrielles». ESE 2008 .

AbstraitLe développement piloté par les tests (TDD) est une pratique de développement logiciel utilisée sporadiquement depuis des décennies. Grâce à cette pratique, un ingénieur en logiciel alterne minute par minute entre l'écriture de tests unitaires défaillants et l'écriture de code d'implémentation pour réussir ces tests. Le développement basé sur les tests est récemment réapparu en tant que pratique essentielle des méthodologies de développement logiciel agiles. Cependant, peu de preuves empiriques soutiennent ou réfutent l'utilité de cette pratique dans un contexte industriel. Des études de cas ont été menées avec trois équipes de développement de Microsoft et une d’IBM qui ont adopté TDD. Les résultats des études de cas indiquent que la densité de défauts avant libération des quatre produits a diminué entre 40% et 90% par rapport à des projets similaires qui n’utilisaient pas la pratique du TDD. Subjectivement,

Le texte intégral résume également brièvement les études empiriques pertinentes sur le TDD et leurs résultats de haut niveau (section 3 Travaux connexes ), y compris George et Williams 2003, Müller et Hagner (2002), Erdogmus et al. (2005), Müller et Tichy (2001), Janzen et Seiedian (2006).

moucheron
la source
2
Dans le cadre d’une discussion sur Meta.StackOverflow , pouvez-vous ajouter des informations supplémentaires sur le document qui pourraient intéresser le demandeur ainsi que les futures personnes qui trouveront cette question?
Thomas Owens
2
@ThomasOwens, je pensais que la conclusion ("TDD ajoute 15 à 35% de temps de développement en contrepartie d'une réduction de 40 à 90% de la densité de défauts") était l'information supplémentaire qui répond à la question initiale <_ <
4
Ce poste a été marqué pour ne pas contenir suffisamment d'informations. Je n'ai pas encore lu le journal, mais il semble que les gens veulent plus d'informations ajoutées au corps de la réponse. Peut-être discuter davantage des conditions spécifiques utilisées dans l'étude?
Thomas Owens
99% de toutes les statistiques sont fictives. : P Mais c'est vraiment une question de contexte. Sur quel genre d'équipe? Un grand troupeau de développeurs Java médiocres? Oui, je pense que TDD les aiderait à gagner en productivité. Mais cela ne veut pas dire que posséder les compétences architecturales nécessaires pour concevoir et valoriser un code robuste ne les aiderait même pas davantage. En outre, le TDD test-first pourrait tout simplement les empêcher d’apprendre à le faire correctement. Et oui, j'ai entendu dire que cela aide à la conception. Dans une certaine mesure, c’est probablement vrai, mais c’est toujours un manque de reconnaissance et une aide de groupe pour le problème fondamental de l’OMI.
Erik Reppen
Ce serait bien si d'autres documents étaient répertoriés dans la bibliothèque numérique d'ACM ou si les mots clés à utiliser pour le moteur de recherche étaient ajoutés. nous avons besoin de plus de rigueur dans nos réponses lorsque nous parlons d'agile et de TDD
Rudolf Olah
16

Je vois des avantages à écrire des tests pour certaines choses, mais très peu. Et bien que j'aime l'idée d'écrire le test en premier, je constate que je passe beaucoup plus de temps à essayer de déboguer mes tests pour les amener à dire ce que je veux dire vraiment que de déboguer le code réel.

Je travaille chez TDD depuis trois ans et mon expérience est exactement le contraire. Je passe moins de temps à écrire des tests unitaires que de déboguer le code si je n'avais pas écrit les tests unitaires.

Non seulement je fais du TDD, je travaille en dehors, c’est-à-dire que je m’applique d’abord en TDD. L'implémentation de la couche supérieure définit les exigences pour la couche suivante du système, que je développe à l'aide de TDD, etc. jusqu'à ce que tout le code requis pour la fonctionnalité ait été implémenté. Souvent, je constate qu'après avoir implémenté une fonctionnalité comme celle-ci et que je teste la fonctionnalité dans le système réel, cela fonctionne la première fois. Pas tout le temps, mais souvent.

Et comme il faut beaucoup plus de temps pour tester une fonctionnalité du système actuel que pour exécuter quelques tests unitaires, je gagne un temps considérable. En réalité, il est plus rapide pour moi d'implémenter une fonctionnalité à l'aide de TDD que de ne pas l'implémenter sans écrire des tests unitaires.

Mais écrire des tests unitaires est une compétence qui doit être apprise et maîtrisée, comme toute autre compétence de programmation. Quand j'ai commencé à travailler chez TDD, j'avais 12 ans d'expérience professionnelle en programmation et j'étais un programmeur très accompli. Je pensais qu'écrire de grandes suites de tests pour le code système serait une chose simple. Mais à mesure que la quantité de code de test augmentait et que différentes parties du système avaient été modifiées, et que les tests existants devaient être modifiés, j'ai appris que la structuration et l'écriture du test unitaire est en soi une compétence qui doit être apprise et maîtrisée. De plus, tout le code n'est pas également testable. Le code système doit être très faiblement couplé pour pouvoir être testé efficacement. L’apprentissage de TDD m’a réellement aidé à rendre le code système plus couplé.

Mais mon efficacité actuelle dans le travail TDD provient d’une combinaison de maîtrise de l’écriture des tests unitaires et de la technologie dans laquelle le système est implémenté (C # dans ce cas).

Faire du TDD tout en apprenant une nouvelle technologie peut être difficile. Par exemple, bien que je sois un peu en programmation pour iPhone, je ne rédige pas une quantité importante de tests unitaires, car je ne maîtrise pas le langage, objectif c, ni moi-même. la bibliothèque. Je ne sais donc pas comment structurer mes tests unitaires, encore moins comment structurer le code système, comment le rendre testable.

Mais comment ça marche sur de vrais projets?

Sur le projet sur lequel je travaille depuis quelques années, bien que le code soit suffisamment couvert par des tests unitaires, je suis le seul membre de l'équipe qui rédige les premiers tests. Mais la grande suite de tests me donne confiance pour pouvoir refactoriser le système, et je suis convaincu que le système fonctionnera correctement si la suite de tests réussit.

Malheureusement, comme beaucoup de tests sont écrits après le code système, bon nombre de tests eux-mêmes sont défectueux, c’est-à-dire qu’ils ne testent pas vraiment ce qu’ils étaient censés tester. Cet imho ne peut être évité. Chaque fois que vous écrivez un morceau de code, il y a une probabilité que le code ne fonctionne pas comme vous le souhaitez, c'est-à-dire qu'il y a un bogue. Il en va de même pour le code de test. Par conséquent, il est probable que le test soit réussi même si le code qu'il devrait tester ne fonctionne pas comme prévu.

Écrire le test en premier, en vérifiant non seulement que vous obtenez un échec de test, mais également que le test échoue avec exactement le message d'erreur attendu avant d'implémenter le code système, réduit considérablement le risque d'erreur dans le code de test unitaire.

Donc, pour résumer, d'après mon expérience, une fois que vous maîtriserez l'art du TDD, vous ne gagnerez pas simplement du temps, vous gagnerez du temps à l'avance. Mais il faut du temps, même pour un programmeur expérimenté, pour maîtriser l'art du TDD. Et il faut encore plus de temps pour une équipe de développeurs aux compétences variées pour maîtriser l'art du TDD.

Pete
la source
9

Nous avons profité massivement.

Nous sommes un commerçant de niveau 1, ce qui signifie que nous traitons plus de six millions de transactions de paiement par an.

Notre système de passerelle de paiement comporte des milliers de tests unitaires et d'intégration. Ces tests nous donnent confiance dans notre capacité à traiter les paiements. Vous voulez être sûr que les freins de votre voiture fonctionnent, n'est-ce pas? Nous voulons avoir la certitude que nous ne perdons pas notre entreprise car nous ne pouvons pas traiter les paiements.

La couverture de code vous donne cette confiance. Bien sûr, ce n'est pas suffisant en soi, mais c'est un très bon début.

La plupart de notre système de passerelle de paiement a été écrit en TDD. Certains aspects étaient plutôt difficiles à tester, nous avons donc décidé de réduire les coûts en sacrifiant une partie de la couverture du code. Nous reviendrons et réglerons ces problèmes éventuellement.

Personnellement, il m'est difficile d'écrire une logique avant d'écrire des tests. Cela dit, il m'a fallu un peu de temps pour commencer à penser de manière TDD.

Référence Visa PCI: http://usa.visa.com/merchants/risk_management/cisp_merchants.html

CodeART
la source
3
"Nous reviendrons et réglerons ces problèmes éventuellement." - Probablement pas ... pas à moins qu'ils ne vous giflent avec un insecte horrible. Ces zones deviendront la colonne vertébrale de tout le reste et guideront toutes les étapes de la conception car personne ne voudra investir les ressources nécessaires pour les redéfinir et personne ne voudra imposer un changement qui pourrait faire mal. Ça se passe à chaque fois: P
Edward Strange
Vous devinez, quand je vous dis ce qui se passe dans l'entreprise. Lorsque nous nous engageons, nous pouvons engager du code avec une couverture de code de 70%. Ceci est constamment augmenté par le plomb CI. D'ici quelques mois, le seuil minimum de couverture de code sera augmenté d'un petit pourcentage. Après cela, il n'y aura plus d'autre choix que d'introduire plus de tests.
CodeART
7

Bien que certaines personnes considèrent souvent les tests comme un moyen de faire trop, je pense que cela en vaut vraiment la peine dans certains cas.

Je développe un solveur Killer Sudoku pour l’école depuis environ 3 mois. Il utilise de nombreuses "stratégies" pour éliminer les possibilités et les solutions. Le fait est qu’une erreur dans une possibilité peut être fatale et entraîner un problème pour résoudre le sudoku, car si une possibilité est supprimée, vous ne l’essayez plus, et si c’était la solution, le programme ne pourrait pas résoudre le problème. la grille plus.

Mais c’est vraiment difficile de tester manuellement, c’est vrai, il ya une grille, je peux voir quelles stratégies font quoi dans un exemple concret, mais je ne peux pas tout vérifier à chaque fois qu’une stratégie s’applique car elle représente trop de données.

Et les stratégies appliquées sur une certaine grille sont assez "aléatoires", c'est-à-dire que vous n'utiliserez pas tout sur une grille particulière.

Alors j’ai écrit des tests sur chaque stratégie, vérifiant le résultat sur chaque cellule, en utilisant seulement des situations simples (par exemple, deux cellules seulement ont déjà supprimé des possibilités) et cela m’a évité des heures par jour où j’avais malheureusement une grille impossible à résoudre. Parce que je savais déjà où était le problème.

Cydonia7
la source
2
Je pense que cette question pique plus au test d'abord, puis à la stratégie plus tard Les tests sont bien sûr utiles pour le débogage d'applications où il serait fastidieux de tester toutes les possibilités vous-même.
Alex Hope O'Connor
6

L’avantage de TDD est que vous savez comment appeler votre code avant d’écrire le code lui-même.

En d’autres termes, TDD vous aide à concevoir votre API.

D'après mon expérience, cela aboutit à de meilleures API, ce qui donne un meilleur code.


EDIT: Comme je l’ai écrit, c’était "selon mon expérience", c’est-à-dire lors de la rédaction de "projets du monde réel", mais malheureusement, c’est avec une base de code source fermée que je ne peux pas laisser le monde voir. Je peux comprendre d'après les commentaires que c'est ce qui est en réalité demandé, et non pas seulement une confirmation de la simple existence de tels projets.

J'ai également constaté - encore une fois dans mon expérience personnelle - que le bénéfice réel apparaît lorsque l'on passe en mode de maintenance car les exigences ont tendance à changer. L'API de nettoyage a beaucoup facilité l'expression des exigences nouvelles ou modifiées dans le code de test, et tous les tests le rendent très permettaient facilement de voir comment le code devait être appelé et ce qui pouvait être attendu.

Les cas de test exécutent des versions de la spécification et vous permettent de voir très, très facilement comment appeler votre API. C’est peut-être la forme la plus utile de documentation "HOW" que j’ai vue jusqu’à présent (comparez à la documentation "WHY" comme JavaDoc), car vous êtes certain qu’elle est correcte (sinon le test échouerait).

Dernièrement, j'ai dû maintenir un client FTP scriptable avec un très grand nombre d'options qui influent toutes sur le fonctionnement de l'application. TDD a été introduit récemment pour les nouvelles fonctionnalités et la grande suite de tests nous permet d’effectuer des corrections à chaud tout en ayant la certitude que les fonctionnalités utilisées fonctionnent toujours comme prévu. En d’autres termes, cette transition a porté ses fruits très rapidement.


la source
8
Cette réponse semble être tout à fait à côté de la question, car elle appelle à des exemples concrets . Mais puisque trois personnes ont pensé que "cette réponse est utile", il me manque quelque chose.
3
D'accord, mais il me manque la réputation de voter à la baisse. C’est juste le "TDD donne de meilleurs résultats" sans exemple de projet dérivé de TDD en maintenance pour sauvegarder la réponse que je voulais éviter.
James
Maintenant que plusieurs personnes sont d’accord avec moi, j’ose oser la voter. Est-ce que n'importe quel votant, ou l'auteur, pourrait-il nous expliquer pourquoi c'est une bonne réponse?
@delnan "I Dare Downvote" - un choix de mots intéressant. Le montage est-il tombé à votre goût?
Oui, j'ai retiré mon vote négatif maintenant que je l'avais remarqué.
5

La valeur d’une approche particulière en matière de test dépend de l’importance critique du système en développement, et de la mesure dans laquelle un autre système essentiel dépend de celle-ci. Un simple script de livre d'or pour votre site Web pourrait difficilement être considéré comme essentiel à la mission, mais si le site Web sur lequel il est exploité pouvait être compromis par un bogue qui permettait une entrée non filtrée dans la base de données et que ce site offre un service essentiel, il devient soudainement beaucoup plus complexe. important pour que le script du livre d’or soit minutieusement testé. Il en va de même pour le code framework / library. Si vous développez un framework avec un bogue, chaque application qui utilise cette fonctionnalité du framework a également ce même bogue.

Le développement piloté par les tests vous apporte une couche supplémentaire de sécurité lors des tests. Si vous écrivez les tests à côté ou même après le code que vous voulez tester, vous risquez alors de vous tromper. Si vous écrivez tous les tests en premier, la manière dont le code fonctionne en interne ne peut pas influencer le but de vos tests. Par conséquent, il est moins probable que vous écriviez par inadvertance des tests qui considèrent qu'une sortie erronée particulière est correcte.

Le développement piloté par les tests encourage également vos développeurs à écrire du code facile à tester, car ils ne veulent pas se donner encore plus de travail! Un code facile à tester a tendance à être un code facile à comprendre, à réutiliser et à gérer.

Et la maintenance est l’endroit où vous récolterez vraiment les fruits du TDD. La grande majorité des efforts de programmation consacrés aux logiciels sont liés à la maintenance. Cela signifie apporter des modifications au code en direct pour lui donner de nouvelles fonctionnalités, corriger des bogues ou l'adapter à de nouvelles situations. Lorsque vous effectuez de telles modifications, vous voulez vous assurer que les modifications que vous apportez ont l'effet souhaité, et plus important encore, elles n'ont aucun effet d'entraînement inattendu. Si vous avez une suite de tests complète pour votre code, il est facile de vérifier que les modifications que vous apportez ne cassent pas autre chose, et si les modifications que vous apportez cassent autre chose, vous pouvez rapidement en trouver la raison. Les avantages sont à long terme.

Vous avez dit ceci dans votre question:

Je vois des avantages à écrire des tests pour certaines choses, mais très peu. Et bien que j'aime l'idée d'écrire le test en premier, je constate que je passe beaucoup plus de temps à essayer de déboguer mes tests pour les amener à dire ce que je veux dire vraiment que de déboguer le code réel. Ceci est probablement dû au fait que le code de test est souvent beaucoup plus compliqué que le code qu’il teste. J'espère que c'est simplement une inexpérience avec les outils disponibles (rspec dans ce cas).

Cela semble suggérer à moi que vous ne faites pas tout à fait le test. Un test unitaire est supposé être extrêmement simple, il ne s'agit que d'une séquence d'appels de méthode, suivie d'une assertion permettant de comparer le résultat attendu au résultat réel. Ils sont censés être simples car les bogues dans vos tests seraient désastreux et si vous introduisez un contrôle de boucle, de branchement ou un autre programme dans le test, il est plus probable que le test contienne un bogue. Si vous passez beaucoup de temps à déboguer des tests, cela signifie que vos tests sont trop compliqués et que vous devriez les simplifier.

Si les tests ne peuvent pas être simplifiés, cela seul suggère qu'il y a quelque chose qui cloche dans le code sous test. Par exemple, si votre classe a de longues méthodes, des méthodes avec beaucoup d'instructions if / elseif / else ou switch ou un grand nombre de méthodes ayant des interactions complexes dictées par l'état actuel de la classe, les tests devront nécessairement être extrêmement complexes. pour fournir une couverture complète du code et tester toutes les éventualités. Si votre classe a des dépendances codées en dur sur d’autres classes, cela augmentera encore le nombre d’arcades à franchir pour tester efficacement votre code.

Si vous maintenez vos classes petites et très concentrées, avec des méthodes courtes avec peu de chemins d'exécution et essayez d'éliminer l'état interne, les tests peuvent être simplifiés. Et c'est un peu le noeud de la question. Un bon code est par nature facile à tester. Si le code n'est pas facile à tester, il y a probablement quelque chose qui ne va pas.

Écrire des tests unitaires vous est bénéfique à long terme, et les éviter revient simplement à stocker les problèmes pour plus tard. Vous ne connaissez peut-être pas le concept de dette technique, mais cela fonctionne beaucoup comme une dette financière. Ne pas écrire de tests, ne pas commenter de code, écrire dans des dépendances codées en dur, ce qui constitue un moyen de s’endetter. Vous «empruntez» du temps en ménageant des étapes précoces, ce qui peut vous aider à respecter un délai serré, mais le temps que vous économisez plus tôt dans le projet est en prêt. Chaque jour qui passe sans nettoyer le code, le commenter correctement ou la construction d’une suite de tests vous coûtera de l’intérêt. Plus cela dure longtemps, plus les intérêts s'accumulent. Finalement, vous découvrirez que votre code est devenu un gâchis enchevêtré sur lequel vous ne pouvez pas apporter de modifications sans entraîner de conséquences inattendues.

Vous pourriez penser à écrire des tests unitaires tôt et à les tenir à jour comme une forme de "crédit technique". Vous mettez votre temps à la banque en consacrant très tôt le projet aux bonnes pratiques. Vous gagnerez de l'intérêt sur cette prévision plus tard, lorsque vous arriverez à la phase de maintenance du projet. Lorsque vous souhaitez effectuer un changement, vous pouvez facilement valider l'exactitude du changement et le fait qu'il n'a pas d'effets secondaires indésirables et que vous pouvez obtenir des mises à jour rapidement et sans tracas. Si des bogues se présentent, vous pouvez ajouter un nouveau test unitaire qui l'exerce, puis corrigez le bogue dans le code. Lors de la prochaine exécution du test unitaire, vous pourrez vérifier que le bogue a été corrigé et qu’il n’a causé aucun autre problème. De plus, vous éviterez les "régressions",

TL: DR - Oui, c’est une aide réelle, mais c’est un investissement. Les avantages ne deviennent apparents que plus tard.

GordonM
la source
1
J'ai acheté cette logique il y a des mois. J'aime l'idée de TDD, je trouve que la réalité est un peu déconcertante. En outre, je remarque que même ici, il n’existe aucun exemple concret où l’héritage d’un projet basé sur TDD a porté ses fruits. Êtes-vous réellement revenu à une ancienne base de code qui comportait de nombreux tests unitaires et cela a porté ses fruits.
James
Malheureusement, personne d'autre ne semble avoir construit de tests unitaires, du moins sur aucun des codes dont j'ai hérité des développeurs précédents. Ma vie aurait été bien plus facile si elles l'avaient été. Je vous suggère de consulter le livre dans le lien, qui contient des exemples réels, bien que ce soit pour PHP plutôt que pour Rails. amazon.fr/…
GordonM
Je suis un très grand critique d'usage général, mais je ne reprocherais à personne d'utiliser cette approche dans un système financier intégré ou critique.
Erik Reppen
4

J'utilise assez souvent TDD au travail. Mon expérience est que TDD se justifie parce que vous ne payez pas plus de temps ou d'effort, vous enregistrez .

  • Depuis que j'utilise TDD, je passe beaucoup moins de temps à déboguer. Cela fonctionne simplement depuis le début car je ne considère pas le code productif comme écrit tant que les tests ne passent pas.

  • QA rapporte beaucoup moins de bugs, nous réduisons donc les coûts de réparation de notre code après une publication. En effet, TDD ne vous permet pas d’écrire du code sans test. La couverture de code est donc bien meilleure.

  • Je peux exécuter mon code (productif) beaucoup plus souvent et plus rapidement, car je n'ai pas besoin de démarrer le serveur d'applications complet. Le démarrage du test unitaire est un ordre de grandeur plus rapide. Bien entendu, je n'en profite que lorsque le test est déjà exécutable lorsque je souhaite tester le code productif. Lorsque les tests viennent après, cet avantage est manqué.

  • Je fais beaucoup moins de tests manuels. Mes collègues qui ne pratiquent pas TDD passent beaucoup de temps à cliquer sur l'application jusqu'à ce qu'ils atteignent le point où le nouveau code est exécuté. Je ne teste qu'une seule fois manuellement, juste avant de m'engager dans le contrôle de version.

  • Même si j'utilise un débogueur, il est beaucoup plus rapide de déboguer l'exécution d'un test que l'ensemble de l'application.

Vous pensez peut-être que les tests unitaires sont des tests de régression. C’est l’un de leurs objectifs, mais leur compréhension en tant qu’outil de développement les rend beaucoup plus rentables.

Wolfgang
la source
La qualité est gratuite!
MathAttack
2
La mauvaise qualité est chère!
Wolfgang
3

Un autre avantage (en plus de ceux mentionnés par les autres personnes qui ont répondu) intervient lorsque les testeurs d’acceptation des clients ou les utilisateurs de (découverte de la production) découvrent un bogue. Transformez le rapport de bogue en un test de type TDD pour la classe qui semble être en faute. Regardez ça échouer. Répare le. Regarde le passer. Ensuite, vous savez que vous avez corrigé le bogue. Cette technique m'a permis d'économiser des heures.

Dawood dit réintégrer Monica
la source
2

Eh bien, je sais que je profite personnellement d’être deux fois plus rapide que mes collègues développeurs et d’écrire moins de la moitié des bugs qu’ils commettent parce qu’ils ne font pas la TDD. Les gens qui devraient probablement être meilleurs que moi même ... Je les surperforme d'au moins un facteur de 2.

Je ne suis pas arrivé tout de suite. Je suis assez bon pour écrire du code à la volée et sans harnais. Semblait être un gros gaspillage pour écrire toute cette merde supplémentaire. Mais il fait plusieurs choses, y compris (non exclusive):

  • Forcer une conception orientée vers le découplage et la réutilisation (tout doit être réutilisé dans un test unitaire).
  • Fournir une plate-forme pour développer du code en petits morceaux et modules afin que je n’aie pas besoin de tout comprendre et de terminer avant d’exécuter un type de test simple: "compile-t-il et prend-t-il les données en entrée".
  • Fournir une plate-forme de test rapide pour apporter des modifications lorsque les utilisateurs exigent des modifications de fonctionnalités auxquelles je ne m'attendais pas.

Un exemple sur ce dernier bit est un projet sur lequel je travaille actuellement, où le responsable a soudainement décidé de réécrire TOTALEMENT le protocole de communication utilisé pour à peu près aucune raison. J'ai été en mesure de réagir à ce changement en 2 heures car je l'avais déjà dissocié de tout le reste et j'étais capable de travailler dessus de manière totalement indépendante jusqu'au dernier assemblage et d'intégrer l'étape de test. La plupart de mes collègues auraient probablement été là depuis un jour ou plus parce que leur code ne serait pas découplé et qu'ils changeraient ici, là-bas, partout ... en compilant tout ... les tests d'intégration ... répétez, répétez ... prend beaucoup plus de temps de cette façon et est loin d'être aussi stable.

Edward Strange
la source
2

La réponse est oui. Dans mon entreprise, nous développons une application C ++ depuis plus de 20 ans. L'année dernière, nous avons introduit TDD dans certains nouveaux modules et les taux de défauts ont considérablement diminué. Cela nous a tellement plu que certains d’entre nous ajoutons même des tests au code hérité chaque fois que nous changeons quelque chose.

De plus, tout un module a été complété du début à la fin, en passant par la production, sans jamais présenter de bogue (et c'est également un module critique). Son développement a donc été plus rapide que d’habitude, car normalement ce qui se passerait autrement, c’est qu’un module serait "achevé", pour ne revenir que 4 à 5 fois à partir de la version bêta du test de correctifs. C'était une amélioration substantielle et les développeurs étaient également plus satisfaits du nouveau processus.

Je n'ai pas beaucoup utilisé Rails TDD, mais j'ai beaucoup fait en C ++, C #, Java et Python. Je peux vous dire que ça marche vraiment. Je suppose que vous passez beaucoup de temps à penser aux noms de test parce que vous n’êtes pas assez confiant. Rédigez votre test en premier, mais laissez couler votre créativité ...

J'ai remarqué qu'une fois que vous maîtrisez vraiment TDD, vous commencez à moins vous soucier de "Comment vais-je nommer ce test ... argh!", Et vous ne faites que suivre, refactoriser et adapter déjà écrit tests pour s'adapter à la situation actuelle.

Temps pour un pourboire

Conseil n ° 1

Je pense donc que le conseil qui devrait vous aider le plus est de ne pas vous inquiéter autant. L'un des plus beaux atouts de TDD est qu'il vous donne le courage de changer des choses qui sont déjà écrites et qui fonctionnent. Et cela inclut les tests.

Conseil n ° 2

Commencez les nouveaux tests de classe par un simple test "canCreate", juste pour vous mettre dans la bonne direction, comme dans "Ok, je travaille sur cette classe maintenant ... c'est bien."

Ensuite, commencez à ajouter plusieurs tests, mais un seul à la fois, et assurez-vous que chaque test que vous créez est le cas le plus simple qui vous vient à l’esprit à ce moment-là (pensez-y pendant 30 secondes maximum, puis arrêtez le délai imparti. avec le meilleur que vous avez à ce point).

Et rappelez-vous

Ne craignez plus de refactoriser les tests existants ni même de supprimer ceux qui sont obsolètes ou redondants. Peu de gens se rendent compte de cela, mais dans TDD, vous bénéficiez de 2 filets de sécurité pour le prix de 1. Vos tests sont un filet de sécurité pour les modifications du code de production, mais votre code de production est également un filet de sécurité pour la refactorisation des tests. La relation est réciproque. C'est en fait un bon cas de couplage étroit.

Donnez-lui un autre coup. Et laissez-moi vous recommander de regarder Clean Code Castts , en particulier ceux sur TDD.

Yam Marcovic
la source
1

Exemple non trivial du monde réel:

Je devais écrire une fonction de transformation de la structure de données. L'entrée serait une structure de données (en réalité une structure de données imbriquée, un peu comme une arborescence) et le résultat serait une structure de données similaire. Je ne pouvais pas visualiser la transformation réelle dans mon esprit. L'un des principaux avantages du TDD (pour moi, en tout cas) est la mise en œuvre progressive des étapes par étapes si vous ne savez pas comment procéder (voir Kent Becks "TDD by Example"). Parce que je ne savais pas où cela se passait, j'ai commencé avec des cas de base simples, tels que des entrées vides ou triviales, et j'ai progressé dans des cas plus compliqués jusqu'à ce que je me rende compte qu'ils étaient tous couverts. Finalement, j'ai eu un algorithme de travail et les tests qui l'ont prouvé. Non seulement les tests prouvent que mon implémentation fonctionne actuellement, mais ils m'empêchent également de tout gâcher par la suite.

EricSchaefer
la source
-1

Je n'aime pas l'idée de suivre aveuglément des conseils génériques, car je ne crois pas qu'il existe une suggestion unique qui aidera la plupart des développeurs à devenir plus productifs et à réduire les défauts dans les applications. D'après mon expérience, plus vous vous inquiétez pour la qualité, plus vous perdez en nouvelles fonctionnalités. Le niveau d'importance que vous souhaitez accorder à la qualité par rapport à la productibilité dépendra en réalité de votre produit et de votre stratégie actuelle. Ce sera probablement quelqu'un d'autre qui décidera stratégiquement de ce qui est le plus important pour le moment: la robustesse ou la productibilité.

Même cette décision n'est ni noire ni blanche. Il est fort probable que certaines parties de votre application doivent être robustes, alors que d'autres ne le sont pas. Une fois que vous avez identifié les pièces qui doivent avoir un degré de qualité élevé, vous devez vous concentrer sur celles-ci du point de vue du test, car vous voulez assurer une qualité élevée à ces pièces.

Tout ce que j'ai dit jusqu'à présent n'a rien à voir avec TDD, en particulier en ce qui concerne l'écriture de tests avant la mise en œuvre, mais je pense qu'il est important de séparer les avantages d'avoir testé le code par rapport à l'écriture des tests.

Une fois que vous avez compris les avantages du test lui-même, TDD ou non, vous pouvez ensuite discuter de la stratégie de test du code que vous souhaitez inclure dans les tests. Certaines personnes diront que si vous écrivez les tests plus tard, vous manquerez certaines conditions, mais je pense que vous devriez être le seul à pouvoir évaluer si cela s'applique à vous. Cela ne s'applique certainement pas à moi.

Alors, voici comment cela fonctionne pour moi. Il existe essentiellement deux situations qui me feront écrire des tests: cela n'améliorera que la qualité ou cela accélérera également le développement de certaines fonctionnalités. Par conséquent, lorsque je rédige des tests, il n’ya pas de nouvelles fonctionnalités dans le backlog et je peux ensuite décider d’améliorer les performances de l’application, de simplifier la base de code ou d’améliorer la suite de tests. Une autre situation est la nécessité de disposer d'un code fonctionnel solide dans lequel les bogues auraient un impact assez important sur les clients réels. Un autre exemple concerne le test de code complexe facile à décomposer lorsque vous y travaillez. Par exemple, ma base de code contient une classe QueryBuilder qui prend en charge de nombreux cas d'utilisation et il serait facile d'en supprimer quelques-uns tout en corrigeant un bogue ou en ajoutant une nouvelle fonctionnalité.

Enfin, il y a le cas où l'écriture des tests me permet d'abord d'écrire une fonctionnalité plus rapidement que de ne pas écrire les tests du tout. QueryBuilder était également un cas où cette règle a également été appliquée, mais cela ne signifie pas que TDD sera également le meilleur chemin. Un autre exemple d'aide de TDD sur la vitesse de développement concerne le test de la génération Excel, tandis que dans l'application réelle, vous devrez peut-être exécuter plusieurs étapes à chaque fois que vous souhaitez tester une condition spécifique de la génération. Ou si vous devez créer des enregistrements pour tester une fonctionnalité et qu'il est difficile, voire impossible, de les supprimer manuellement après avoir testé manuellement le code.

Donc, s'il est plus facile pour vous de reproduire les étapes pour exécuter du code en développement par programmation (via des tests), lancez-vous. Mais si écrire le test est plus compliqué que de le tester manuellement, vous devez alors décider si le moment est venu de vous concentrer sur la qualité ou si votre carnet de commandes contient beaucoup de demandes et qu'un membre de l'entreprise le saura probablement mieux et vous laissera sachez où vous devriez vous concentrer en fonction de leurs besoins actuels et de la stratégie de leur entreprise.

Dans un monde idéal, tout le code est testé, mais on ne peut pas prétendre qu'il n'y a pas de compromis à faire et supposer que TDD est toujours la meilleure et unique voie. Comme pour toutes les meilleures pratiques existantes, vous devez toujours vous concentrer sur ce qui est le mieux pour l'entreprise pour laquelle vous travaillez et non sur ce qui est meilleur pour vous. Une fois que vous êtes devenu indépendant, vous êtes libre de décider d'effectuer le TDD à tout moment si vous pensez que c'est la meilleure voie à suivre. Si votre société estime que tout le code doit être testé, vous devez écrire des tests pour tout le code que vous écrivez. Mais dans la plupart des cas, vous devez avoir une vue d'ensemble et comprendre les compromis avant de prendre une décision. Désolé, mais ce n'est pas une science exacte et il n'y a pas de réponse simple (et difficile) one-size-fits-all que vous devriez suivre à chaque fois.

Juste comme avec les modèles de conception. Comprenez comment ils fonctionnent et pourquoi ils ont été créés, quels types de problèmes ils résolvent et quels sont leurs inconvénients. Comprendre que le raisonnement est beaucoup plus important que de se souvenir des solutions proposées. Ce qui est une opération coûteuse aujourd'hui peut être facilement réalisé demain avec d'autres technologies. Si les prémisses d'une solution bien établie ne sont plus valables, il est fort probable que la solution ne soit plus la meilleure à utiliser. Lorsque les exigences, la technologie disponible ou la stratégie de l'entreprise ont changé, vous devez toujours réévaluer votre boîte à outils. Lorsque cela se produit, vous devez comprendre pourquoi vous avez choisi chaque voie au lieu de la prendre pour subvention comme étant la meilleure option.

Rosenfeld
la source
cela ne tente même pas de répondre à la question posée: "avons-nous enfin des exemples montrant que le gain est réel? Quelqu'un at-il réellement hérité ou est retourné au code qui a été conçu / développé avec TDD et dispose d'un ensemble complet de tests unitaires et vraiment senti un gain? "
moucher
1
Cela répond, mais puisque vous ne partagez pas mon opinion, vous lui donnez -1. En gros, quiconque n'essaiera pas de montrer les valeurs de TDD donnera une réponse indésirable de votre point de vue;), laissez-moi deviner. . Vous êtes un évangélisateur de TDD, non? :) Au fait, la vraie question de l'auteur est de savoir si le TDD est rentable ou non. Vous n'avez pas besoin de pratiquer TDD pour répondre à cette question. Fortran est-il rentable pour l'écriture d'applications Web? Avez-vous essayé avant de répondre?
Rosenfeld
Je n'ai pas d'opinion sur le TDD, et je n'utilise pas les votes comme j'aime / je n'aime pas (c'est un site de questions et réponses, pas un Facebook). D'après mes lectures, cette "réponse" ne répond tout simplement pas à la question posée, ni positivement ni négativement
Gnat
De mon point de vue, ce n’est pas une question technique, comme "comment puis-je faire X avec nginx?". Il existe de bonnes réponses aux questions de ce type, mais pas aux questions qualitatives et subjectives de ce type, lorsque l'auteur souhaite en réalité connaître l'opinion des autres sur le TDD et savoir si cela en vaut la peine. C'était ma tentative de montrer mon point de vue. Je n'ai aucune idée de la façon dont une réponse pourrait être la bonne, car elles me semblent toutes comme des opinions personnelles. Vous ne pouvez pas mesurer efficacement si le TDD vaut la peine ou non. Tout article essayant de faire cela est fondamentalement faux.
Rosenfeld
"Ce site est un circuit qui cherche des réponses . Ce n'est pas un forum de discussion ..."
jeudi