TDD et contrôle de version

25

J'apprends actuellement le TDD et j'essaie de le mettre en pratique dans mes projets personnels. J'ai également beaucoup utilisé le contrôle de version sur bon nombre de ces projets. Je suis intéressé par l'interaction de ces deux outils dans un flux de travail typique, surtout quand il s'agit de maximiser les commits. Voici quelques exemples qui me viennent à l'esprit:

  1. Je démarre un nouveau projet et j'écris un test simple pour créer une classe encore inexistante. Dois-je valider le test avant d'écrire la classe même si le test ne se compile même pas? Ou dois-je supprimer la quantité minimale de code nécessaire pour que le test soit compilé avant de valider?

  2. Je trouve un bug et écris un test pour le recréer. Dois-je valider le test ayant échoué ou implémenter la correction de bogue, puis valider?

Ce sont les deux exemples qui me viennent immédiatement à l'esprit. N'hésitez pas à fournir des exemples supplémentaires dans votre réponse.

Modifier:

J'ai fait l'hypothèse dans les deux exemples qu'immédiatement après avoir écrit le test, j'écrirai du code pour réussir le test. Une autre situation pourrait également survenir: je travaille sur un projet en utilisant TDD pendant plusieurs heures sans m'engager. Quand je fais enfin des commits, je veux diviser mon travail en petits morceaux. (Git rend cela relativement facile même si vous souhaitez ne valider que certaines des modifications dans un seul fichier.)

Cela signifie que ma question porte autant sur ce qu'il faut engager que sur le moment de s'engager.

Code-Guru
la source

Réponses:

21

Dois-je valider le test avant d'écrire la classe même si le test ne se compile même pas? Ou dois-je supprimer la quantité minimale de code nécessaire pour que le test soit compilé avant de valider?

Bien sûr que non. Vous devez terminer le test et la classe. Commettre quelque chose 1 qui ne compile même pas n'a aucun sens, et mettra certainement les gens travaillant sur le même projet en colère si vous le faites régulièrement.

Je trouve un bug et écris un test pour le recréer. Dois-je valider le test ayant échoué ou implémenter la correction de bogue, puis valider?

Non, ne commettez pas de test ayant échoué. La loi de LeBlanc stipule:

Plus tard n'est jamais égal.

et votre test pourrait échouer pendant longtemps. Il est préférable de résoudre le problème dès qu'il est détecté.

En outre, le style de développement TDD indique:

Le développement piloté par les tests répète constamment les étapes d'ajout de cas de test qui échouent, de leur réussite et de la refactorisation.

Si vous enregistrez un test qui a échoué, cela signifie que vous n'avez pas terminé le cycle.


1 Quand j'ai dit commit, je voulais dire vraiment commit sur le tronc (pour les utilisateurs de git, poussez vos modifications, afin que d'autres développeurs les obtiennent).

BЈовић
la source
4
"et rendra certainement les gens en colère travaillant sur le même projet si" - quelqu'un vivant dans le monde SVN utilise GIT et vous ne
Mateusz
3
Je pense que commettre est bien après avoir écrit un test, ne le poussez pas tant que vous n'avez pas terminé.
Matsemann
4
@radarbob Est-ce que cela s'applique même pour un DVCS où il y a une distinction entre commettre et pousser? Je peux imaginer une situation où je fais plusieurs commits à mon dépôt git local où, lors du commit final, la build n'est pas interrompue, mais à n'importe quel commit provisoire, cela pourrait être le cas.
Code-Guru
6
Non, ne validez pas le test. Mais l'un des points du TDD est justement de faire un test raté avant de coder. Il est donc logique de valider un test qui échoue.
mouviciel
4
@ Code-Guru: Pour un DVCS, ces règles devraient être: "Ne pas commettre de code cassé dans une branche dont d'autres tirent régulièrement". Si d'autres ne se retirent pas de votre dépôt local, cela peut être dans n'importe quel état avec lequel vous pouvez vivre.
Bart van Ingen Schenau
6

Dois-je valider le test avant d'écrire la classe même si le test ne se compile même pas?

Non.

Dois-je commettre l'échec du test

Non.

Vous parlez de deux paradigmes ici:

  1. développement piloté par les tests - qui ne dit rien sur la validation du code. En effet, il vous indique comment écrire du code et quand vous avez terminé. Je considérerais donc chaque «fait» comme un candidat à un engagement.
  2. développement agile, plus précisément: "s'engager tôt et souvent" (ce qui ne nécessite pas TDD). L'idée sous-jacente est d'avoir une intégration précoce avec d'autres composants du système et ainsi obtenir un retour d'information précoce. Si vous vous engagez dans un DVCS localement et que vous ne poussez pas, cela ne vaut rien dans ce sens. Les validations locales aident uniquement les développeurs à structurer leur travail.

Ma recommandation est: suivez le cercle de TDD jusqu'à ce que votre code soit compilé, vos tests soient verts et vous avez quelque chose à apporter au système. Par conséquent, vous devez couper vos fonctionnalités verticalement, par exemple pour un nouveau masque d'interface utilisateur, ne créez pas le formulaire entier et ne vous engagez pas sans la logique métier, mais implémentez plutôt un petit aspect mais dans le frontend ainsi que la logique métier ainsi que dans la couche de persistance .

Pour un gros bug corrigé, validez après chaque amélioration (par exemple refactoring), même si le bug n'est pas encore corrigé. Les tests doivent être verts et le code doit cependant être compilé.

Andy
la source
5

Vous commencez certainement par utiliser un contrôle de source sain comme git.

Ensuite, vous pouvez travailler comme vous le souhaitez et vous engager à chaque coin - chaque étape ou sous-étape est un jeu équitable.

