Je trouve les tests beaucoup plus difficiles et plus difficiles à écrire que le code réel qu'ils testent. Il n'est pas inhabituel que je passe plus de temps à écrire le test que le code qu'il teste.
Est-ce normal ou est-ce que je fais quelque chose de mal?
Les questions «Les tests unitaires ou le développement piloté par les tests en valent-ils la peine? ”,“ Nous passons plus de temps à mettre en place un test fonctionnel qu’à mettre en place le système lui-même, est-ce normal? ”Et leurs réponses sont plus axées sur la question de savoir si le test en vaut la peine (comme dans“ devons-nous ignorer complètement les tests? ”). Bien que je sois convaincu que les tests sont importants, je me demande si je passe plus de temps à faire des tests que du code réel ou si ce n’est que moi.
À en juger par le nombre de points de vue, de réponses et de critiques positives que ma question a été reçue, je ne peux que supposer que c’est une préoccupation légitime qui n’est abordée dans aucune autre question du site Web.
la source
Réponses:
Je me souviens d'un cours de génie logiciel, que l'un consacrait environ 10% de son temps de développement à l'écriture de nouveau code et l'autre 90% au débogage, aux tests et à la documentation.
Étant donné que les tests unitaires capturent le débogage et les efforts de test dans du code (potentiellement automatisable), il serait logique que davantage d'efforts y soient consacrés; le temps réellement nécessaire ne devrait pas être beaucoup plus que le débogage et les tests que l’on ferait sans écrire les tests.
Enfin, les tests devraient également servir de documentation! On devrait écrire des tests unitaires de la manière dont le code est destiné à être utilisé; c'est-à-dire que les tests (et leur utilisation) doivent être simples, mettez les éléments compliqués dans la mise en œuvre.
Si vos tests sont difficiles à écrire, le code qu'ils testent est probablement difficile à utiliser!
la source
Il est.
Même si vous ne faites que des tests unitaires, il n’est pas inhabituel d’avoir plus de code dans les tests que le code réellement testé. Il n'y a rien de mal à cela.
Considérons un code simple:
Quels seraient les tests? Il y a au moins quatre cas simples à tester ici:
Le nom de la personne est
null
. Une exception est-elle réellement levée? Cela fait au moins trois lignes de code de test à écrire.Le nom de la personne est
"Jeff"
. Sommes-nous"Hello, Jeff!"
en réponse? C'est quatre lignes de code de test.Le nom de la personne est une chaîne vide. À quelle sortie attendons-nous? Quelle est la sortie réelle? Question secondaire: cela correspond-il aux exigences fonctionnelles? Cela signifie quatre autres lignes de code pour le test unitaire.
Le nom de la personne est suffisamment court pour une chaîne, mais trop long pour être combiné avec
"Hello, "
le point d'exclamation. Qu'est-ce qui se passe? ¹Cela nécessite beaucoup de code de test. De plus, les éléments de code les plus élémentaires nécessitent souvent un code de configuration qui initialise les objets nécessaires au code testé, ce qui conduit souvent à l'écriture de stubs et de mocks, etc.
Si le rapport est très grand, dans ce cas, vous pouvez vérifier quelques points:
Existe-t-il une duplication de code dans les tests? Le fait qu'il s'agisse d'un code de test ne signifie pas que le code doit être dupliqué (copier-coller) entre des tests similaires: une telle duplication rendra difficile la maintenance de ces tests.
Y a-t-il des tests redondants? En règle générale, si vous supprimez un test unitaire, la couverture des branches devrait diminuer. Si ce n'est pas le cas, cela peut indiquer que le test n'est pas nécessaire, car les chemins sont déjà couverts par d'autres tests.
Testez-vous uniquement le code que vous devriez tester? Vous n'êtes pas censé tester la structure sous-jacente des bibliothèques tierces, mais uniquement le code du projet lui-même.
Avec les tests de fumée, les tests de système et d'intégration, les tests de fonctionnement et d'acceptation, ainsi que les tests de contrainte et de charge, vous ajoutez encore plus de code de test. Il ne faut donc pas s'inquiéter d'avoir quatre ou cinq LOCs de tests pour chaque LOC de code réel.
Une note sur le TDD
Si vous êtes préoccupé par le temps nécessaire pour tester votre code, il se peut que vous le fassiez mal, c'est-à-dire le code d'abord, puis les tests plus tard. Dans ce cas, TDD peut vous aider en vous encourageant à travailler dans des itérations de 15 à 45 secondes, en alternant code et tests. Selon les partisans de TDD, cela accélère le processus de développement en réduisant à la fois le nombre de tests que vous devez faire et, plus important encore, le nombre de codes d’entreprise à écrire et surtout la réécriture des tests.
¹ Soit n soit la longueur maximale d'une chaîne . Nous pouvons appeler
SayHello
et transmettre par référence une chaîne de longueur n - 1 qui devrait fonctionner correctement. Maintenant, à l’Console.WriteLine
étape, le formatage doit se terminer par une chaîne de longueur n + 8, ce qui entraînera une exception. Peut-être, en raison des limites de mémoire, même une chaîne contenant n / 2 caractères entraînera une exception. La question à se poser est de savoir si ce quatrième test est un test unitaire (il en a l'air, mais peut avoir un impact beaucoup plus important en termes de ressources que les tests unitaires moyens) et s'il teste le code réel ou le framework sous-jacent.la source
personName
fits in astring
, mais la valeur depersonName
plus les valeurs concaténées débordentstring
.As a rule of thumb, if you remove a unit test, the branch coverage should decrease.
Si j'écris les quatre tests que vous avez mentionnés ci-dessus, puis que je supprime le troisième test, la couverture diminuera-t-elle?Je pense qu'il est important de distinguer deux types de stratégies de test: le test unitaire et le test d'intégration / acceptation.
Bien que les tests unitaires soient nécessaires dans certains cas, ils sont souvent excessivement complétés. Ceci est exacerbé par des métriques sans signification imposées aux développeurs, comme "couverture à 100%". http://www.rbcs-us.com/documents/Why-Most-Unit-Testing-is-Waste.pdf fournit un argument convaincant à cet égard. Considérez les problèmes suivants avec les tests unitaires agressifs:
Par ailleurs, les tests d’intégration / d’acceptation constituent un élément extrêmement important de la qualité des logiciels et, d’après mon expérience, vous devriez consacrer beaucoup de temps à les corriger.
De nombreux magasins ont bu le TDD Kool-Aid, mais comme le montre le lien ci-dessus, un certain nombre d’études montrent que ses avantages ne sont pas concluants.
la source
.equals()
méthodes générées par Eclipse." J'ai écrit un test harnais pourequals()
etcompareTo()
github.com/GlenKPeterson/TestUtils. Presque toutes les implémentations que j'ai testées manquaient. Comment utilisez-vous les collections siequals()
ethashCode()
ne travaillent pas ensemble correctement et efficacement? J'encourage à nouveau le reste de votre réponse et je l'ai votée favorablement. Je reconnais même que certaines méthodes equals () générées automatiquement n'ont peut-être pas besoin de tests, mais j'ai eu tellement de bogues avec une mise en œuvre médiocre que cela me rend nerveux.Ne peut pas être généralisé.
Si j'ai besoin d'implémenter une formule ou un algorithme à partir d'un rendu physique, il se peut très bien que je passe 10 heures sur des tests unitaires paranoïaques, car je sais que le moindre bogue ou une imprécision peut conduire à des bugs presque impossibles à diagnostiquer, des mois plus tard. .
Si je veux juste regrouper logiquement quelques lignes de code et lui donner un nom, utilisé uniquement dans l'étendue du fichier, je ne peux pas le tester du tout (si vous insistez pour écrire des tests pour chaque fonction, sans exception, les programmeurs risquent de se replier écrire le moins de fonctions possible).
la source
Oui, c'est normal si vous parlez de TDDing. Lorsque vous avez des tests automatisés, vous sécurisez le comportement souhaité de votre code. Lorsque vous écrivez vos tests en premier, vous déterminez si le code existant a déjà le comportement souhaité.
Cela signifie que:
(Cela ne tient pas compte de la refactorisation du code, qui vise à passer moins de temps à l'écriture du code suivant. Elle est contrebalancée par la refactorisation des tests, qui vise à passer moins de temps à la rédaction des tests suivants.)
Oui aussi, si vous parlez d'écrire des tests après coup, vous passerez plus de temps:
Que vous passerez réellement à écrire du code.
Alors oui, c'est une mesure attendue.
la source
Je trouve que c'est la partie la plus importante.
Les tests unitaires ne consistent pas toujours à "voir si cela fonctionne bien", mais à apprendre. Une fois que vous testez quelque chose, cela devient "codé en dur" dans votre cerveau et vous réduisez éventuellement le temps de test de votre unité et vous pouvez vous retrouver à écrire des classes et des méthodes entières sans rien tester jusqu'à ce que vous ayez terminé.
C'est pourquoi l'une des autres réponses sur cette page mentionne que dans un "cours", ils ont effectué des tests à 90%, car chacun devait apprendre les mises en garde relatives à son objectif.
Les tests unitaires ne sont pas seulement une utilisation très précieuse de votre temps, car ils améliorent littéralement vos compétences, c'est également un bon moyen de revoir votre propre code et de trouver une erreur logique en chemin.
la source
Cela peut être pour beaucoup de gens, mais cela dépend.
Si vous écrivez d’abord des tests (TDD), il est possible que le chevauchement du temps passé à l’écriture du test soit réellement utile pour écrire le code. Considérer:
Lorsque vous écrivez des tests après avoir écrit le code, vous découvrirez peut-être que votre code n'est pas facilement testable. L'écriture de tests est donc plus difficile et prend plus de temps.
La plupart des programmeurs écrivent du code beaucoup plus longtemps que les tests, alors je m'attendrais à ce que la plupart d'entre eux ne soient pas aussi fluides. De plus, vous devez ajouter le temps nécessaire pour comprendre et utiliser votre infrastructure de test.
Je pense que nous devons changer notre état d'esprit en ce qui concerne le temps requis pour coder et la manière dont les tests unitaires sont impliqués. Ne le regardez jamais à court terme et ne comparez jamais le temps total nécessaire pour fournir une fonctionnalité particulière, car vous devez tenir compte non seulement de l'écriture d'un code meilleur / moins bogué, mais également d'un code plus facile à modifier et à conserver. mieux / moins buggy.
À un moment donné, nous ne sommes tous capables que de rédiger un code aussi bon. Certains outils et techniques ne peuvent donc offrir que beaucoup pour améliorer nos compétences. Ce n'est pas comme si je pouvais construire une maison si je n'avais qu'une scie guidée au laser.
la source
Oui, ça l'est. Avec quelques mises en garde.
Tout d’abord, c’est "normal" dans le sens où la plupart des grands magasins fonctionnent de cette façon. Même si cette façon de procéder était complètement erronée et idiote, le fait que la plupart des grands magasins fonctionnent de cette manière le rend "normal".
Par cela, je ne veux pas dire que les tests sont faux. J'ai travaillé dans des environnements sans tests et dans des environnements avec des tests obsessionnels compulsifs, et je peux toujours vous dire que même les tests obsessionnels compulsifs étaient meilleurs que l'absence de tests.
Et je ne fais pas encore TDD (qui sait, je le ferai peut-être à l'avenir), mais je fais la grande majorité de mes cycles de montage-exécution-débogage en exécutant les tests, pas l'application réelle, alors naturellement, je travaille beaucoup sur mes tests, afin d'éviter autant que possible d'avoir à exécuter l'application proprement dite.
Sachez toutefois que des tests excessifs présentent des dangers, notamment le temps consacré à leur maintenance . (J'écris principalement cette réponse pour le préciser.)
Dans la préface de L'Art des tests unitaires de Roy Osherove (Manning, 2009), l'auteur reconnaît avoir participé à un projet qui a échoué en grande partie en raison de l'énorme fardeau de développement imposé par des tests unitaires mal conçus qu'il a fallu maintenir tout au long du processus. durée de l'effort de développement. Donc, si vous passez trop de temps à ne faire que maintenir vos tests, cela ne signifie pas nécessairement que vous êtes sur la bonne voie, car c'est "normal". Votre effort de développement est peut-être entré dans un mode malsain, où il pourrait être nécessaire de repenser radicalement votre méthodologie de test afin de sauver le projet.
la source
la source