Supposons que nous ayons une grande application de niveau entreprise sans tests unitaires / fonctionnels. Il n'y a pas eu de processus de développement piloté par les tests pendant le développement en raison de délais très serrés (je sais que nous ne devrions jamais promettre de délais serrés lorsque nous ne sommes pas sûrs, mais ce qui est fait est fait!)
Maintenant que tous les délais sont passés et que les choses sont calmes, tout le monde a accepté de nous transformer en une équipe productive basée sur TDD / BDD ... Ouais!
Maintenant, la question porte sur le code que nous avons déjà: (1) Est-ce toujours correct ou une bonne idée d'arrêter la plupart du développement et de commencer à écrire des scénarios de test possibles depuis le début, même si tout fonctionne complètement OKAY (encore!) ? Ou (2) il vaut mieux attendre que quelque chose se passe mal, puis pendant le correctif, écrivez de nouveaux tests unitaires, ou (3) oubliez même les codes précédents et écrivez simplement les tests unitaires pour les nouveaux codes uniquement et reportez tout au prochain refactor majeur.
Il y a quelques bons articles connexes comme celui-ci . Je ne sais toujours pas s'il vaut la peine d'investir dans ce domaine étant donné que nous avons un temps très limité et de nombreux autres projets / travaux nous attendent.
Remarque : Cette question explique / imagine une situation totalement délicate dans une équipe de développement. Cela ne concerne ni moi ni aucun de mes collègues; c'est juste une situation imaginaire. Vous pensez peut-être que cela ne devrait jamais arriver ou que le responsable du développement est responsable d'un tel gâchis! Mais de toute façon, ce qui est fait est fait. Si possible, ne votez pas simplement parce que vous pensez que cela ne devrait jamais se produire.
la source
int
valeur et retournera quelque chose de spécifique, il n'est pas possible d'écrire un test unitaire pour chaqueint
valeur possible , mais il est probablement logique de tester une poignée de valeurs utiles qui pourraient déclencher code, tels que les nombres négatifs (y comprisminint
), zéromaxint
, etc. pour vous assurer que certains cas de bord sont couverts.Réponses:
Cette déclaration est très préoccupante. Non pas parce que cela signifie que vous avez développé sans TDD ou parce que vous ne testez pas tout. C'est inquiétant, car cela montre que vous pensez que TDD vous ralentira et vous fera manquer un délai.
Tant que vous le voyez de cette façon, vous n'êtes pas prêt pour TDD. Le TDD n'est pas quelque chose que vous pouvez progressivement maîtriser. Soit vous savez comment le faire, soit vous ne le savez pas. Si vous essayez de le faire à mi-chemin, vous allez le faire et vous-même paraître mauvais.
TDD est quelque chose que vous devez d'abord pratiquer à la maison. Apprenez à le faire, car cela vous aide à coder maintenant . Pas parce que quelqu'un vous a dit de le faire. Pas parce que cela vous aidera lorsque vous apporterez des modifications ultérieurement. Lorsque cela devient quelque chose que vous faites parce que vous êtes pressé, vous êtes prêt à le faire de manière professionnelle.
TDD est quelque chose que vous pouvez faire dans n'importe quel magasin. Vous n'avez même pas à rendre votre code de test. Vous pouvez le garder pour vous si les autres dédaignent les tests. Lorsque vous le faites correctement, les tests accélèrent votre développement même si personne d'autre ne les exécute.
D'un autre côté, si d'autres aiment et exécutent vos tests, vous devez toujours garder à l'esprit que même dans un magasin TDD, ce n'est pas votre travail de vérifier les tests. Il s'agit de créer un code de production éprouvé. Si cela peut être testé, c'est bien.
Si vous pensez que la direction doit croire en TDD ou que vos collègues codeurs doivent prendre en charge vos tests, vous ignorez la meilleure chose que TDD fait pour vous. Il vous montre rapidement la différence entre ce que vous pensez que votre code fait et ce qu'il fait réellement.
Si vous ne voyez pas comment cela, à lui seul, peut vous aider à respecter un délai plus rapidement, alors vous n'êtes pas prêt pour TDD au travail. Vous devez vous entraîner à la maison.
Cela dit, c'est bien quand l'équipe peut utiliser vos tests pour les aider à lire votre code de production et quand la direction achètera de nouveaux outils TDD.
Peu importe ce que fait l'équipe, ce n'est pas toujours une bonne idée d'écrire tous les cas de test possibles. Écrivez les cas de test les plus utiles. La couverture à 100% du code a un coût. N'ignorez pas la loi des rendements décroissants simplement parce qu'il est difficile d'émettre un jugement.
Économisez votre énergie de test pour la logique métier intéressante. Le truc qui prend des décisions et applique la politique. Testez le diable de cela. Un code de colle structurelle évident et facile à lire qui ne fait que câbler des éléments n'a pas besoin d'être testé aussi mal.
Non, c'est la pensée "faisons une réécriture complète". Cela détruit les connaissances durement acquises. Ne demandez pas à la direction le temps d'écrire des tests. Écrivez simplement des tests. Une fois que vous savez ce que vous faites, les tests ne vous ralentiront pas.
Je répondrai 2 et 3 de la même manière. Lorsque vous changez le code, pour une raison quelconque, c'est vraiment bien si vous pouvez glisser un test. Si le code est hérité, il n'accueille actuellement pas de test. Ce qui signifie qu'il est difficile de le tester avant de le changer. Eh bien, puisque vous le changez de toute façon, vous pouvez le changer en quelque chose de testable et le tester.
C'est l'option nucléaire. C'est risqué. Vous apportez des modifications sans tests. Il existe quelques astuces créatives pour tester le code hérité avant de le modifier. Vous recherchez ce que l'on appelle des coutures qui vous permettent de modifier le comportement de votre code sans changer le code. Vous modifiez les fichiers de configuration, créez des fichiers, tout ce qu'il faut.
Michael Feathers nous a donné un livre à ce sujet: Travailler efficacement avec le code hérité . Lisez-le et vous verrez que vous n'avez pas à brûler tout ce qui est ancien pour faire quelque chose de nouveau.
la source
Étant donné le code hérité 1 , écrivez des tests unitaires dans ces situations:
Aussi utile que les tests unitaires sont la création d' une complète suite de tests unitaires pour un existant 1 codeBase probablement n'est pas une idée réaliste. Les pouvoirs en place vous ont poussé à respecter un délai serré. Ils ne vous ont pas laissé le temps de créer des tests unitaires adéquats pendant votre développement. Pensez-vous qu'ils vous donneront suffisamment de temps pour créer des tests pour le "programme qui fonctionne"?
1 Le code hérité est le code sans tests unitaires. Il s'agit de la définition TDD du code hérité. Il s'applique même si le code hérité est fraîchement livré [même si l'encre n'a pas encore séché].
la source
D'après mon expérience, les tests n'ont pas besoin d'une couverture totale pour être utiles. Au lieu de cela, vous commencez à récolter différents types d'avantages à mesure que la couverture augmente:
La vérité est que si vous ne commencez pas avec BDD, vous n'y arriverez jamais, car le travail requis pour tester après le codage est simplement excessif. Le problème n'est pas d' écrire les tests, mais plus encore d'être conscient des exigences réelles (plutôt que des détails d'implémentation fortuits) et de pouvoir concevoir le logiciel de manière à la fois fonctionnelle et facile à tester. Lorsque vous écrivez les tests en premier ou avec le code, cela est pratiquement gratuit.
Étant donné que les nouvelles fonctionnalités nécessitent des tests, mais que les tests nécessitent des modifications de conception, mais que la refactorisation nécessite également des tests, vous avez un peu un problème de poule et d'oeuf. À mesure que votre logiciel se rapproche d'une couverture décente, vous devrez effectuer une refactorisation minutieuse dans les parties du code où de nouvelles fonctionnalités se produisent, juste pour rendre les nouvelles fonctionnalités testables. Cela vous ralentira beaucoup - au début. Mais en ne refactorisant et en testant que les pièces où un nouveau développement est nécessaire, les tests se concentrent également sur le domaine où ils sont le plus nécessaires. Le code stable peut continuer sans tests: s'il était bogué, il faudrait quand même le changer.
Pendant que vous essayez de vous adapter au TDD, une meilleure mesure que la couverture totale du projet serait la couverture du test dans les parties qui sont modifiées. Cette couverture devrait être très élevée dès le départ, bien qu'il ne soit pas possible de tester toutes les parties du code impactées par une refactorisation. En outre, vous bénéficiez de la plupart des avantages d'une couverture de test élevée au sein des composants testés. Ce n'est pas parfait, mais tout de même assez bon.
Notez que bien que les tests unitaires semblent être courants, commencer par les plus petites pièces n'est pas une stratégie appropriée pour tester un logiciel hérité. Vous voudrez commencer par des tests d'intégration qui exercent une grande partie du logiciel à la fois.
Par exemple, j'ai trouvé utile d'extraire des cas de test d'intégration à partir de fichiers journaux réels. Bien sûr, l'exécution de ces tests peut prendre beaucoup de temps, c'est pourquoi vous pouvez configurer un serveur automatisé qui exécute les tests régulièrement (par exemple, un serveur Jenkins déclenché par des validations). Le coût d'installation et de maintenance d'un tel serveur est très faible par rapport à la non-exécution régulière des tests, à condition que les échecs des tests soient résolus rapidement.
la source
N'écrivez pas de tests pour le code existant. Ça ne vaut pas le coup.
Ce que vous avez fait est déjà quelque peu testé de manière complètement informelle - vous l'avez constamment essayé à la main, les gens ont fait des tests non automatisés, il est utilisé maintenant. Cela signifie que vous ne trouverez pas beaucoup de bugs .
Il ne reste que les bugs auxquels vous n'avez pas pensé. Mais ce sont exactement ceux pour lesquels vous ne penserez pas écrire des tests unitaires, vous ne les trouverez donc probablement pas.
En outre, une raison pour TDD est de vous faire réfléchir sur les exigences exactes d'un peu de code avant de l'écrire. De quelque manière que ce soit, vous l'avez déjà fait.
En attendant, écrire ces tests demande toujours autant de travail que cela aurait été le cas auparavant. Cela coûtera beaucoup de temps, pour peu d'avantages.
Et c'est extrêmement ennuyeux d'écrire des tas de tests sans codage entre les deux et ne trouvant pratiquement aucun bogue. Si vous commencez à le faire, les nouveaux venus chez TDD le détesteront .
En bref, les développeurs le détesteront et les gestionnaires le verront comme coûteux, alors qu'il n'y a pas beaucoup de bogues trouvés. Vous n'obtiendrez jamais à la partie TDD réelle.
Utilisez-le sur les choses que vous souhaitez modifier, dans le cadre normal du processus.
la source
Un test est un moyen de communiquer la compréhension.
Par conséquent, seuls les tests pour ce que vous comprenez doivent être vrais.
Vous ne pouvez comprendre ce qui devrait être vrai que lorsque vous travaillez avec.
N'écrivez donc que des tests pour le code avec lequel vous travaillez.
Lorsque vous travaillez avec le code, vous apprendrez.
Par conséquent, écrivez et réécrivez des tests pour capturer ce que vous avez appris.
Rincez et répétez.
Exécutez un outil de couverture de code avec vos tests et acceptez uniquement les validations sur la ligne principale qui ne réduisent pas la couverture. Finalement, vous atteindrez un niveau de couverture élevé.
Si vous n'avez pas travaillé avec le code depuis un certain temps, une décision commerciale doit être prise. Il est peut-être maintenant si hérité que personne dans votre équipe ne sait comment travailler avec. Il a probablement des bibliothèques / compilateurs / documentation obsolètes, ce qui représente une responsabilité énorme à presque tous les égards.
Deux options:
la source
L'un des principaux objectifs des tests est de s'assurer qu'un changement n'a rien cassé. Il s'agit d'un processus en trois étapes:
Cela signifie que vous devez avoir des tests de travail avant de réellement changer quelque chose. Si vous choisissez le deuxième chemin, cela signifie que vous devrez forcer vos développeurs à écrire des tests avant même qu'ils ne touchent le code. Et je soupçonne fortement que lorsqu'ils sont déjà confrontés à un changement dans le monde réel, les développeurs ne vont pas accorder aux tests unitaires l'attention qu'ils méritent.
Je suggère donc de diviser les tâches d'écriture de test et de modification pour éviter que les développeurs ne sacrifient la qualité de l'un pour l'autre.
Juste pour le signaler spécifiquement, c'est une idée fausse courante que vous n'avez besoin de tests que lorsque le code ne fonctionne pas. Vous avez également besoin de tests lorsque le code fonctionne, par exemple pour prouver à quelqu'un que [le nouveau bug qui se produit] n'est pas dû à votre partie car les tests sont toujours réussis.
Confirmer que tout fonctionne toujours comme avant était un avantage important des tests que vous omettez lorsque vous indiquez que vous n'avez pas besoin de tests lorsque le code fonctionne.
Idéalement, tout le code source existant devrait maintenant recevoir des tests unitaires. Cependant, il existe un argument raisonnable selon lequel le temps et les efforts (et les coûts) nécessaires pour le faire ne sont tout simplement pas pertinents pour certains projets.
Par exemple, une application qui n'est plus en cours de développement et qui ne devrait plus être modifiée (par exemple, le client ne l'utilise plus ou le client n'est plus un client), vous pouvez faire valoir qu'il n'est plus pertinent de tester ce code plus .
Cependant, ce n'est pas aussi clair où vous tracez la ligne. C'est quelque chose qu'une entreprise doit examiner dans une analyse coûts-avantages. L'écriture de tests coûte du temps et des efforts, mais s'attendent-ils à un développement futur de cette application? Les gains des tests unitaires l'emportent-ils sur le coût de leur rédaction?
Ce n'est pas une décision que vous (en tant que développeur) pouvez prendre. Au mieux, vous pouvez offrir une estimation du temps nécessaire pour mettre en œuvre des tests sur un projet donné, et c'est à la direction de décider s'il y a une attente suffisante d'avoir réellement besoin de maintenir / développer le projet.
Si le prochain refactor majeur est une donnée, vous devez en effet écrire les tests.
Mais ne le remettez pas avant que vous ne soyez confronté à des changements majeurs. Mon point de départ (ne pas combiner l'écriture de tests et la mise à jour du code) est toujours valable, mais je veux ajouter un deuxième point ici: vos développeurs connaissent actuellement mieux leur chemin dans le projet qu'ils ne le seront en six mois s'ils passent ce temps à travailler sur d'autres projets. Tirez parti des périodes où les développeurs sont déjà au chaud et n'ont pas besoin de comprendre comment les choses fonctionneront à nouveau à l'avenir.
la source
Mes deux centimes:
Attendez une mise à niveau technique majeure du système et écrivez ensuite les tests ... officiellement avec le soutien de l'entreprise.
Alternativement, disons que vous êtes un magasin SCRUM, votre charge de travail est représentée par la capacité et vous pouvez allouer un% de cela aux tests unitaires, mais ...
Dire que vous allez revenir en arrière et écrire les tests est naïf, ce que vous allez vraiment faire est d'écrire des tests, de refactoriser et d'écrire plus de tests après que le refactor a rendu le code plus testable, c'est pourquoi il est préférable de commencer avec des tests comme vous le savez déjà, et ...
Il est préférable que l'auteur d'origine écrive des tests et remanie le code qu'ils ont écrit précédemment, ce n'est pas l'idéal, mais d'après l'expérience, vous voulez que le refactoriste améliore le code et n'empire pas.
la source