Je travaille dans une petite entreprise en tant que développeur solo. Je suis le seul développeur de la société en fait. J'ai plusieurs projets (relativement) importants que j'ai écrits et maintenus régulièrement, et aucun d'entre eux n'a de tests pour les soutenir. Lorsque je commence de nouveaux projets, je me demande souvent si je devrais essayer une approche TDD. Cela semble être une bonne idée, mais honnêtement, je ne peux jamais justifier le travail supplémentaire que cela implique.
Je travaille dur pour être avant-gardiste dans ma conception. Je me rends bien compte qu'un jour, un autre développeur devra maintenir mon code, ou du moins le résoudre. Je fais des choses aussi simples que possible et je commente et documente des choses difficiles à comprendre. Et le fait est que ces projets ne sont ni si grands ni si compliqués qu'un développeur honnête aurait du mal à les comprendre.
Beaucoup d'exemples d'essais que j'ai vus vont jusqu'aux minuties, couvrant toutes les facettes du code. Étant donné que je suis le seul développeur et que je suis très proche du code dans l'ensemble du projet, il est beaucoup plus efficace de suivre un modèle de test en écriture puis en test manuel. Je trouve également que les exigences et les fonctionnalités changent assez souvent pour que le maintien des tests ajoute un frein considérable au projet. Temps qui pourrait autrement être utilisé pour résoudre les besoins de l'entreprise.
Je me retrouve donc chaque fois avec la même conclusion. Le retour sur investissement est trop faible.
J'ai parfois mis en place quelques tests pour vérifier que j'ai écrit un algorithme correctement, comme par exemple calculer le nombre d'années écoulées depuis qu'une personne travaille pour l'entreprise en fonction de sa date d'embauche. Mais du point de vue de la couverture de code, j'ai couvert environ 1% de mon code.
Dans ma situation, trouveriez-vous toujours un moyen de faire des tests unitaires une pratique régulière, ou ai-je le droit d'éviter ces frais généraux?
MISE À JOUR: J'ai omis quelques points à propos de ma situation: Mes projets sont tous des applications Web. Pour couvrir tout mon code, je devrais utiliser des tests d'interface utilisateur automatisés, et c'est un domaine pour lequel je ne vois toujours pas d'avantage important par rapport aux tests manuels.
la source
Réponses:
Alors? Vous n'êtes pas obligé de tout tester . Juste les choses pertinentes.
C'est en fait faux. Ce n'est pas plus efficace. C'est vraiment juste une habitude.
Ce que font les autres développeurs solo, c’est écrire un croquis ou un plan, écrire les scénarios de test, puis compléter le plan avec le code final.
C'est très très efficace.
C'est faux aussi. Les tests ne sont pas la traînée. Les changements requis sont la traînée.
Vous devez corriger les tests pour refléter les exigences. Que ce soit leur minutie ou de haut niveau; écrit en premier ou écrit en dernier.
Le code n'est pas terminé tant que les tests ne sont pas réussis. C'est la seule vérité universelle du logiciel.
Vous pouvez avoir un test d'acceptation limité "ici c'est".
Ou vous pouvez avoir des tests unitaires.
Ou vous pouvez avoir les deux.
Mais quoi que vous fassiez, il y a toujours un test pour démontrer que le logiciel fonctionne.
Je suggérerais qu'un peu de formalité et une belle suite d'outils de test unitaire rendent ce test beaucoup plus utile.
la source
sqrt(-1)
devrait s'agir d'un nombre entier, vous obtiendrez des réponses écrasantes dans un sens. La balance est autour de "comment" et "quel ordre". Le fait est que vous devez tester. Alors écrivez d'abord les tests et assurez-vous qu'ils fonctionnent.Imaginez que vous ayez une série de tests qui pourraient fonctionner dans les yeux et allumeraient une lumière verte ou rouge. Imaginez que cette suite de tests a tout testé ! Imaginez que tout ce que vous avez à faire pour exécuter la suite de tests consiste à taper ^ T. Quel pouvoir cela vous donnerait-il?
Pourriez-vous modifier le code sans craindre de casser quelque chose? Pourriez-vous ajouter une nouvelle fonctionnalité sans craindre de casser une ancienne fonctionnalité? Pourriez-vous nettoyer le code en désordre rapidement sans crainte de dommages?
Oui, vous pourriez faire toutes ces choses! Et qu'adviendrait-il de votre code avec le temps? Cela deviendrait de plus en plus propre car il n'y aurait aucun risque à le nettoyer.
Imaginons que vous ayez une petite fée sur votre épaule. Chaque fois que vous écriviez une ligne de code, la fée ajoutait quelque chose à la suite de tests qui vérifiait que cette ligne de code avait les résultats escomptés. Ainsi, toutes les deux secondes, vous pouvez taper ^ T et voir que la dernière ligne de code que vous avez écrite a fonctionné.
Combien de débogage pensez-vous que vous feriez?
Si cela ressemble à de la fantaisie, vous avez raison. Mais la réalité n’est pas très différente. Remplacez le clignement des yeux par quelques secondes et la fée par la discipline TDD, et vous l'aurez compris.
Supposons que vous revenez à un système que vous avez construit il y a un an et que vous avez oublié comment créer l'un des objets centraux. Il existe des tests qui créent cet objet de toutes les manières possibles. Vous pouvez lire ces tests et rafraîchir votre mémoire. Besoin d'appeler une API? Il existe des tests qui appellent cette API de toutes les manières possibles. Ces tests sont de petits documents écrits dans une langue que vous comprenez. Ils sont complètement sans ambiguïté. Ils sont si formels qu'ils exécutent. Et ils ne peuvent pas être désynchronisés avec l'application!
Ne vaut pas l'investissement? Tu rigoles! Comment quelqu'un pourrait-il pas vouloir cette suite de tests? Faites-vous une faveur et arrêtez de chicaner sur la bêtise. Apprenez à bien faire le TDD et observez à quelle vitesse vous allez, et à quel point votre code est plus propre.
la source
L'erreur que vous faites est que vous voyez les tests comme un investissement de temps sans retour immédiat. Cela ne fonctionne pas nécessairement comme ça.
Premièrement, l'écriture de tests vous concentre vraiment sur ce que cette partie de votre code doit faire.
Deuxièmement, leur exécution révèle des bugs qui seraient sinon apparus lors des tests.
Troisièmement, les exécuter montre parfois des bugs qui, autrement, ne seraient pas détectés lors des tests et vous auraient vraiment mordu dans la production.
Quatrièmement, si vous rencontrez un bogue avec un système en cours d’exécution et créez un test unitaire, vous ne pourrez pas réintroduire ce bogue ultérieurement. Cela peut être une très grande aide. Les insectes réintroduits sont courants et très ennuyeux.
Cinquièmement, si vous avez besoin de transmettre le code à quelqu'un d'autre, une suite de tests leur facilitera la vie. De plus, si vous avez ignoré un projet et que vous y revenez après quelques années, vous n'en serez plus aussi proche et cela vous sera utile également.
Mon expérience a toujours été que, tout au long du développement d'un projet, des tests unitaires décents ont toujours rendu le processus plus rapide et plus fiable.
la source
Les gars de JUnit (framework de test d'unité Java) ont pour philosophie que s'il est trop simple à tester, ne le testez pas . Je recommande fortement de lire leur FAQ sur les meilleures pratiques , car elle est assez pragmatique.
TDD est un processus différent d’écriture de votre logiciel. Le principe de base des tests unitaires est que vous passerez moins de temps dans le débogueur à parcourir le code et à déterminer plus rapidement si la modification de votre code annule accidentellement quelque chose d'autre dans le système. Cela correspond au TDD. Le cycle TDD est comme ceci:
Ce qui est moins évident dans l’application de TDD, c’est que cela change la façon dont vous écrivez le code . En vous forçant à réfléchir à la manière de tester / valider le fonctionnement du code, vous écrivez du code testable. Et puisque nous parlons de tests unitaires, cela signifie généralement que votre code devient plus modulaire. Pour moi, le code modulaire et testable est une grande victoire dès le départ.
Maintenant, avez-vous besoin de tester des choses comme les propriétés C #? Imaginez une propriété définie comme ceci:
La réponse serait "non", cela ne vaut pas la peine d'être testé, car vous testez actuellement la fonctionnalité linguistique. Ayez juste confiance que les gars de la plate-forme C # ont eu raison. En outre, si cela échouait, que pourriez- vous faire pour le réparer?
En outre, vous constaterez que certaines parties de votre code nécessiteront trop d’efforts pour être testées correctement. Cela signifie que ne le faites pas, mais assurez-vous de tester le code qui utilise / est utilisé par le problème épineux:
Croyez-le ou non, TDD vous aidera à atteindre un rythme de développement durable. Ce n'est pas à cause de la magie, mais plutôt parce que vous avez une boucle de rétroaction serrée et que vous êtes en mesure d'attraper rapidement des erreurs vraiment stupides. Le coût de la correction de ces erreurs est essentiellement constant (du moins suffisant pour la planification), car les petites erreurs ne deviennent jamais de grandes erreurs. Comparez cela à la nature éclatante des sprints de purge de binge / débogage de code.
la source
Vous devez équilibrer le coût des tests avec le coût des bugs.
L'écriture d'un test unitaire de 10 lignes pour une fonction qui ouvre un fichier, où l'échec est "fichier introuvable" est inutile.
Une fonction qui fait quelque chose de complexe à une structure de données complexe - alors évidemment oui.
La partie la plus délicate est entre les deux. Mais rappelez-vous que la valeur réelle des tests unitaires ne consiste pas à tester une fonction particulière, mais à tester les interactions complexes qui les unissent. Ainsi, un test unitaire qui détecte qu'un changement dans un bit de code, casse certaines fonctions dans un module différent à une distance de 1000 lignes, vaut son pesant poids en café.
la source
Tester, c'est jouer.
Créer un test est un pari sur le fait que le coût des bogues dans une unité qui surviennent et ne pas les rattraper avec ce test (maintenant et lors de toutes les révisions de code futures) est supérieur au coût de développement du test. Ces coûts de développement de tests incluent des éléments tels que la paie pour une ingénierie de test supplémentaire, un délai de commercialisation plus long, des coûts d’opportunité perdus du fait de ne pas coder d’autres éléments, etc.
Comme tout pari, parfois vous gagnez, parfois vous perdez.
Parfois, un logiciel en retard avec beaucoup moins de bogues l'emporte sur des choses rapides mais boguées qui arrivent en premier sur le marché. Parfois le contraire. Vous devez examiner les statistiques de votre domaine et déterminer combien de joueurs veulent jouer.
Il est possible que certains types de bogues ne soient pas générés, ou sortent de tout test de validation préalable, de manière à ne pas, statistiquement, valoir le temps nécessaire pour créer des tests spécifiques supplémentaires. Mais parfois, le coût d'un bug est tellement élevé (médical, nucléaire, etc.) qu'une entreprise doit prendre un pari perdant (similaire à l'achat d'une assurance). De nombreuses applications n'ont pas un coût d'échec aussi élevé, et n'ont donc pas besoin de la couverture d'assurance non rentable plus élevée. Les autres font.
la source
Mon conseil est de ne tester que le code sur lequel vous voulez travailler correctement.
Ne testez pas le code pour lequel vous voulez être bogué et vous poser des problèmes par la suite.
la source
TDD et tests unitaires ne sont pas la même chose.
Vous pouvez écrire du code, puis ajouter des tests unitaires ultérieurement. Ce n'est pas un TDD et représente beaucoup de travail supplémentaire.
TDD est la pratique de coder dans une boucle de lumière rouge. Lumière verte. Itérations de refactoring.
Cela signifie écrire des tests pour du code qui n'existe pas encore, regarder les tests échouer, corriger le code pour que les tests fonctionnent, puis rendre le code "correct". Cela vous évite souvent de travailler
L'un des avantages de TDD est qu'il réduit le besoin de penser à des anecdotes. Des choses comme les erreurs off-by-one disparaissent. Vous n'avez pas à parcourir la documentation de l'API pour savoir si la liste renvoyée commence à 0 ou 1, faites-le.
la source
J'ai travaillé sur un système où nous avons presque tout testé. Les exécutions notables à tester étaient les codes de sortie PDF et XLS.
Pourquoi? Nous avons pu tester les parties qui ont rassemblé les données et construit le modèle utilisé pour créer la sortie. Nous avons également pu tester les éléments permettant de déterminer les éléments du modèle destinés aux fichiers PDF. Nous n'avons pas été en mesure de vérifier si le fichier PDF paraissait correct car il était totalement subjectif. Nous n'avons pas été en mesure de vérifier que toutes les parties d'un fichier PDF étaient lisibles par un utilisateur typique, car elles étaient également subjectives. Ou si le choix entre les graphiques à barres et à secteurs était correct pour l'ensemble de données.
Si le résultat doit être subjectif, il y a peu de tests unitaires qui permettent de faire ce qui en vaut la peine.
la source
Dans bien des cas, un test d'écriture, puis manuel, ne prend pas plus de temps que d'écrire quelques tests. Les économies de temps résultent de la possibilité de réexécuter ces tests à tout moment.
Pensez-y: si vous avez une couverture de fonctionnalités décente avec vos tests (à ne pas confondre avec la couverture de code), et disons que vous avez 10 fonctionnalités - cliquer sur un bouton signifie que vous avez à peu près 10 répétitions de vos tests ... pendant que vous vous asseyez et sirotez votre café.
Vous n'avez pas non plus à tester les minutae. Vous pouvez écrire des tests d'intégration qui couvrent vos fonctionnalités si vous ne voulez pas entrer dans les détails - IMO, certains tests unitaires sont trop détaillés pour tester le langage et la plate-forme, et non le code.
TL; DR Ce n'est vraiment jamais approprié car les avantages sont tout simplement trop bons.
la source
Deux très bonnes réponses que j'ai rencontrées sont ici:
Les justifications pour éviter les frais généraux perçus:
Ne voudriez-vous pas laisser un bon produit de votre côté comme gage de la qualité de votre travail? En termes égoïstes, n’est-ce pas mieux pour vous que vous faites?
la source
Les développeurs professionnels écrivent des tests unitaires car, à long terme, ils permettent de gagner du temps. Vous allez tester votre code tôt ou tard, et si ce n'est pas le cas de vos utilisateurs, et si vous devez corriger les bogues plus tard, ils seront plus difficiles à corriger et auront plus d'effets d'entraînement.
Si vous écrivez du code sans tests ni bugs, alors tout va bien. Je ne crois pas que vous puissiez écrire un système non trivial avec zéro bogue, alors je suppose que vous le testez d'une manière ou d'une autre.
Les tests unitaires sont également essentiels pour éviter les régressions lorsque vous modifiez ou refactorisez du code ancien. Ils ne prouvent pas que votre changement n'a pas cassé l'ancien code, mais ils vous donnent beaucoup de confiance (tant qu'ils passent, bien sûr :))
Je ne voudrais pas revenir en arrière et écrire tout un lot de tests pour le code que vous avez déjà fourni, mais la prochaine fois que vous devrez modifier une fonctionnalité, je vous suggérerais d'essayer d'écrire des tests pour ce module ou cette classe, obtenez une couverture allant jusqu'à 70%. + avant d'appliquer les modifications. Voyez si cela vous aide.
Si vous essayez et que vous pouvez honnêtement dire que cela n’a pas été une aide, alors je pense qu’il existe suffisamment de preuves dans l’industrie pour les aider à valoriser au moins votre tentative d’approche.
la source
Il semble que la plupart des réponses soient pro-TDD, même si la question ne portait pas sur le TDD mais sur les tests unitaires en général.
Il n'y a pas de règle complètement objective derrière ce qui doit être testé ou non. Mais il semble parfois que de nombreux programmeurs n'effectuent pas de tests unitaires:
Selon votre philosophie de POO, vous pouvez créer des méthodes privées pour découpler des routines complexes de vos méthodes publiques. Les méthodes publiques sont généralement destinées à être appelées dans de nombreux endroits et sont souvent utilisées, et les méthodes privées ne sont réellement appelées que par une ou deux méthodes publiques dans une classe ou un module, dans un but très spécifique. Il est généralement suffisant d'écrire des tests unitaires pour les méthodes publiques, mais pas les méthodes privées sous-jacentes qui permettent à la magie de se produire. Si quelque chose ne va pas avec une méthode privée, vos tests unitaires de méthode publique devraient suffire à détecter ces problèmes.
Beaucoup de nouveaux programmeurs s'opposent à cela lorsqu'ils apprennent à tester pour la première fois et pensent qu'ils doivent tester chaque ligne exécutée. Si vous utilisez une bibliothèque externe et que sa fonctionnalité est bien testée et documentée par ses auteurs, il est généralement inutile de tester la fonctionnalité spécifique dans les tests unitaires. Par exemple, une personne peut écrire un test pour s'assurer que son modèle ActiveRecord conserve la valeur correcte pour un attribut avec un rappel "before_save" à la base de données, même si ce comportement est déjà testé de manière approfondie dans Rails. La ou les méthodes que le rappel appelle, peut-être, mais pas le comportement du rappel lui-même. Tous les problèmes sous-jacents liés aux bibliothèques importées seraient mieux révélés par des tests d'acceptation plutôt que par des tests unitaires.
Les deux peuvent s'appliquer que vous soyez en TDD ou non.
la source
Ken, moi-même et de nombreux autres développeurs sommes parvenus à la même conclusion à plusieurs reprises au cours de notre carrière.
La vérité que je crois que vous découvrirez (comme beaucoup d’autres), c’est que l’investissement initial dans la rédaction de tests pour votre application peut sembler décourageant, mais si bien écrit et ciblé sur les parties correctes de votre code, ils peuvent vraiment économiser une tonne. de temps.
Mon gros problème était avec les cadres de test disponibles. Je n'avais jamais vraiment eu l'impression qu'ils correspondaient à ce que je cherchais, alors j'ai simplement présenté ma propre solution très simple. Cela m'a vraiment aidé à comprendre le «côté obscur» des tests de régression. Je vais partager un pseudo extrait de base de ce que j'ai fait ici et j'espère que vous pourrez trouver une solution qui vous convient.
Après cela, la seule difficulté consiste à déterminer le niveau de granularité qui vous convient le mieux, quel que soit votre projet.
Construire un carnet d'adresses nécessitera évidemment beaucoup moins de tests qu'un moteur de recherche d'entreprise, mais les principes fondamentaux ne changent pas vraiment.
Bonne chance!
la source