Ensuite, avant de pousser le contenu, vous écrasez l'ensemble du travail en un seul commit. Ou en couple, à des points où tout est vert et où la composition a du sens. Et poussez ces engagements raisonnables. Pour le cas multiple, faites-en une branche avec laquelle vous fusionnez --no-ff.

Le contrôle de source n'est pas un système de suivi des travaux ou un historien. Les validations doivent présenter un delta cohérent sensible, tandis que l'état de vérification doit être compilé au moins. Les intermédiaires peuvent être conservés pendant un certain temps à des fins d'examen, mais une fois que tout est jugé correct, un seul commit par fonctionnalité est équitable.

Balog Pal
la source
5

C'est ma compréhension du monde que l'on s'engage à marquer un point sur lequel il peut être souhaitable de revenir. Le point a auquel un test échoue (mais se compile) en est certainement un. Si je devais errer dans la mauvaise direction en essayant de réussir un test, je voudrais pouvoir ramener le code au point de départ et réessayer; Je ne peux pas faire ça si je ne me suis pas engagé.

Scroog1
la source
Je suis d'accord avec toi. Je préfère utiliser une branche différente pour suivre la règle "ne pas casser la construction" et fusionner les modifications dans le coffre uniquement lorsque le test réussit.
Fil
5

Dois-je valider le test avant d'écrire la classe même si le test ne se compile même pas?

Avec un SCM de branchement (je vous ai vu utiliser Git), vous devez valider chaque fois que vous voulez un point de sauvegarde ("J'ai foiré quelque chose; je vais réinitialiser le répertoire de travail au dernier point de sauvegarde") ou lorsque vous avez une version stable. Lorsque vous avez une version stable (tous les tests réussissent), vous devriez également envisager de fusionner la branche de fonctionnalité actuelle dans votre branche de développement principale.

Ou dois-je supprimer la quantité minimale de code nécessaire pour que le test soit compilé avant de valider?

À vous de choisir (git vous donne la flexibilité de vous engager quand vous le souhaitez sans affecter les autres membres de votre équipe, ou votre capacité à travailler sur différentes fonctionnalités). Assurez-vous simplement que vous n'avez pas plusieurs fonctionnalités incomplètes (non fonctionnelles) dans la même branche en même temps (elles se bloqueront alors).

Je trouve un bug et écris un test pour le recréer. Dois-je valider le test ayant échoué ou implémenter la correction de bogue, puis valider?

Je fais généralement deux commits pour cela, sauf si le code de test est vraiment petit / trivial à écrire.

Ce sont les deux exemples qui me viennent immédiatement à l'esprit. N'hésitez pas à fournir des exemples supplémentaires dans votre réponse.

Modifier:

J'ai fait l'hypothèse dans les deux exemples que, immédiatement après avoir écrit le test, j'écrirai du code pour réussir le test.

Cela pourrait être une mauvaise hypothèse. Si vous travaillez seul (projet personnel), rien ne vous empêche de toujours le faire. Dans l'un de mes projets les plus réussis (en ce qui concerne le maintien d'une haute qualité de code et de TDD tout au long du développement du projet), nous avons défini des tests parfois des semaines avant de les implémenter (c'est-à-dire que "le test" test_FOO_with_null_first_parameter "est maintenant défini comme une fonction vide et ensuite, nous prenions un sprint (ou un demi-sprint) parfois un mois plus tard, pour simplement augmenter la couverture des tests pour le module. Comme nous avions déjà déclaré les tests, c'était facile à estimer.

Une autre situation pourrait également survenir: je travaille sur un projet en utilisant TDD pendant plusieurs heures sans m'engager. Quand je fais enfin des commits, je veux diviser mon travail en petits morceaux. (Git rend cela relativement facile même si vous souhaitez ne valider que certaines des modifications dans un seul fichier.) Cela signifie que ma question concerne autant ce qu'il faut valider que le moment où le valider.

Je dirais que je m'engage définitivement à créer des points de sauvegarde . Cela fonctionne très bien pour les tests exploratoires ("Je vais simplement ajouter quelques impressions dans la base de code, les exécuter et git reset --hardles supprimer lorsque j'ai terminé) et pour le prototypage.

utnapistim
la source
2
Soyez prudent lorsque vous recommandez git reset --hard. C'est l'une des rares commandes de git qui vous fera perdre du travail.
gnash117
2

Dans mon flux de travail, chaque fois que possible, je fais un travail incertain sur une branche personnelle de contrôle des sources. Je peux donc essayer, échouer, réessayer si nécessaire jusqu'à ce que cela fonctionne, et ne m'engager dans le projet plus grand que lorsque j'ai du code de travail réel.

Du point de vue de TDD, la question de "vous enregistrez-vous d'abord le test?" dépend entièrement du code sur lequel vous travaillez. S'il s'agit d'un nouveau code, vous ne consignez rien tant que vous n'avez pas quelque chose qui mérite d'être enregistré. Mais s'il s'agit d'un bogue trouvé dans du code déjà compilé ou expédié, archiver un test pour reproduire le bogue, BY ITSELF, vaut la peine d'être vérifié. Surtout si c'est la fin d'une journée de travail et que vous quitterez le bureau avant de corriger le code.

(Bien sûr, si votre boutique a un processus de construction automatisé qui meurt si des tests unitaires échouent, vous ne voudrez peut-être pas archiver un test qui échoue jusqu'à ce que vous corrigiez le bogue. Mais cela semble être une façon étrange de travailler, car "trouver et documenter les bogues "et" corriger les bogues "peuvent être effectués par deux équipes entièrement différentes.)

DougM
la source