Je suis un nouveau programmeur (j'apprends seulement depuis environ un an) et dans mon objectif de devenir meilleur dans ce domaine, je viens tout juste d'apprendre le TDD. Je voulais prendre l'habitude de l'utiliser car cela semble très utile. Je voulais vérifier et m'assurer de l'utiliser correctement.
Qu'est-ce que je fais:
- Pensez à une nouvelle méthode dont j'ai besoin.
- Créez un test pour cette méthode.
- Échec du test.
- Méthode d'écriture.
- Test de passage.
- Méthode de refactorisation.
- Répéter.
Je fais cela pour CHAQUE méthode que j'écris, y en a-t-il avec qui je ne devrais pas m'embêter? Plus tard, je pense généralement à un moyen de tester mes méthodes déjà existantes d'une manière ou d'une situation différente. Dois-je faire ces nouveaux tests auxquels je pense, ou puisque chaque méthode a déjà son propre test, ne devrais-je pas m'embêter? Puis-je être PLUS de tester mon code, je suppose que c'est ma principale préoccupation en demandant cela.
ÉDITER
Aussi, c'était quelque chose que je me demandais. Lorsque vous faites quelque chose comme faire une interface graphique, le TDD serait-il nécessaire dans cette situation? Personnellement, je ne vois pas comment j'écrirais des tests pour ça.
Réponses:
Ce que vous décrivez comme un flux de travail n'est pas, à mon avis, l' esprit du TDD.
Le synopsis du livre de Kent Becks sur Amazon dit:
TDD pratique
Les tests automatisés formels, en particulier les tests unitaires, chaque méthode de chaque classe est tout aussi mauvais un anti-modèle et ne teste rien. Il y a un équilibre à trouver. Ecrivez-vous des tests unitaires pour chaque
setXXX/getXXX
méthode, ce sont aussi des méthodes!Les tests peuvent également aider à économiser du temps et de l'argent, mais n'oubliez pas qu'ils coûtent du temps et de l'argent à développer et qu'ils sont du code, donc ils coûtent du temps et de l'argent à maintenir. S'ils s'atrophient par manque d'entretien, ils deviennent un passif plus qu'un avantage.
Comme tout comme ça, il y a un équilibre qui ne peut être défini par personne d'autre que vous-même. Tout dogme dans un sens ou dans l'autre est probablement plus faux que correct.
Une bonne métrique est le code qui est essentiel à la logique métier et sujet à des modifications fréquentes en fonction des exigences changeantes. Ces choses nécessitent des tests formels qui sont automatisés, ce serait un gros retour sur investissement.
Vous allez avoir beaucoup de mal à trouver de nombreux magasins professionnels qui fonctionnent de cette façon. Il n'est tout simplement pas logique de dépenser de l'argent pour tester des choses qui, à toutes fins pratiques, ne changeront jamais après un simple test de fumée. La rédaction de tests unitaires formels automatisés pour les
.getXXX/.setXXX
méthodes en est un excellent exemple, une perte de temps totale.Voir aussi cette réponse .
la source
setXXX/getXXX
ne sont pas nécessaires du tout :)Tu es très proche. Essayez de penser de cette manière légèrement différente.
Ne créez pas automatiquement de getters et setters pour chaque propriété . Ne pensez pas à une méthode entière et écrivez le (s) test (s) pour couvrir toutes les fonctionnalités . Essayez d'encapsuler les propriétés à l'intérieur de la classe et d'écrire des méthodes pour fournir le comportement dont vous avez besoin. Laissez vos méthodes évoluer vers une bonne conception au lieu d'essayer de les planifier à l'avance. N'oubliez pas que TDD est un processus de conception et non un processus de test. L'avantage qu'il a sur les autres processus de conception est de laisser derrière lui un flux de tests de régression automatisés, plutôt qu'un morceau de papier que vous jetez à la poubelle.
Souvenez-vous également des trois règles de l'oncle Bob en matière de TDD .
la source
Peu de choses à ajouter aux réponses des autres:
Il y a une telle chose que sur-tester. Vous voulez vous assurer que vos tests unitaires se chevauchent le moins possible. Il est inutile que plusieurs tests vérifient les mêmes conditions dans le même morceau de code. En revanche, lorsque vous refactorisez votre code de production et que vous avez de nombreux tests qui chevauchent cette section, vous devrez revenir en arrière et corriger tous ces tests. Alors que s'ils ne se chevauchent pas, un changement ne pourra au plus casser qu'un seul test.
Tout simplement parce que vous avez pensé à une meilleure façon d'écrire un test, je ne voudrais pas y retourner et commencer à le réécrire. Cela revient aux individus qui continuent d'écrire et de réécrire la même classe / fonction parce qu'ils essaient de la rendre parfaite. Ce ne sera jamais parfait, alors passez à autre chose. Lorsque vous découvrez une meilleure méthode, gardez-la à l'esprit (ou ajoutez-la aux commentaires du test). La prochaine fois que vous êtes là-bas et que vous voyez un avantage immédiat à passer à la nouvelle façon, c'est le moment de refactoriser. Sinon, si la fonctionnalité est terminée et que vous avez continué et que tout fonctionne, laissez-la fonctionner.
TDD se concentre sur la fourniture d'une valeur immédiate, et non simplement sur le fait que chaque fonction est testable. Lorsque vous ajoutez des fonctionnalités, commencez par demander «de quoi a besoin le client». Définissez ensuite une interface pour donner au client ce dont il a besoin. Ensuite, implémentez tout ce qu'il faut pour réussir le test. TDD est presque comme tester des scénarios de cas d'utilisation (y compris tous les "what-ifs"), plutôt que de simplement coder des fonctions publiques et de tester chacun.
Vous avez posé des questions sur le test du code GUI. Recherchez les modèles "Humble Dialog" et "MVVM". L'idée derrière ces deux est que vous créez un ensemble de classes de "modèle de vue", qui n'ont pas réellement de logique spécifique à l'interface utilisateur. Cependant, ces classes auront toute la logique métier qui fait généralement partie de votre interface utilisateur et ces classes doivent pouvoir être testées à 100%. Ce qui reste est un shell d'interface utilisateur très mince et oui, généralement ce shell est laissé sans couverture de test, mais à ce stade, il ne devrait presque pas avoir de logique.
Si vous avez une grande partie du code existant, comme peu d'autres l'ont suggéré, vous ne devriez pas commencer à ajouter des tests unitaires absolument partout. Cela vous prendra une éternité et vous n'aurez aucun avantage à ajouter des tests unitaires à 80% des classes qui sont stables et ne changeront pas dans un avenir proche (ou pas si proche). Cependant, pour de nouveaux travaux, je trouve que l'utilisation du développement TDD avec TOUT le code est extrêmement bénéfique. Non seulement vous vous retrouvez avec une suite de tests automatisés lorsque vous avez terminé, mais le développement réel présente d'énormes avantages:
la source
Il existe certaines méthodes qui ne sont pas testées, à savoir ces tests. Cependant, il y a quelque chose à dire pour certains tests ajoutés après l'écriture du code initial, tels que les conditions aux limites et d'autres valeurs afin qu'il puisse y avoir plusieurs tests sur une seule méthode.
Bien que vous puissiez sur-tester votre code, cela vient généralement là où quelqu'un veut tester toutes les permutations possibles des entrées, ce qui ne ressemble pas vraiment à ce que vous faites. Par exemple, si vous avez une méthode qui prend un caractère, écrivez-vous un test pour chaque valeur possible qui pourrait être entrée? Ce serait là que vous auriez à surestimer, OMI.
la source
En général, vous le faites correctement.
Les tests sont du code. Donc, si vous pouvez améliorer le test, allez-y et refactorisez-le. Si vous pensez qu'un test peut être amélioré, allez-y et changez-le. N'ayez pas peur de remplacer un test par un meilleur.
Je recommande lors du test de votre code, d'éviter de spécifier comment le code est censé faire ce qu'il fait. Les tests devraient examiner les résultats des méthodes. Cela vous aidera à refactoriser. Certaines méthodes n'ont pas besoin d'être testées explicitement (c.-à-d. De simples getters et setters) car vous les utiliserez pour vérifier les résultats d'autres tests.
la source
Mon opinion sur TDD est que l'outillage a créé un monde de développeurs de style «pointer et cliquer». Ce n'est pas parce que les outils créent un talon de test pour chaque méthode que vous devez écrire des tests pour chaque méthode. Certaines personnes «renomment» TDD en BDD (développement axé sur le comportement) où les tests sont beaucoup plus larges et destinés à tester le comportement de la classe, et non chaque petite méthode.
Si vous concevez vos tests pour tester la classe comme elle est destinée à être utilisée, vous commencez à gagner certains avantages, en particulier lorsque vous commencez à écrire des tests qui exercent un peu plus que chaque méthode, en particulier lorsque vous commencez à tester l'interaction de ces méthodes. Je suppose que vous pourriez y penser comme de l'écriture de tests pour une classe, plutôt que de méthodes. Dans tous les cas, vous devez toujours écrire des «tests d'acceptation» qui exercent la combinaison de méthodes pour vous assurer qu'il n'y a pas de contradictions ou de conflits dans la façon dont ils sont utilisés ensemble.
Ne confondez pas TDD avec les tests - ce n'est pas le cas. TDD est conçu pour que vous écriviez du code pour répondre à vos besoins et non pour tester les méthodes. C'est un point subtil mais important qui est souvent perdu pour les personnes qui écrivent aveuglément du code de test pour chaque méthode. C'est que vous devriez écrire des tests pour vous assurer que votre code fait ce que vous voulez qu'il fasse, pas que le code que vous avez écrit fonctionne comme il est censé le faire.
Il existe de bons liens vers la droite sur BDD v TDD. Vérifie-les.
la source
Lorsque vous commencez à apprendre le TDD, oui, vous devez suivre aveuglément l'approche dogmatique de ne pas écrire une seule ligne de code, sauf pour réussir un test échoué, et écrire suffisamment de test pour échouer (et échouer pour la bonne raison / la raison attendue) .
Une fois que vous avez appris ce qu'est le TDD, ALORS vous pouvez décider que certains types de choses ne valent pas la peine d'être testés. C'est la même approche que vous devez suivre pour tout, et les arts martiaux japonais appellent cela " shuhari ". (Le lien explique également comment on peut progresser à travers les étapes de l'apprentissage sans enseignant, ce qui est, je suppose, la façon dont la plupart des gens doivent apprendre.)
la source
Je crois que vous surestimez.
Je pratique le TDD depuis de nombreuses années, et d'après mon expérience, lorsque le TDD est effectué efficacement, vous obtenez deux avantages principaux:
Fournir une rétroaction rapide
En particulier avec les langages dynamiques, je peux exécuter les tests pertinents en moins d'une seconde. Et j'ai des observateurs de système de fichiers qui exécutent ces tests automatiquement lorsqu'un fichier source est modifié sur le disque. Ainsi, je n'ai pratiquement pas de temps d'attente pour les tests, et je sais immédiatement si le code que j'écris a fait comme prévu. TDD conduit ainsi à une manière de travailler très efficace.
Activer le refactoring
Si vous avez une bonne suite de tests, vous pouvez refactoriser en toute sécurité, car vous obtenez de nouvelles informations sur la façon dont le système doit être conçu.
Une bonne suite de tests vous permet de déplacer la responsabilité dans votre code, tout en étant sûr que le code fonctionne comme prévu après le déplacement. Et vous devriez pouvoir le faire avec de petites modifications du code de test.
Si vous écrivez des tests pour chaque méthode de votre système, il y a de fortes chances que vous ne puissiez pas facilement refactoriser votre code, chaque refactoreur de votre code nécessitera des modifications massives du code de test. Et pouvez-vous même être sûr que le code de test fonctionne toujours comme prévu? Ou avez-vous accidentellement introduit un bogue dans le code de test, ce qui conduit par conséquent à un bogue dans le code de production?
Si toutefois, comme le suggère également la réponse de pdr, vous vous concentrez sur le comportement plutôt que sur les méthodes lors de l'écriture des tests, vous aurez des tests qui nécessiteront beaucoup moins de changements lors de la refactorisation du système.
Ou, comme le dit Ian Cooper dans cette présentation (je l'ai cité de mémoire, donc peut-être pas correctement cité):
la source
Vous devez tester chaque méthode publique .
Le problème ici est que si vos méthodes publiques sont très petites, vous exposez probablement trop d'informations. La pratique courante d'exposer chaque propriété comme
getXXX()
rompt réellement l'encapsulation.Si vos méthodes publiques sont en fait le comportement de la classe, vous devez les tester. Sinon, ce ne sont pas de bonnes méthodes publiques.
EDIT: la réponse de pdr est beaucoup plus complète que la mienne.
la source