Je suis développeur solo dans un environnement de travail assez contraint où le temps de développement varie généralement entre 1 et 4 semaines par projet, en fonction des besoins, de l'urgence ou des deux. À tout moment, je gère environ 3 ou 4 projets, certains ayant des échéances qui se chevauchent.
De manière attendue, la qualité du code en souffre. Je n'ai pas non plus de test formel; il faut généralement marcher dans le système jusqu'à ce qu'il se casse un peu. En conséquence, un nombre considérable de bugs s'échappent en production, ce que je dois corriger et retarde à mon tour mes autres projets.
C’est là que les tests unitaires entrent en jeu. Lorsque cela est fait correctement, il convient de limiter au minimum les bugs, sans parler de ceux qui échappent à la production. Par ailleurs, la rédaction de tests peut prendre un temps considérable, ce qui ne sonne pas très bien avec des projets tels que le mien, qui sont soumis à des contraintes de temps.
La question est de savoir quelle différence de temps l'écriture de code testé par unités par rapport à un code non testé, et comment cette différence de temps peut-elle être élargie à mesure que la portée du projet s'élargit?
Réponses:
Plus vous testez tard, plus il vous en coûtera pour écrire des tests.
Plus un bogue dure longtemps, plus il est coûteux de le réparer.
La loi des rendements décroissants garantit que vous pouvez vous mettre à l’essai en essayant de vous assurer qu’il n’ya pas de bugs.
Bouddha a enseigné la sagesse de la voie médiane. Les tests sont bons. Il y a une telle chose comme trop d'une bonne chose. La clé est de pouvoir savoir quand vous êtes en déséquilibre.
Chaque ligne de code que vous écrivez sans test entraînera des coûts beaucoup plus élevés pour l'ajout de tests plus tard que si vous aviez écrit les tests avant l'écriture du code.
Chaque ligne de code sans test sera beaucoup plus difficile à déboguer ou à réécrire.
Chaque test que vous écrivez prendra du temps.
Chaque bug prendra du temps à corriger.
Les fidèles vous diront de ne pas écrire une seule ligne de code sans avoir au préalable écrit un test ayant échoué. Le test garantit que vous obtenez le comportement que vous attendez. Il vous permet de changer le code rapidement sans vous soucier du reste du système, car le test prouve que le comportement est le même.
Vous devez peser tout cela contre le fait que les tests n’ajoutent pas de fonctionnalités. Le code de production ajoute des fonctionnalités. Et ce sont les fonctionnalités qui paient les factures.
De manière pragmatique, j'ajoute tous les tests possibles. J'ignore les commentaires en faveur de regarder les tests. Je ne fais même pas confiance au code pour faire ce que je pense qu'il fait. Je fais confiance aux tests. Mais on m'a appris à lancer de temps en temps la grêle et à avoir de la chance.
Cependant, beaucoup de codeurs qui réussissent ne font pas de TDD. Cela ne signifie pas qu'ils ne testent pas. Ils n’insistent tout simplement pas pour que chaque ligne de code soit testée automatiquement. Même oncle Bob admet qu'il ne teste pas son interface utilisateur. Il insiste également pour que vous déplaciez toute logique en dehors de l'interface utilisateur.
En tant que métaphore du football (c'est le football américain), TDD est un bon jeu au sol. Les tests manuels uniquement lorsque vous écrivez une pile de code et espérez que cela fonctionne est un jeu passager. Vous pouvez être bon à l'un ou l'autre. Votre carrière ne fera les séries que si vous pouvez faire les deux. Cela ne fera pas le superbowl jusqu'à ce que vous sachiez quand choisir chacun. Mais si vous avez besoin d'un coup de pouce dans une direction particulière: les appels des officiels vont plus souvent contre moi lorsque je passe.
Si vous voulez essayer TDD, je vous recommande vivement de vous entraîner avant d'essayer de le faire au travail. TDD fait à mi-chemin, mi-cœur, et moitié assed est une raison majeure pour laquelle certains ne le respectent pas. C'est comme verser un verre d'eau dans un autre. Si vous ne vous engagez pas et que vous le faites rapidement et complètement, vous finissez par dribbler de l'eau sur toute la table.
la source
Je suis d’accord avec le reste des réponses mais je réponds directement à la question du décalage horaire .
Dans son ouvrage intitulé The Art of Unit Testing, deuxième édition, page 200, Roy Osherove a mené une étude de cas sur la mise en œuvre de projets de taille similaire avec des équipes similaires (en termes de compétences) pour deux clients différents.
Ses résultats étaient comme suit:
Ainsi, à la fin d'un projet, vous obtenez à la fois moins de temps et moins de bugs. Cela dépend bien sûr de la taille du projet.
la source
Il n'y a qu'une une étude que je connaisse qui a étudié cela dans un « monde réel réglage »: Se rendant compte amélioration de la qualité par le développement piloté par les tests: les résultats et les expériences des quatre équipes industrielles . Cela coûte cher de le faire de façon sensée, car cela signifie en gros que vous devez développer le même logiciel deux fois (ou idéalement même plus souvent) avec des équipes similaires, puis tout jeter sauf un.
Les résultats de l'étude ont été une augmentation du temps de développement comprise entre 15% et 35% (ce qui est loin du chiffre 2x souvent cité par les critiques de TDD) et une diminution de la densité de défauts avant publication de 40% à 90% (! ) Notez que toutes les équipes n’ayant aucune expérience préalable en TDD, on peut donc supposer que l’augmentation du temps peut au moins en partie être attribuée à l’apprentissage, et qu’elle diminuerait donc avec le temps, mais cela n’a pas été évalué par l’étude.
Notez que cette étude concerne le TDD, et votre question concerne les tests unitaires, qui sont des choses très différentes, mais c’est le test le plus proche que je puisse trouver.
la source
null
, fonctionnel sur l'impératif, contrats de code, analyse statique, refactoring automatisé, pas de conteneurs IoC (mais DI), etc. Je parie que la valeur des tests unitaires diminuerait (mais ne disparaîtrait pas).Bien fait, le développement avec des tests unitaires peut être plus rapide même sans considérer les avantages des extras bugs capturés.
Le fait est que je ne suis pas assez bon codeur pour que mon code fonctionne dès sa compilation. Lorsque j'écris / modifie du code, je dois l'exécuter pour m'assurer qu'il fait ce que je pensais. À un projet, cela avait tendance à ressembler à:
Et bien sûr, après tout cela, il fallait généralement quelques allers-retours pour bien faire les choses.
Maintenant, que se passe-t-il si j'utilise des tests unitaires? Ensuite, le processus ressemble plus à:
C'est plus facile et plus rapide que de tester manuellement l'application. Je dois encore exécuter manuellement l’application (donc je n’ai pas l’air idiot de rendre un travail qui ne fonctionne pas du tout), mais la plupart du temps, j’ai déjà résolu les problèmes, et j’ai vérifier à ce point. Généralement, je resserre encore davantage cette boucle en utilisant un programme qui relance automatiquement mes tests lorsque je sauvegarde.
Toutefois, cela dépend du travail dans une base de code conviviale pour les tests. De nombreux projets, même ceux comportant de nombreux tests, rendent la rédaction de tests difficile. Mais si vous y travaillez, vous pouvez avoir une base de code plus facile à tester avec des tests automatisés qu'avec des tests manuels. En prime, vous pouvez conserver les tests automatisés et les exécuter pour éviter les régressions.
la source
Bien qu'il y ait déjà beaucoup de réponses, elles sont quelque peu répétitives et je voudrais adopter une approche différente. Les tests unitaires sont précieux, si et seulement si , ils augmentent la valeur commerciale . Tester à des fins de test (tests triviaux ou tautologiques), ou pour atteindre une mesure arbitraire (comme la couverture de code), est une programmation culte du fret.
Les tests sont coûteux, non seulement en temps, mais en maintenance. Ils doivent rester synchronisés avec le code qu'ils testent ou ils ne valent rien. Sans parler du temps nécessaire pour les exécuter à chaque changement. Ce n'est pas une rupture de marché (ni une excuse pour ne pas faire les choses vraiment nécessaires), mais il faut en tenir compte dans l'analyse coûts-avantages.
Donc, la question à poser lorsque vous décidez si vous voulez ou non (ou de quel type) tester une fonction / méthode, posez-vous la question suivante: "quelle valeur d'utilisateur final est-ce que je crée / sauvegarde avec ce test?". Si vous ne pouvez pas répondre à cette question, du haut de votre tête , puis ce test risque ne vaut pas le coût de l' écriture / maintien. (ou vous ne comprenez pas le domaine du problème, qui est un problème beaucoup plus important qu'un manque de tests).
http://rbcs-us.com/documents/Why-Most-Unit-Testing-is-Waste.pdf
la source
Cela dépend de la personne, de la complexité et de la forme du code avec lequel vous travaillez.
Pour moi, dans la plupart des projets, écrire des tests unitaires signifie que le travail est fait environ 25% plus rapidement. Oui, même y compris le temps nécessaire pour écrire les tests.
Parce que le fait est que le logiciel n'est pas terminé lorsque vous écrivez le code. C'est fait lorsque vous l'envoyez au client et celui-ci en est satisfait. Les tests unitaires sont de loin le moyen le plus efficace que je connaisse pour attraper la plupart des bogues, isoler la plupart des bogues pour le débogage et gagner la confiance que le code est bon. Vous devez faire ces choses de toute façon , alors faites-les bien.
la source
Le problème s'aggrave à mesure que l'âge du projet augmente: parce que chaque fois que vous ajoutez une nouvelle fonctionnalité et / ou que vous modifiez la mise en œuvre existante, vous devez tester à nouveau ce qui a déjà été testé pour vous assurer qu'il fonctionne toujours. Ainsi, pour un projet de longue durée (pluriannuel), vous devrez peut-être non seulement tester les fonctionnalités, mais aussi les tester à nouveau 100 fois et plus. Pour cette raison, vous pourriez bénéficier de tests automatisés . Cependant, IMO est assez bon (ou même meilleur) si ce sont des tests système automatisés, plutôt que des tests unitaires automatisés.
Un deuxième problème est que les bogues peuvent être plus difficiles à trouver et à corriger s'ils ne sont pas détectés tôt. Par exemple, s'il y a un bogue dans le système et que je sais qu'il fonctionnait parfaitement avant que vous n'ayez effectué votre dernier changement, je concentrerai alors mon attention sur votre dernier changement pour voir comment il aurait pu introduire le bogue. Mais si je ne savais pas que le système fonctionnait avant que vous n'ayez effectué votre dernière modification (car le système n'a pas été correctement testé avant votre dernière modification), le bogue pourrait se situer n'importe où.
Ce qui précède s’applique en particulier au code profond et moins au code superficiel, par exemple en ajoutant de nouvelles pages Web lorsque les nouvelles pages n’affecteront probablement pas les pages existantes.
D'après mon expérience, ce serait inacceptable et vous posez la mauvaise question. Au lieu de demander si les tests rendraient le développement plus rapide, vous devriez vous demander ce qui rendrait le développement plus exempt de bogues.
Une meilleure question pourrait être:
L'apprentissage est un processus en deux étapes: apprenez à le faire assez bien, puis apprenez à le faire plus rapidement.
la source
Quelques aspects à considérer, non mentionnés dans les autres réponses.
Sommaire
Lorsque vous commencez avec tdd, il est difficile d'atteindre l'état "plus d'avantages que de coûts" tant que vous êtes dans un "environnement de travail contraint", surtout s'il existe des "gestionnaires intelligents" qui vous disent de "vous débarrasser de la tester des trucs "
Remarque: par "tests unitaires", je veux dire "tests de modules isolés".
Note: avec "test de régression" je veux dire
la source
Les programmeurs, comme ceux qui s’occupent de la plupart des tâches, sous-estiment le temps qu’il faut pour s’acquitter de cette tâche. En gardant cela à l'esprit, passer 10 minutes à écrire un test peut être considéré comme du temps que l'on aurait pu consacrer à écrire des tonnes de code alors qu'en réalité, vous auriez passé ce temps à définir le même nom de fonction et les mêmes paramètres que lors du test. . Ceci est un scénario TDD.
Ne pas passer de test, c'est un peu comme avoir une carte de crédit. nous avons tendance à dépenser plus ou à écrire plus de code. Plus de code a plus de bugs.
Au lieu de décider d’avoir une couverture totale ou aucune couverture de code, je suggère de mettre l’accent sur la partie critique et compliquée de votre application et d’y effectuer des tests. Dans une application bancaire, cela pourrait être le calcul de l'intérêt. Un outil de diagnostic moteur peut avoir des protocoles d'étalonnage complexes. Si vous avez travaillé sur un projet, vous savez probablement de quoi il s'agit et où se trouvent les bugs.
Commencez lentement. Construisez un peu de fluidité avant de juger. Tu peux toujours t'arrêter.
la source
Il y a longtemps que les programmeurs promeuvent le TDD et d'autres méthodologies de test. Je ne me souviendrai pas de leurs arguments et ne les approuve pas, mais voici quelques éléments supplémentaires à prendre en compte qui devraient être légèrement nuancés:
Je dirais que les tests sont bons, mais assurez-vous de les tester tôt et de déterminer le gain.
la source
mainTest()
qui appelle tous vos modules de test n'est pas si difficile.Un avantage souvent négligé de TDD est que les tests agissent comme une sauvegarde pour vous assurer que vous n'introduisez pas de nouveaux bogues lorsque vous apportez une modification.
L’approche TDD prend sans aucun doute plus de temps au départ, mais le point à retenir est que vous écrivez moins de code, ce qui signifie moins de problèmes. Tous ces gadgets que vous incluez souvent naturellement ne feront pas partie du code.
Il y a une scène dans le film Swordfish où, si les souvenirs sont bons, un pirate informatique doit travailler avec une arme à feu à la tête et être fou ... sinon distrait. Le fait est qu'il est beaucoup plus facile de travailler lorsque votre espace libre est dans le code et que vous avez du temps de votre côté plutôt que des mois avec un client qui vous hurle dessus et d'autres priorités qui se coincent.
Les développeurs comprennent que la résolution des bogues plus tard est plus coûteuse, mais inversez-la. Si vous pouviez être payé 500 dollars par jour pour coder votre code actuel ou 1 000 dollars si vous écriviez en langage TDD, vous mordriez la main de la personne qui vous faisait la deuxième offre. Plus tôt vous arrêterez de considérer les tests comme une corvée et de le voir comme un épargnant, plus vous serez prospère.
la source
Je peux comprendre votre expérience: notre base de code n’avait pratiquement pas de tests et était pour la plupart indestablable. Il a fallu littéralement du temps pour développer quelque chose et la réparation des bugs de production prenait un temps précieux depuis les nouvelles fonctionnalités.
Pour une réécriture partielle, j'ai promis d'écrire des tests pour toutes les fonctionnalités principales. Au début, cela a pris beaucoup plus de temps et ma productivité a sensiblement baissé, mais ma productivité a été meilleure que jamais auparavant.
Une partie de cette amélioration tenait au fait que j'avais moins de bugs de production, ce qui entraînait moins d'interruptions -> j'avais une meilleure concentration à tout moment.
De plus, la capacité de tester ET de déboguer le code pris isolément est très rentable - une suite de tests est nettement supérieure à un système qui ne peut être débogué qu'avec une configuration manuelle, par exemple en lançant votre application et en naviguant à l'écran ... peut-être quelques dizaines de fois
Mais notez qu'il y a une baisse de productivité au début, alors commencez à apprendre à tester sur certains projets où la pression du temps n'est pas déjà insensée. Essayez également de le démarrer sur un projet en arrière-plan. Le test des unités sur un code hérité est très difficile et il est utile de savoir à quoi ressemble une bonne suite de tests.
la source
Pour compléter les réponses précédentes, rappelez-vous que le test n’est pas un objectif en soi. Les tests ont pour but de permettre à votre application de se comporter comme prévu au fil de l'évolution, dans des contextes inattendus, etc.
Par conséquent, écrire des tests ne signifie pas prouver tous les comportements de tous les points d'extrémité d'une entité. C'est une erreur commune. Beaucoup de développeurs pensent avoir besoin de tester toutes les fonctions / objets / méthodes / propriétés / etc. Cela conduit à une charge de travail élevée et à un tas de codes et de tests non pertinents. Cette approche est courante dans les grands projets, où la plupart des développeurs ne sont pas conscients du comportement holistique, mais ne peuvent voir que leur domaine d’interaction.
La bonne approche pour gérer les ressources rares et les tests est assez évidente et de bon sens, mais elle n’est pas formalisée: investissez d’abord les ressources de développement de test dans des fonctionnalités de haut niveau, puis entrez progressivement dans les spécificités . Cela signifie qu'à un moment donné, en tant que développeur solitaire, vous ne vous concentreriez pas uniquement sur les tests unitaires, mais également sur les fonctionnalités / intégration / etc. testez et, en fonction de vos ressources en temps, insérez progressivement les principales fonctions unitaires, comme vous le souhaiteriez. Les tests de haut niveau fourniront les informations nécessaires pour traiter les tests de bas niveau / unitaires et pour planifier votre stratégie de développement de tests en fonction des ressources dont vous disposez.
Par exemple, vous souhaitez d'abord tester une chaîne de traitement en tant que boîte noire. Si vous constatez que certains membres de la chaîne échouent en raison d'un comportement ne prenant pas en compte une condition extrême, vous écrivez les tests qui garantissent la fonctionnalité non seulement de ce membre, mais également d'autres personnes. Ensuite, vous livrez. Pour le cycle suivant, vous détectez que le réseau échoue parfois. Vous écrivez donc des tests sur les modules susceptibles d’être vulnérables. Etc.
la source