Les tests unitaires sont-ils vraiment utiles? [fermé]

98

Je viens tout juste d'obtenir un diplôme en informatique et je travaille actuellement en tant que développeur junior .NET (formulaires C #, ASP.NET et Web). À l'époque où j'étais encore à l'université, le sujet des tests unitaires avait été couvert, mais je n'en avais jamais vraiment vu les avantages. Je comprends ce qu’elle est censée faire, à savoir déterminer si un bloc de code est utilisable ou non. Cependant, je n'ai jamais eu à écrire un test unitaire auparavant et je n'ai jamais ressenti le besoin de le faire.

Comme je l'ai déjà mentionné, je développe habituellement avec des formulaires Web ASP.NET et récemment, j'ai pensé à écrire des tests unitaires. Mais j'ai quelques questions à ce sujet.

J'ai lu que les tests unitaires se font souvent en écrivant des "simulacres". Bien que je comprenne ce concept, je n'arrive pas à comprendre comment je suis censé écrire des simulacres pour des sites Web complètement dynamiques et où presque tout dépend des données provenant d'une base de données. Par exemple: j'utilise beaucoup de répéteurs qui ont des événements ItemDataBound, etc. (encore une fois, cela dépend des données "inconnues").

Donc, question numéro 1: l’écriture de tests unitaires pour les formulaires Web ASP.NET est-elle une tâche fréquente, et si c’est le cas: comment résoudre le problème de "l’environnement dynamique"?

Quand je me développe, je fais beaucoup d'essais et d'erreurs. Cela ne signifie pas que je ne sais pas ce que je fais, mais que j'écris habituellement du code, frappe Ctrl F5et vois ce qui se passe. Bien que cette approche fasse le travail la plupart du temps, j'ai parfois le sentiment d'être un peu désemparée (à cause de ma petite expérience). Je perds parfois beaucoup de temps comme ça aussi.

Donc, question numéro 2: Est-ce que vous me conseillez de commencer à écrire des tests unitaires? Je pense que cela pourrait m'aider dans la mise en œuvre réelle, mais là encore, je sens que cela pourrait me ralentir.

Jane Doe
la source
1
Je voudrais juste dire que l’autre côté de la question est que certains endroits les exigent comme pratique. Je suis à un endroit où nous ne sommes pas autorisés à enregistrer le code, sauf s'il est couvert par des tests unitaires. Il est donc important de noter que même si vous ne croyez pas en elles, vous serez peut-être obligé de les faire plus tard. Je pense que c'est une compétence utile à apprendre et à avoir dans son arsenal. Je vais souvent trouver des petits bugs et des incidents dans mon code en effectuant les tests, presque une petite session d’assurance qualité avec vous-même.
Adam
9
Comment couvrez-vous exactement les tests unitaires sans écrire de tests unitaires? S'agit-il d'une de ces écoles "évaluez-vous" ou "concevez votre propre programme"?
JeffO
4
Les tests unitaires sont discutables - Idéal pour les langages dynamiques, moins utile plus votre langue est stricte, mais CONSTRUISEZ DES TESTS. Ils ne doivent pas nécessairement être des tests unitaires, mais vous devriez vraiment avoir des tests d'intégration que vous pouvez exécuter avec JUnit, ceux-ci sont très utiles.
Bill K
13
-1 Désolé, je suis tout pour les bons arguments, même si je ne suis pas d'accord, mais c'est faux. Personne ne prétend que "les tests unitaires servent à détecter les bogues dans le nouveau code", ce qui en fait un homme de paille - les tests unitaires servent à détecter les régressions . Et la citation de Dijkstra est sortie de son contexte - le contexte est que les tests sont inutiles si vous avez une spécification formelle de votre problème .
Sleske
9
"les tests unitaires sont destinés à capturer des régressions". Non. Les tests automatisés servent à capturer les régressions. Les régressions exigent invariablement que les mêmes tests soient exécutés plusieurs centaines de fois; il est donc intéressant de les automatiser. Malheureusement, de nombreuses réponses et commentaires sur cette question traitent réellement de la question "Les tests automatisés sont-ils utiles?". Les tests unitaires peuvent être une forme de test automatisé, mais ils ont un objectif complètement différent. Je considère certainement que les tests automatisés valent leur pesant d'or, mais cela ne devrait pas servir d'argument pour justifier des tests unitaires (ou TDD pour cette question).
njr101

Réponses:

124

À mon avis: oui, et vous devriez le faire.

  1. Ils vous donnent confiance dans les changements que vous apportez (tout le reste fonctionne encore). Cette confiance est ce dont vous avez besoin pour modeler le code, sinon vous pourriez avoir peur de changer les choses.

  2. Ils améliorent votre code. la plupart des erreurs simples sont détectées tôt avec les tests unitaires. Détecter les bogues tôt et les réparer revient toujours moins cher que de les réparer plus tard, par exemple lorsque l'application est en production.

  3. Ils servent de documentation aux autres développeurs sur le fonctionnement de votre code et sur son utilisation.

Le premier problème auquel vous êtes confrontés est le fait qu'ASP.NET en soi ne vous aide pas à écrire des tests unitaires. En réalité, cela fonctionne contre vous. Si vous avez le choix, commencez à utiliser ASP.NET MVC , créé pour les tests unitaires. Si vous ne pouvez pas utiliser ASP.NET MVC, vous devez utiliser le modèle MVP dans ASP.NET afin de pouvoir au moins tester votre logique à l'unité.

En plus de cela, vous devez juste maîtriser la rédaction de tests unitaires. Si vous pratiquez le TDD, votre code est créé et peut être testé - en d’autres termes, propre et net.

Je vous conseillerais de pratiquer et de programme en binôme. En lisant:

Ou, pour un premier aperçu:

KeesDijk
la source
4
Je viens juste de commencer les tests unitaires, je suis d’accord C'est non seulement une bonne habitude, très utile, associée à une approche TDD, mais cela réduit beaucoup de temps. Je ne pense pas que mes projets pourraient être aussi utiles si je ne pouvais pas simplement exécuter un test unitaire et vérifier que tout fonctionnait correctement même après avoir ajouté une nouvelle fonctionnalité ou corrigé un bogue. Je ne peux pas penser à faire un test de régression d'une autre manière.
Kwelch
21
Si les tests unitaires fonctionnent comme une documentation, il y a un problème. La lecture de 500 lignes de code pour comprendre le fonctionnement de 5 lignes de code est inversée.
Coder
4
@Coder: lorsque vous testez des méthodes de niveau supérieur, cela implique plus de 5 lignes de code.
7
@coder: la documentation d'une classe vous indique les services fournis par les instances de la classe. Il vous dit moins d'informations sur la façon dont les instances de cette classe sont utilisées dans un contexte plus large, à savoir l'interaction entre les objets. Les tests vous donnent dans certains cas un code d’interaction typique, qui a été un point de départ précieux, à tel point que je ne peux même pas les compter.
Stefano Borini
21
@Coder: Il ne documentant ce que le code fait, il est de documenter les hypothèses inhérentes à ce code, à savoir pourquoi et quand il est censé fonctionner. Si les hypothèses sous-jacentes sont invalidées par une modification du système sous test, un ou plusieurs tests unitaires doivent échouer. Cela ne remplace pas la documentation de conception / architecture supérieure, ni même la documentation XML, mais couvre tout ce que ces choses ne peuvent jamais faire.
Aaronaught
95

Non.

Le concept derrière les tests unitaires est basé sur un principe qui était connu pour être faux avant même que les tests unitaires n'aient été inventés: l'idée que les tests peuvent prouver que votre code est correct.

Avoir beaucoup de tests qui réussissent prouve une chose et une chose: que vous avez beaucoup de tests qui réussissent tous. Cela ne prouve pas que ce que les tests testent correspond à la spécification. Cela ne prouve pas que votre code est exempt d'erreurs que vous n'avez jamais prises en compte lors de la rédaction des tests. (Et les choses que vous pensiez tester étaient les problèmes potentiels sur lesquels vous vous focalisiez, alors vous les aurez probablement bien comprises!) Et enfin, cela ne prouve pas que les tests, qui sont du code, sont exempts de bugs. (Suivez ce dernier jusqu'à sa conclusion logique et vous vous retrouverez avec des tortues tout en bas .)

Djikstra avait rejeté le concept de test comme preuve de correction en 1988, et ce qu'il a écrit reste tout aussi valable aujourd'hui:

Cela fait maintenant deux décennies qu'il a été souligné que les tests de programmes peuvent démontrer de manière convaincante la présence de bugs, mais ne peuvent jamais démontrer leur absence. Après avoir cité avec dévotion cette remarque très médiatisée, l’ingénieur logiciel revient à l’ordre du jour et continue d’affiner ses stratégies de test, à l’instar de l’alchimiste d’aujourd’hui, qui a continué d’affiner ses purifications chrysocosmiques.

L’autre problème des tests unitaires est qu’il crée un couplage étroit entre votre code et la suite de tests. Lorsque vous changez de code, vous vous attendez à ce que des bogues qui échouent à certains tests apparaissent. Mais si vous changez de code parce que les exigences elles-mêmes ont changé, vous obtiendrez de nombreux tests qui échoueront et vous devrez les examiner manuellement pour décider si le test est toujours valide ou non. (Et il est également possible, bien que moins courant, qu'un test existant qui devrait être invalide réussisse quand même parce que vous avez oublié de changer quelque chose qui devait être changé.)

Les tests unitaires ne sont que le dernier d'une longue série de modes de développement qui promettent de faciliter l'écriture de code fonctionnel sans être en réalité un bon programmeur. Aucun d'entre eux n'a jamais réussi à tenir sa promesse, pas plus que celle-ci. Il n’existe tout simplement aucun raccourci pour savoir comment écrire du code de travail .

Certains rapports font état de tests automatisés réellement utiles dans les cas où la stabilité et la fiabilité sont d’une importance primordiale. Par exemple, le projet de base de données SQLite. Mais ce qu’il faut pour atteindre leur niveau de fiabilité n’est absolument pas rentable pour la plupart des projets: un rapport de code test-sur-code-SQLite réel de presque 1200: 1. La plupart des projets ne peuvent pas se le permettre et n'en ont de toute façon pas besoin.

Mason Wheeler
la source
69
Cela prouve que votre code se comporte correctement pour ces tests. Si vous me le demandez, c'est un sacré lot.
Stefano Borini
111
Qui de nos jours croit réellement que les tests unitaires sont une "preuve de correction"? Personne ne devrait penser ça. Vous avez raison de dire qu'ils prouvent seulement que ces tests sont réussis, mais c'est un point de données de plus que ce que vous aviez avant d'écrire les tests unitaires. Vous devez effectuer des tests à plusieurs niveaux pour vous donner une idée de la qualité de votre code. Les tests unitaires ne prouvent pas que votre code est dépourvu de défauts, mais ils vous permettent de croire (ou devriez ...) que le code fait ce que vous avez conçu et continue de faire demain ce qu'il fait aujourd'hui.
Bryan Oakley
40
> but if the test itself is buggy, then you have false confidenceet si le testeur manuel ne fonctionne pas correctement, vous avez également une fausse confiance.
Stefano Borini
33
@ MasonWheeler: désolé, maçon, je ne suis pas convaincu. En plus de deux décennies de programmation, je ne pense pas avoir personnellement vu un cas où un test donnait un faux sentiment de sécurité. Peut-être que certains d'entre eux l'ont fait et que nous les avons corrigés, mais le coût de ces tests unitaires n'a pas dépassé les énormes avantages de les avoir. Si vous êtes capable d'écrire du code sans le tester au niveau de l'unité, je suis impressionné, mais la très grande majorité des programmeurs sont incapables de le faire de manière cohérente.
Bryan Oakley
41
Si vous avez écrit un test de bug que votre code a réussi, votre code est probablement aussi un buggy. Les chances d'écrire un code et un test de bug sont bien moins que le code de bug seul. Les tests unitaires ne sont pas une panacée. Ils constituent une bonne couche supplémentaire (là où il est prudent) de réduire le fardeau des testeurs manuels.
Telastyn
60

Si vous avez déjà constaté l'avantage de rédiger une méthode principale pour tester un petit élément de code à l'école, le test unitaire est la version professionnelle / entreprise de cette même pratique.

Imaginez également le temps système nécessaire à la création du code, au démarrage de votre serveur Web local, à la navigation vers la page en question, à la saisie des données ou à la définition de la source de test appropriée, à l'envoi du formulaire et à l'analyse des résultats ... vs création et frappe le bouton nUnit run.

Voici une image amusante aussi ... entrez la description de l'image ici

J'ai trouvé cette image ici:
http://www.howtogeek.com/102420/geeks-versus-non-geeks-when-doing-repetitive-tasks-funny-chart/

Heath Lilley
la source
2
Oui, vous pouvez. Isolez la couche Web dans vos tests unitaires pour tester la configuration Web (URL, validation des entrées, etc.). En substituant les couches Web et Base de données, vous pouvez tester le niveau métier sans base de données ni serveur Web. J'utilise dbunit pour tester ma base de données. Si vous le souhaitez, vous pouvez toujours effectuer des tests d'intégration complets, mais je le fais en tant que tâche spécifique après le développement.
Heath Lilley
12
Joli graphique, mais la balance est très mauvaise. Comme je l'ai indiqué dans ma réponse, la couverture complète des tests de SQLite nécessite environ 1200 fois plus de code dans les tests que dans le code du produit lui-même. Et même si vous n'êtes pas que obsessionnelle sur une couverture complète, vous devez encore plusieurs fois plus de tests que produit à aborder , même un niveau utile de la couverture dans vos tests. Pour être précis ici, la partie verticale de cette ligne rouge devrait continuer à monter et à monter pendant environ 3 pages.
Mason Wheeler
27
@MasonWheeler C'est un très beau cheval que vous battez, je pense qu'il est peut-être mort cependant ... SQLite a autant de tests parce que c'est une foutue base de données. Je veux m'assurer que ça marche. Autre exemple, le framework Silverstripe a un ratio de tests: code proche de 1: 1, donc ce n’est pas comme si SQLite était représentatif.
Aatch
15
@MasonWheeler Vous échouez au premier des paradoxes de Zeno . Si vous souhaitez adapter cette image au niveau de test de SQLite, l'axe X devra également se développer jusqu'à environ 100 fois sa longueur actuelle.
Izkata
2
Cela est particulièrement vrai lorsque vous êtes un développeur backend qui n'a pas le temps de créer une page Web en noir et blanc afin de pouvoir tester votre logique back-end. Tout ce que je dois faire est de fournir des objets de requête et de session fictifs et d'exécuter mes contrôleurs via un test unitaire, et à la fin de tout cela, je sais si c'est vrai ou faux. Si vous utilisez DI, injectez simplement un DAO qui interagit avec une base de données en mémoire afin que votre base de données ne change pas ou lancez-le simplement Exceptionet récupérez-le afin que vos données ne soient pas validées. Je dis oui aux tests unitaires.
Varun Achar
49

Les tests unitaires ont quelque chose de mystique ces jours-ci. Les gens le traitent comme si la couverture de test à 100% était un saint graal et comme si le test unitaire était la seule façon de développer un logiciel.

Ils manquent le point.

Les tests unitaires ne sont pas la solution. Le test est.

Maintenant, chaque fois que cette discussion survient, quelqu'un (souvent même moi) écrira la citation de Dijkstra: "Les tests de programme peuvent démontrer la présence de bugs, mais ne démontrent jamais leur absence." Dijkstra a raison: les tests ne suffisent pas pour prouver que le logiciel fonctionne comme prévu. Mais il est nécessaire : à un certain niveau, il doit être possible de démontrer que le logiciel fait ce que vous voulez.

Beaucoup de gens testent à la main. Même les enthousiastes du TDD effectueront des tests manuels, bien qu'ils ne l'admettent parfois pas. On n'y peut rien: avant de vous rendre dans la salle de conférence pour faire une démonstration de votre logiciel auprès de votre client / responsable / investisseurs / etc., vous le parcourrez à la main pour vous assurer qu'il fonctionnera correctement. Il n’ya rien de mal à cela, et en fait, il serait insensé de s’attendre à ce que tout se déroule sans heurts sans le parcourir manuellement, c’est-à-dire à le tester , même avec une couverture de 100% des tests unitaires et une confiance absolue dans vos tests. .

Mais les tests manuels, même s’ils sont nécessaires à la construction de logiciels, sont rarement suffisants . Pourquoi? Parce que les tests manuels sont fastidieux, prennent du temps et sont effectués par des humains. Et les humains sont notoirement mauvais pour effectuer des tâches fastidieuses et chronophages: ils évitent de les faire autant que possible, et souvent ils ne les font pas bien quand ils sont forcés de le faire.

Les machines , en revanche, sont excellentes pour effectuer des tâches fastidieuses et fastidieuses. C'est pour cela que les ordinateurs ont été inventés, après tout.

Les tests sont donc cruciaux et les tests automatisés sont le seul moyen judicieux de garantir que vos tests sont utilisés de manière cohérente. Et il est important de tester et de tester à nouveau le logiciel. Une autre réponse souligne l’importance des tests de régression . En raison de la complexité des systèmes logiciels, les modifications apparemment inoffensives apportées à une partie du système entraînent des modifications inattendues (c.-à-d. Des bogues) dans d'autres parties du système. Vous ne pouvez pas découvrir ces modifications inattendues sans une forme de test. Et si vous souhaitez disposer de données fiables sur vos tests, vous devez effectuer vos tests de manière systématique, ce qui signifie que vous devez disposer d'un système de test automatisé.

Qu'est-ce que tout cela a à voir avec les tests unitaires? De par leur nature, les tests unitaires sont exécutés par la machine et non par un humain. Par conséquent, de nombreuses personnes ont la fausse impression que les tests automatisés sont équivalents aux tests unitaires . Mais ce n'est pas vrai: les tests unitaires ne sont que de très petits tests automatisés.

Maintenant, quelle est la valeur des très petits tests automatisés? L'avantage est qu'ils testent les composants d'un système logiciel de manière isolée , ce qui permet un ciblage plus précis des tests et facilite le débogage . Mais les tests unitaires ne signifient pas intrinsèquement des tests de qualité supérieure . Cela conduit souvent à des tests de meilleure qualité, car il couvre les logiciels à un niveau de détail plus fin. Mais il est possible de tester complètement le comportement d'un système complet, et non de ses composants, tout en le testant de manière approfondie.

Mais même avec une couverture de 100% des tests unitaires, un système peut toujours ne pas être testé de manière approfondie. Parce que les composants individuels peuvent fonctionner parfaitement de manière isolée, ils échouent quand ils sont utilisés ensemble. Ainsi , les tests unitaires, bien que très utiles, ne suffisent pas pour garantir que le logiciel fonctionne comme prévu. En effet, de nombreux développeurs complètent les tests unitaires par des tests d'intégration automatisés, des tests fonctionnels automatisés et des tests manuels.

Si vous ne voyez pas l'intérêt des tests unitaires, la meilleure façon de commencer consiste peut-être à utiliser un type de test automatisé différent. Dans un environnement Web, l’utilisation d’un outil de test d’automatisation de navigateur tel que Selenium représente souvent un gain important pour un investissement relativement modeste. Une fois que vous avez plongé vos orteils dans l'eau, vous pourrez voir plus facilement à quel point les tests automatisés sont utiles. Et une fois que vous avez des tests automatisés, les tests unitaires ont beaucoup plus de sens, car ils offrent un délai d'exécution plus rapide que les gros tests d'intégration ou de bout en bout, car vous pouvez cibler les tests uniquement sur le composant sur lequel vous travaillez actuellement.

TL; DR: ne vous inquiétez pas pour le moment des tests unitaires . Ne vous inquiétez pas avant de tester votre logiciel.

Daniel Pryden
la source
Les tests unitaires sont également écrits par des humains et pourraient être erronés.
Seun Osewa
41

Ça dépend

C’est une réponse que vous verrez beaucoup en matière de développement logiciel, mais l’utilité des tests unitaires dépend vraiment de la qualité de leur rédaction. Un nombre limité de tests unitaires qui vérifient la fonctionnalité de l'application pour les tests de régression peuvent être très utiles; Cependant, une pléthore de tests simples qui vérifient les retours de fonctions peuvent être totalement inutiles et fournir un faux sentiment de sécurité, car l'application "comporte de nombreux tests unitaires".

De plus, votre temps en tant que développeur est précieux et le temps passé à écrire des tests unitaires n'est pas du temps passé à écrire de nouvelles fonctionnalités. Encore une fois, cela ne veut pas dire que vous ne devriez pas écrire de tests unitaires, mais chaque fonction publique at-elle besoin d’un test unitaire? Je dirais que la réponse est non. Le code qui effectue la validation des entrées utilisateur nécessite-t-il des tests unitaires? Très probablement, car il s’agit d’un point de défaillance courant dans les applications.

C’est l’un des domaines dans lesquels l’expérience entre en jeu. Au fil du temps, vous reconnaîtrez les parties de l’application qui pourraient bénéficier du test unitaire, mais il faudra un certain temps avant d’atteindre ce stade.

rjzii
la source
C'est un bon point. Vous devez savoir écrire de bons tests qui capturent la valeur du SUT.
Andy
3
Cela couvre essentiellement la façon dont on m'a appris à faire des tests unitaires - écrivez des tests pour couvrir les situations les plus importantes / critiques, puis ajoutez d'autres tests lorsque vos hypothèses se sont révélées fausses (je pensais que quelque chose ne pouvait "jamais échouer", mais ce l'était) .
Réintégrer Monica le
38

Les projets réalisés pour les cours universitaires diffèrent considérablement des applications professionnelles que vous écrivez au travail. La différence est la durée de vie. Combien de temps le projet universitaire "vit-il"? Dans la plupart des cas, cela commence lorsque vous écrivez la première ligne de code et se termine lorsque vous obtenez votre note. Vous pourriez dire que, effectivement, il ne vit que pour le moment de la mise en œuvre. "Libérer" est généralement égal à sa "mort".

Les logiciels conçus pour les entreprises dépassent le stade de la libération du projet universitaire et continuent de vivre aussi longtemps que les entreprises en ont besoin. Ce qui est très long . Quand on parle d'argent, personne ne dépensera un sou pour avoir un "code plus froid et plus ordonné". Si un logiciel écrit en C il y a 25 ans fonctionne toujours et est assez bon (comme l'entendent les besoins de son propriétaire), attendez-vous à le maintenir (ajout de nouvelles fonctionnalités, amélioration des anciennes - modification du code source ).

Nous arrivons à un point très important - la régression . À l'endroit où je travaille, nous avons deux équipes qui gèrent deux applications; l'un, écrit il y a environ 5 à 6 ans avec très peu de couverture de tests de code *, et le second, la version plus récente de la première application avec une suite complète de tests (unité, intégration et quoi d'autre). Les deux équipes ont des testeurs manuels (humains) dédiés. Vous voulez savoir combien de temps faut-il pour introduire une nouvelle fonctionnalité assez basique pour la première équipe? 3 à 4 semaines. La moitié de ce temps est "vérifier si tout le reste fonctionne encore". C'est une période occupée pour les testeurs manuels. Les téléphones sonnent, les gens se fâchent, quelque chose se brise à nouveau. La deuxième équipe traite généralement ces problèmes en moins de 3 jours.

Je ne dis absolument pas que les tests unitaires rendent votre code sujet aux erreurs, aux mots corrects ou à d’autres mots sophistiqués que vous pouvez trouver. Ils ne font pas disparaître les insectes comme par magie. Mais, lorsqu'elles sont combinées avec d'autres méthodes de test logiciel automatisé, elles rendent vos applications beaucoup plus faciles à gérer qu'elles ne l'auraient été autrement. C'est une victoire énorme.

Et le dernier mais non le moindre, le commentaire de Brian qui, je pense, résume toute la question:

(...) ils vous font croire (ou devriez ...) que le code fait ce que vous avez conçu et continue de faire demain ce qu'il fait aujourd'hui.

Parce qu'entre aujourd'hui et demain, quelqu'un pourrait effectuer de minuscules modifications qui provoqueraient le blocage du code du générateur de rapports, qui est si important . Les tests indiquent que vous découvrirez ceci avant que votre client ne soit un peu plus à vos côtés.

* Ils introduisent lentement de plus en plus de tests dans leur base de code, mais nous savons tous à quoi cela ressemble habituellement.

km
la source
10
+1000 pour la liaison à Software_Regression. Les collèges exposent les tests unitaires comme quelque chose que vous devez faire par pure confiance, sans expliquer en détail le fait qu'il existe une maladie à prévenir et à contrôler et que cette maladie s'appelle la régression . (Ensuite, il y a le problème avec les tests de régression étant quelque chose de très différent des tests unitaires, car la seule lecture que j'ai trouvée en l'expliquant bien est l'échantillon gratuit de ce livre )
ZJR
25

L’écriture de tests unitaires pour les formulaires Web ASP.NET est-elle une tâche fréquente, et si c’est le cas: comment résoudre le problème de "l’environnement dynamique"?

Ce n'est pas souvent fait. Travailler avec des éléments d'interface utilisateur n'est pas ce à quoi les tests unitaires sont bons, car il n'y a pas de moyen génial de vérifier par programme que les éléments corrects apparaissent à l'écran aux bons endroits.

Est-ce que vous me conseillez de commencer à écrire des tests unitaires? Je pense que cela pourrait m'aider dans la mise en œuvre réelle, mais là encore je sens que cela pourrait me ralentir.

Si applicable, oui. Ils peuvent être très utiles pour vérifier des cas spécifiques de manière répétable. Ils aident à agir en tant que «friction» contre les changements gênants et en tant que sécurité intégrée lorsque vous effectuez de meilleurs changements.

Une chose à noter est qu'ils vous ralentiront habituellement.

C'est d'accord.

Passer un peu de temps maintenant vous permettra (s’il est bien fait) de gagner du temps à l’avenir, car ils détectent certains bugs, empêchent leur réapparition et vous permettent d’être un peu plus à l'aise avec d'autres améliorations du code pour l'empêcher de pourrir.

Telastyn
la source
8
+1 pour répondre réellement au cas d'utilisation de la question! Tous les autres ont sauté sur la partie "test unitaire" et ont oublié la partie "Formulaires Web ASP.NET" ...
Izkata
1
C'est une excellente réponse qui mérite plus de votes positifs. La raison en est que vous avez répondu aux questions et que vous avez été honnête dans votre évaluation, à savoir ralentir le développeur et ne pas promettre que tous les bugs seraient capturés ou prévenus, ce qui est complètement et toujours une erreur. tout à fait vrai.
Mantorok
11

Je viens tout juste d'obtenir un diplôme en informatique et j'ai actuellement un travail en tant que développeur junior .NET (en C # et généralement en ASP.NET, formulaires Web - pas ASP.NET MVC). À l'époque où j'étais encore à l'université, le sujet des tests unitaires a été couvert, mais je n'en ai jamais vraiment vu les avantages.

C'est parce que tu n'as jamais programmé grand.

Je comprends ce qu’il est censé faire - déterminer si un bloc de code est utilisable - mais je n’ai jamais eu à écrire de test unitaire auparavant. (ni> n'ai-je jamais ressenti le besoin de ..)

La rédaction de tests unitaires oblige votre code à se conformer à une structure mentale donnée, vérifiable, bien documentée et fiable. C'est beaucoup plus que ce que vous prétendez.

-J'ai lu que les tests unitaires se font souvent en écrivant des "simulacres". Bien que je comprenne ce concept, je n'arrive pas à comprendre comment je suis censé écrire des simulacres pour des sites Web totalement dynamiques et où presque tout dépend des données provenant d'une base de données.

simulez l'accès à la base de données avec une classe factice qui renvoie des classes de modèle contenant des données codées en dur bien définies. ou , remplissez une base de données de test avec les données de fixture et travaillez à partir de là.

-Est-ce que vous me conseillez de commencer à écrire des tests unitaires?

putain, oui. Lisez d'abord "Test Driven Development" de Beck .

Je pense que cela pourrait m'aider dans la mise en œuvre réelle, mais là encore je sens que cela pourrait me ralentir.

Cela vous ralentit maintenant. Mais lorsque vous devez déboguer pendant des heures au lieu de plusieurs jours, vous changez d'avis.

N'importe quel conseil sera apprécié :)

Tester. Croyez-moi. Malheureusement, cela doit aussi être une politique de gestion, mais c'est quelque chose qui fait gagner du temps. Les tests restent, ils sont là, maintenant et à l'avenir. Lorsque vous changez de plate-forme et exécutez les tests, et qu'ils fonctionnent toujours, vous savez que vos données fonctionnent comme prévu.

Stefano Borini
la source
8

Edit: J'ai bien sûr rejoint le TDD Pro / Con Dogpile et ai sauté la question n ° 1:

1 - Implémentation des tests unitaires dans les formulaires Web ASP.net:

Tout d’abord, si vous pensez que vous pouvez les convaincre d’utiliser MVC, défendez-vous comme un infatigable enragé. En tant que développeur front-end / UI, .net MVC est ce qui m’a aidé à cesser de détester .net afin que je puisse mieux me concentrer sur le fait de détester toutes les solutions Web Java que je rencontre. Les tests unitaires posent problème car les formulaires Web brouillent vraiment les lignes entre le serveur et le côté client. Dans toute tentative de tests unitaires, je mettrais l’accent sur la manipulation de données et (espérons-le) supposons que les formulaires Web gèrent la normalisation des entrées utilisateur pour vous sous le capot.

2 - Si les tests unitaires valent la peine en premier lieu:

Très bien, divulgation complète:

  • Je suis surtout autodidacte. Ma formation classique se résume à aimer un JavaScript, un PHP et une classe C #, ainsi que ma propre étude personnelle des principes de la programmation orientée objet et la lecture d'éléments tels que Design Patterns.

cependant,

  • J'écris principalement pour le Web côté client et la partie programmation est dans l'un des langages les plus rapides et les plus lâches du marché en ce qui concerne le typage dynamique, les fonctions de premier ordre et la mutabilité des objets.

Cela signifie que je n'écris pas pour le même compilateur ou la même machine virtuelle. J'écris pour environ 4 à 20 interprétations différentes de trois langues (oui, deux d'entre elles sont simplement déclaratives mais déterminent également l'espace physique fondamental de l'interface utilisateur avec laquelle je travaille parfois de manière différente), et ce depuis les interprétations beaucoup plus varié qu'aujourd'hui. Et non, je ne suis pas juste un gamin qui branche du contenu JQuery pour des applications jetables. J'aide à construire et à maintenir des éléments assez sophistiqués avec beaucoup de complexité d'éléments d'interface utilisateur.

Alors oui, il y a beaucoup d'opportunités pour quelques ajustements ici et là pour créer une cascade d'échecs si vos compétences en matière de conception sont de la merde complète ou si vous lancez des développeurs médiocres en grande quantité à 1-2 problèmes de développement de qualité.

D'après ce que je comprends de ce que TDD est censé faire pour vous, les tests ont davantage pour but de vous obliger à examiner plus attentivement la conception et de vous concentrer sur les exigences. Très bien, mais le problème ici est que cela subvertit ce que vous devriez faire, qui consiste à concevoir pour une interface, en quelque chose de subtilement mais fondamentalement différent, qui consiste à concevoir pour les tests d’une interface. La différence pour moi est entre dessiner une image claire que maman n'aura pas à deviner la signification de et remplir la page entière de vert très rapidement pour que vous puissiez être le premier enfant à frapper de ses crayons sur la table et à crier "Terminé! " En privilégiant les résultats aux processus et à la conception, vous encouragez essentiellement la poursuite de la mise en œuvre du code de déchets, qui est généralement à l'origine de vos problèmes.

Et puis, bien sûr, il y a le "non-réel-point-réel" de l'avantage encore souvent loué des tests unitaires qui vous aident à détecter les erreurs de régression. Les défenseurs de TDD ont tendance à être un peu fous sur le fait de savoir si c'est vraiment l'objectif ou juste un effet secondaire astucieux, IMO, parce qu'ils savent très bien ou soupçonnent au moins que cela n'est tout simplement pas suffisant pour établir l'absence de bugs dans votre système. le code, en particulier dans un langage plus dynamique comme JavaScript où supposer que vous pouvez même prédire tous les scénarios possibles dans une longue chaîne de dépendances est imprudent.

JS a une place pour les tests automatisés dans JS, mais une utilisation bien plus efficace de votre temps que de lier un test unitaire à chaque "unité" de votre code qui entre en contact avec un autre est de vous assurer que vous n'avez pas Les objets poubelles qui font double emploi ou dont l'utilisation prévue est ambiguë sémantiquement là. Vous suivez le principe DRY. Vous faites abstraction de choses pour la réutilisation / la portabilité lorsque la valeur de le faire devient évidente (et pas une minute avant). Vous établissez des processus cohérents et des façons de faire les choses en suivant davantage le principe de la carotte que du bâton (c.-à-d. Qu'il est trop facile d'utiliser votre matériel de la bonne façon pour ne pas vouloir le faire à mauvais escient). Et pour l'amour de tout, foo et bar, vous ne vous laissez jamais aller à des anti-modèles massifs de schémas d'héritage en cascade comme moyen de réutilisation du code.

Tout ce qui précède m'a aidé à réduire sérieusement les bogues difficiles à diagnostiquer dans mon code et vous pouvez avoir confiance que c'est une grande priorité pour quelqu'un qui est arrivé en tant que développeur avec un ensemble de navigateurs qui n'avait rien de mieux à vous dire que " euh il y a eu un problème avec un objet de type 'Object' à ce numéro de ligne imaginaire dans un fichier non spécifié. " (merci, IE6) TDD, dans mon travail, n'encouragerait pas ces choses. Cela porterait l'accent sur les résultats à 100% sur les processus où la différence entre les points A et B importait peu tant que cela fonctionnait. C'est une perte de temps qu'il serait préférable d'appliquer pour vous assurer que vos documents sont lisibles, portables et faciles à modifier sans trop de casse source de confusion.

Ou peut-être suis-je trop excentrique à propos du paradigme dans lequel je suis enraciné, mais à mon avis, agir correctement dès le départ est une utilisation du temps beaucoup plus efficace que de vous couvrir les fesses lorsque vous ou tout le monde sur votre l'équipe le fait mal. Et rien ne devrait vous obliger à envisager la conception avant la mise en œuvre. La conception devrait être l'autel freaking de chaque programmeur. Et tout ce qui "vous oblige" à faire ce qui est juste ou qui vous protège de vous-même devrait être considéré avec le même soupçon que celui réservé aux bouteilles d’huile de serpent, OMI. L'huile de serpent dans l'informatique moderne et le développement général, si vous ne le savez pas encore, est vendue à la tonne liquide.

Erik Reppen
la source
1
J'écris beaucoup de tests unitaires. Je ne vais pas écrire de code sans eux. Mais je suis d'accord avec vos sentiments. Les tests doivent guider et non stimuler le développement. Vous ne pouvez pas automatiser la réflexion sur un problème.
FizzyTea
Je n'ai aucun problème avec les tests automatisés. Mais son adoption massive à chaque moment semble plus être une panique qu'un processus pour moi. Ce que je préfère, c'est de gagner du temps pour la conception et d'automatiser les tests et la validation à des moments où vous êtes susceptible d'interagir avec une variété d'éléments que vous ne maîtrisez pas.
Erik Reppen
5

D'après mon expérience, les tests unitaires sont effectivement très utiles lorsque vous commencez avec eux et que vous restez avec eux, c'est-à-dire le développement piloté par les tests. Voici pourquoi:

  • Les tests unitaires vous obligent à réfléchir à ce que vous voulez et à la manière de vérifier que vous l'avez obtenu avant d'écrire le code qui le fait . Dans un scénario TDD, vous écrivez d'abord le test. Vous devez donc savoir ce que le code que vous êtes sur le point d'écrire doit faire et comment vous pouvez le vérifier, afin d'écrire un test "rouge" que vous rendrez ensuite "vert" en écrivant le code dans passe-le. Dans de nombreux cas, cela vous oblige à réfléchir un peu plus sur l'algorithme que vous êtes sur le point d'écrire pour réussir ce test, ce qui est toujours une bonne chose car il réduit les erreurs de logique et les "cas critiques". Pendant que vous écrivez le test, vous pensez "comment cela pourrait- il échouer" et "qu'est-ce que je ne teste pas ici", ce qui conduit à un algorithme plus robuste.

  • Les tests unitaires vous obligent à réfléchir à la manière dont le code que vous allez écrire va être utilisé . Avant d’avoir appris le TDD, j’ai écrit BEAUCOUP de code à une époque qui attendait une dépendance à sens unique, puis une dépendance écrite par un collègue qui fonctionnait de manière complètement différente. Bien que cela soit encore possible avec TDD, le test unitaire que vous écrivez vous oblige à réfléchir à la façon dont vous voulez utiliser l'objet que vous écrivez, car il s'agit d'un exemple d'utilisation de cet objet. Nous espérons ensuite écrire l'objet de manière à ce qu'il soit facile à consommer, et donc à s'adapter si nécessaire (bien que la programmation sur des interfaces prédéfinies soit une meilleure solution globale à ce problème qui ne nécessite pas de TDD).

  • Les tests unitaires vous permettent de "coder par test" . Un outil de refactoring tel que ReSharper peut être votre meilleur ami si vous le permettez. Vous pouvez l'utiliser pour définir le squelette de la nouvelle fonctionnalité lors de la définition de l'utilisation dans un test.

    Par exemple, supposons que vous deviez créer un nouvel objet MyClass. Vous commencez par créer une instance de MyClass. "Mais MyClass n'existe pas!", Se plaint ReSharper. "Alors créez-le", dites-vous en appuyant sur Alt + Entrée. Et hop, vous avez votre définition de classe. Dans la ligne suivante du code de test, vous appelez une méthode MyMethod. "Mais ça n'existe pas!", Dit ReSharper. "Ensuite, créez-le", répétez-vous, avec un autre Alt + Entrée. En appuyant quelques fois sur la touche, vous avez défini le "squelette" de votre nouveau code. Au fur et à mesure que vous continuez à préciser l'utilisation, l'EDI vous avertit lorsque quelque chose ne va pas, et la solution est généralement assez simple pour que l'EDI ou un outil le connectant sache comment le réparer.

    Des exemples plus extrêmes sont conformes au modèle "Triple-A"; "Organiser, agir, affirmer". Configurez tout, exécutez la logique que vous testez, puis affirmez que la logique est correcte. En codant de cette manière, il est très naturel de coder la solution dans le test; ensuite, avec quelques appuis sur les touches, vous pouvez extraire cette logique et la placer à un endroit où elle peut être utilisée dans le code de production, puis apporter de petites modifications au test qui pointe vers le nouvel emplacement de la logique. Cela vous oblige à concevoir le code de manière modulaire et facile à réutiliser, car les unités que vous testez doivent toujours être accessibles.

  • Les tests unitaires exécutent de nombreux ordres de grandeur plus rapidement que tous les tests manuels imaginables. Il existe un point, très rapidement respecté dans le cas de projets de grande envergure, où le temps supplémentaire consacré aux tests unitaires commence à s’amortir en réduisant le temps consacré aux tests manuels. Vous devez TOUJOURS exécuter le code que vous venez d'écrire. Traditionnellement, vous le faisiez manuellement, en démarrant un programme volumineux, en naviguant dans l'interface utilisateur pour configurer la situation pour laquelle vous avez changé le comportement, puis en vérifiant à nouveau les résultats dans l'interface utilisateur ou sous la forme de données générées. Si le code était en TDD, vous venez d'exécuter les tests unitaires. Je vous garantis que si vous écrivez de bons tests unitaires, la dernière option sera beaucoup plus rapide que la première.

  • Les tests unitaires interceptent la régression . Encore une fois, avant d'apprendre le TDD, il m'est souvent arrivé de modifier ce que je pensais être une modification chirurgicale d'un code, de vérifier que le changement corrigeait un comportement errant (ou produisait un nouveau comportement souhaité) dans la situation signalée. , et l’a vérifié pour publication, seulement pour constater que le changement a cassé un autre cas délicat dans un module complètement différent qui permettait de réutiliser ce même bloc de code. Dans un projet TDDed, je peux rédiger un test vérifiant une modification que je suis sur le point d'effectuer, effectuer la modification, puis exécuter la suite complète. Si tous les autres usages du code étaient en TDD et que ma modification ne respectait pas les règles, les tests de ces modifications d'autres choses vont échouer, et je peux enquêter.

    Si les développeurs devaient rechercher et tester manuellement toutes les lignes de code susceptibles d'être affectées par un changement potentiel, rien ne serait jamais fait car le coût de la détermination de l'impact d'un changement rendrait ce changement impossible. À tout le moins, rien ne serait solide et donc facile à entretenir, car vous n’oseriez jamais toucher à quelque chose qui pourrait être utilisé à plusieurs endroits; au lieu de cela, vous utiliseriez votre propre solution de modification mineure très similaire, incorporant votre modification mineure, violant SRP et probablement OCP, et transformant lentement votre base de code en une courtepointe patchwork.

  • Les tests unitaires façonnent l'architecture de manière généralement avantageuse . Les tests unitaires sont des tests effectués indépendamment de toute autre logique. Afin de pouvoir tester votre code à l’unité, vous devez écrire le code de manière à ce que vous puissiez:l'isoler. Les bonnes décisions de conception, telles que le couplage lâche et l'injection de dépendance, sortent donc naturellement du processus TDD; les dépendances doivent être injectées de sorte que, lors d'un test, vous puissiez injecter un "mock" ou "stub" produisant l'entrée ou gérant la sortie pour la situation testée sans créer d '"effets secondaires". La mentalité "d'utilisation avant tout" de TDD conduit généralement à "coder en interfaces", l'essence même du couplage lâche. Ces bons principes de conception vous permettent ensuite d’apporter des modifications à la production, telles que le remplacement d’une classe entière, sans nécessiter de modifications importantes du code-base.

  • Les tests unitaires montrent que le code fonctionne, au lieu de prouver que le code fonctionne . À première vue, vous pourriez penser qu’un inconvénient; sûrement la preuve vaut-elle mieux que la démonstration? La théorie est grande; la théorie informatique et algorithmique est la base de notre travail. Mais, une preuve mathématique de l'exactitude d'un algorithme n'est pas une preuve de l'exactitude de la mise en oeuvre . Une preuve mathématique montre seulement que le code adhérant à l'algorithme doit être correct. Un test unitaire montre que le code réellement écrit fait ce que vous pensiez qu'il ferait et prouve donc qu'il est correct. C’est généralement beaucoup plus intéressant que la preuve théorique.

Cela dit, les tests unitaires présentent des inconvénients:

  • Vous ne pouvez pas tout tester à l'unité. Vous pouvez concevoir votre système de manière à minimiser le nombre de lignes de crédit non couvertes par un test unitaire, mais certaines zones du système ne pourront tout simplement pas être testées. Votre couche d'accès aux données peut être simulée lorsqu'elle est utilisée par un autre code, mais la couche d'accès aux données elle-même contient de nombreux effets secondaires et il n'est généralement pas possible de tester un peu beaucoup (la plupart?) D'un référentiel ou d'un DAO. De même, le code qui utilise des fichiers, établit des connexions réseau, etc. a des effets secondaires intégrés et vous ne pouvez tout simplement pas tester la ligne de code qui le fait. Les éléments de l'interface utilisateur ne peuvent souvent pas être testés par unité; vous pouvez tester des méthodes codebehind telles que les gestionnaires d'événements, vous pouvez tester les constructeurs et vérifier que les gestionnaires sont bien branchés, mais il n'y a tout simplement pas de substitut dans le code pour un utilisateur qui clique avec la souris sur un élément graphique particulier et regarde le gestionnaire être appelé. L’atteinte de ces limites entre ce qui peut et ne peut pas être testé de manière adéquate par une unité est appelée «grattage du bord du bac à sable»; au-delà de ce point, vous êtes limité à l'utilisation de tests d'intégration, de tests d'acceptation automatisés et de tests manuels pour vérifier le comportement.

  • De nombreux avantages des tests unitaires ne s'appliquent pas sans TDD. Il est parfaitement possible d'écrire du code, puis d'écrire des tests qui l'exercent. Ce sont toujours des "tests unitaires". Cependant, en écrivant du code en premier, vous perdez de nombreux avantages inhérents au développement "test-en-premier": le code n'est pas nécessairement conçu de manière à pouvoir être facilement testé, voire utilisé en production. ; vous ne comprenez pas le processus de «double vérification» inhérent à la rédaction du test et à la réflexion sur ce à quoi vous n'aviez pas pensé; vous ne codez pas en testant; et si vous écrivez du code, testez-le manuellement et assurez-vous qu'il fonctionne, puis codez un test unitaire qui échoue, qui est incorrect, le code ou le test? Vos principaux avantages sont la prévention de la régression (vous serez averti lorsque le code qui a déjà réussi ses tests échoue) et la vérification à haute vitesse par rapport aux tests manuels. La perte de TDD '

  • Les tests unitaires introduisent une surcharge . Tout simplement, vous écrivez du code pour tester le code que vous écrivez. Cela augmentera nécessairement le total de la LOC d'un projet de développement, et oui, la LOC pour les tests peut dépasser le LOC du projet actuel. Les développeurs et les non-développeurs naïfs examineront cet état de fait et diront que les tests sont une perte de temps.

  • Les tests unitaires exigent de la discipline. Vous devez rédiger des tests qui exercent correctement le code base (bonne couverture du code), vous devez les exécuter régulièrement (car chaque fois que vous effectuez une modification, la suite complète doit être exécutée), et vous devez tout conserver "vert" ( tous les tests réussis). Lorsque les choses se cassent, vous devez les réparer, soit en corrigeant un code qui ne répond pas aux attentes, soit en mettant à jour les attentes des tests. Si vous modifiez les tests, vous devriez demander "pourquoi" et rester vigilant; il est incroyablement tentant de simplement changer les assertions ayant échoué pour qu'elles correspondent au comportement actuel ou simplement de supprimer les tests ayant échoué; mais, ces tests doivent être basés sur les exigences, et lorsque les deux ne correspondent pas, vous avez un problème. Si ces choses ne sont pas faites,

  • Les tests unitaires nécessitent plus d'équipement. La solution habituelle au besoin de discipline susmentionné et à la tendance naturelle des humains à la paresse et à la compacité est un "build-bot" exécutant un logiciel "d'intégration continue" comme TeamCity, CruiseControl, etc., qui effectue des tests unitaires, calcule mesures de couverture de code et dispose d’autres contrôles tels que «triple-C» (conformité à la convention de codage, à la FxCop). Le matériel du build-bot doit être raisonnablement performant (sinon, il ne suivra pas le taux d’enregistrement de code effectué par l’équipe moyenne), et les procédures d’enregistrement sur le bot devront être tenues à jour (si nécessaire). une nouvelle bibliothèque de tests unitaires est créée, les scripts de construction qui exécutent les tests unitaires doivent être modifiés pour permettre la recherche dans cette bibliothèque). C'est moins de travail que ça en a l'air, mais nécessite généralement une certaine expertise technique de la part d’au moins quelques personnes de l’équipe qui connaissent le fonctionnement de divers processus de construction (et peuvent donc les automatiser dans des scripts et en assurer la maintenance). Cela nécessite aussi toujours de la discipline sous la forme d'attention lorsque la construction "casse" et de réparer ce qui a causé la rupture de la construction (correctement) avant d'enregistrer de nouvelles données.

  • Les tests unitaires peuvent forcer l'architecture du code de manière non idéale . Bien que TDD soit généralement bon pour la modularité et la réutilisabilité du code, il peut être préjudiciable à sa bonne accessibilité. Les objets et les membres, placés dans des bibliothèques de production, ne peuvent pas être privés ou internes s'ils sont directement utilisés par des tests unitaires. Cela peut poser problème lorsque d’autres codeurs, qui voient maintenant un objet, essaient de l’utiliser alors qu’ils devraient utiliser quelque chose d’autre présent dans la bibliothèque. Les revues de code peuvent aider à cela, mais cela peut être une préoccupation.

  • Les tests unitaires interdisent généralement les styles de codage "développement rapide d'applications". Si vous écrivez des tests unitaires, vous ne codez pas "vite fait". C’est généralement une bonne chose, mais lorsque vous êtes sous un délai imposé hors du contrôle de votre volonté, ou que vous implémentez un changement de très petite envergure et que la partie prenante (ou votre supérieur hiérarchique) se demande pourquoi toute cette cruauté doit se produire juste pour Si vous changez une ligne de code, il peut simplement être impossible d’écrire et de maintenir la suite de tests unitaires appropriée. Les processus agiles y contribuent généralement en permettant aux développeurs de s'exprimer sur les contraintes de temps; Rappelez-vous que tout ce que le vendeur doit faire est de dire «oui, nous pouvons» et ils obtiennent le chèque de commission, à moins que le processus implique des personnes qui doivent réellement faire le travail en disant «non, nous ne pouvons pas» et auxquelles il faut prêter attention. Mais, tout le monde n'est pas agile, et agile a ses propres limites.

KeithS
la source
4

Les tests unitaires sont utiles lorsqu'ils sont utilisés correctement. votre logique pose divers problèmes.

"Quand je me développe, je fais beaucoup d'essais et d'erreurs", a déclaré Kevin.

Regardez la programmation par hasard. Il vaut mieux comprendre ce qu'un code doit faire et ensuite prouver qu'il le fait via un test unitaire. Ne supposez pas qu'un code fonctionne simplement parce que l'interface utilisateur ne s'est pas cassée lorsque vous avez exécuté le programme!

s writing unit tests for ASP.NET web forms something that is done often

Je ne connais pas les données statistiques pour dire à quelle fréquence les gens testent les formulaires Web. Ce n'est pas important. L'interface utilisateur est difficile à tester et les tests unitaires ne doivent pas non plus être couplés à une interface utilisateur. Séparez votre logique en couches, bibliothèques de classes pouvant être testées. Testez l'interface utilisateur séparément de la logique de back-end.

So, question number 2: Would you guys advise me to start writing unit tests?

Oui. Une fois que vous vous y êtes habitués, ils vous accélèrent. La maintenance prend beaucoup plus de temps et est plus coûteuse que la phase de développement initiale. La maintenance est grandement facilitée par les tests unitaires, même lors des tests initiaux et de la réparation des bogues.

P.Brian.Mackey
la source
Il existe des structures de test pouvant effectuer des tests sur des pages aspx simplement pour vérifier si les pages sont chargées avec succès ou non dans différents scénarios. Cela pourrait ne pas suffire, mais c'est mieux que rien.
étonnement
4

Sur le plan pratique, les tests unitaires peuvent être extrêmement utiles pour une raison très importante: vous pouvez tester un bit d'un code à la fois.

Lorsque vous écrivez toute une séquence d'étapes complexes et que vous les corrigez à la fin, vous avez tendance à trouver de nombreux bogues et le processus est généralement plus difficile, car vous êtes plus avancé dans le processus. Dans Visual Studio, vous pouvez générer un test rapide, le modifier un peu et exécuter UNIQUEMENT ce test . Vous savez alors que, par exemple, une méthode appelant cette méthode peut compter sur elle. Donc, cela augmente la confiance.

Les tests unitaires ne prouvent pas que votre programme est correct! : Les tests unitaires vérifient les régressions dans le code sensible et vous permettent de tester les nouvelles méthodes que vous écrivez.

Les tests unitaires ne sont pas conçus pour tester les frontaux : imaginez un test unitaire comme un petit projet que vous créez pour tester une nouvelle méthode que vous écrivez ou quelque chose du genre, et non comme une condition que votre code doit remplir.

Le test unitaire fonctionne très bien pour les environnements collaboratifs : si je dois fournir une méthode à un collègue qui utilise une technologie complètement différente de la mienne, comme par exemple, il l'appelle depuis iOS, je peux alors écrire rapidement un test unitaire pour voir si la méthode qu'il veut a) retransmet les données correctes b) exécute conformément à ses spécifications c) ne présente pas de goulet d'étranglement désagréable.

Tjaart
la source
"Les tests unitaires ne sont pas destinés à tester les interfaces" Qui a dit cela? Je ne le questionne pas. Je voudrais juste le savoir, car beaucoup de gens semblent avoir la fausse idée et j'aimerais les bousiller avec le bâton qui dit-ce-pas-ce-que-c'est-ce-que-cet-influent-extrêmement-influent-TDD-source.
Erik Reppen le
Certaines personnes, y compris moi-même, ont eu cette idée fausse en rencontrant des tests unitaires pour la première fois, je suis donc en train de clarifier cela. Je ne sais pas pourquoi vous sentez que je vous mets au défi, en fait je suis entièrement d'accord avec vous.
Tjaart
4

Une chose qui ne semble pas être abordée est la complexité de tester différents types de code.

Lorsque vous traitez avec des éléments avec des entrées et des sorties simples, il est généralement facile de procéder à des tests unitaires. Si les tests sont choisis en gardant à l'esprit les cas extrêmes du code testé, ils vous donneront une grande confiance dans leur exactitude. Ne pas écrire de tests pour un tel code serait fou. (Notez que la plupart des codes qui entrent dans les bibliothèques répondent à ce critère.)

Cependant, dans d’autres cas, vous devez construire d’énormes simulacres à tester car le code joue avec des données sous-jacentes complexes (généralement une base de données, mais pas forcément), ou produit des données de sortie très complexes (pensez à une routine une valeur de départ dans un niveau de jeu pour un exemple assez extrême) et les tests unitaires ne sont pas aussi utiles. Couvrir tout ce qui se trouve dans vos cas de test est généralement une chimère. Lorsque vous trouvez un bogue, c'est presque toujours un cas auquel vous n'aviez jamais pensé et qui n'aurait donc pas pu construire un test.

Il n'y a pas de balle en argent, tout ce qui est décrit comme une balle en argent n'est pas aussi bon que le prétendent ses partisans, mais cela ne veut pas dire que c'est inutile.

Loren Pechtel
la source
4

L'écriture de tests unitaires pour l'application de formulaires Web ASP.NET n'est PAS courante et très difficile à accomplir. Cependant, cela ne signifie pas que le projet doit le sauter.

Les tests unitaires concernent corner stonesdes applications critiques et offrent fiabilité et tranquillité d'esprit lorsque les fonctionnalités essentielles fonctionnent comme prévu.

En fait, vous pouvez introduire le test unitaire beaucoup plus facilement avec un modèle ASP.NET MVP qui pourrait être utilisé dans le développement de vos formulaires Web. Il introduira une séparation des préoccupations et ability to write essential unit tests.

Certaines références qui pourraient être utiles sont:

ElYusubov
la source
2
+1 Peu importe que vous fassiez des tests unitaires ou non, MVP est la voie à suivre lorsque vous travaillez avec Web Forms (peut-être aussi WinForms).
simoraman
3

Les tests unitaires ont pour but de vous permettre de modifier votre code en toute sécurité (refactorisation, amélioration, etc.) sans craindre de perdre quelque chose à l'intérieur du système. Cela s'avère très utile pour les applications de grande taille, lorsque vous ne connaissez pas vraiment tous les effets de votre changement de code (malgré un couplage lâche).

m3th0dman
la source
6
Sans crainte, c'est un faux sentiment de sécurité.
Codeur
Peut-être que "moins de peur" est une meilleure phrase, mais la réponse est encore largement correcte.
Réintégrer Monica le
1
@ Coder Si vos tests réussissent après le refactoring, alors vous pouvez être presque certain que votre amélioration de code n'a pas changé le comportement de l'application (en gros, vous n'avez pas introduit de nouveaux bogues, mais ce n'est pas nécessairement vrai car vous ne pouvez pas atteindre Couverture de test à 100%).
m3th0dman
2

D'après mon expérience, oui , les tests unitaires sont utiles.

Le test unitaire consiste à séparer des parties du code que vous écrivez et à vous assurer qu'elles fonctionnent de manière isolée. Cet isolement peut en effet impliquer la création d'objets fictifs ou factices pour parler à l'objet que vous testez, ou non. Cela dépend beaucoup de l'architecture de votre objet.

Le test unitaire offre divers avantages:

Cela garantit principalement que les unités que vous testez fonctionnent comme vous, le développeur, pensez qu'elles devraient fonctionner. Bien que ce soit moins que cela puisse paraître: cela ne signifie pas nécessairement que l'objet fonctionne correctement; seulement que cela fonctionne comme vous pensez que cela devrait fonctionner, il s'agit d'une déclaration beaucoup plus forte que la méthode d'essai et d'erreur nécessaire sans test unitaire.

De plus, cela garantit que les unités continuent à fonctionner comme vous, les développeurs, pensez qu'elles devraient fonctionner. Les modifications logicielles peuvent avoir un impact inattendu sur les unités.

Un autre effet secondaire est que cela signifie que les unités que vous testez faire le travail en vase clos. Cela signifie généralement que vous commencez à programmer des interfaces plutôt que des classes concrètes, en réduisant le couplage et en renforçant la cohésion: toutes les caractéristiques communes d'une bonne conception. Oui: le simple fait de permettre à vos unités de code de faire des tests unitaires améliorera naturellement la conception de votre code.

Pourtant...

Les tests unitaires ne sont pas la fin des tests. D'autres types de tests sont toujours nécessaires. Par exemple, même lorsque vous avez montré que les unités fonctionnent comme vous le souhaitez, vous devez toujours montrer que chaque unité fonctionne comme les unités qui lui parlent s’attendent à ce qu’elle fonctionne. En d'autres termes, vos composants s'intègrent-ils correctement les uns aux autres?

Kaz Dragon
la source
1

Pour les applications simples avec un petit nombre de couches à tester (Fenêtre principale -> sous-menu), peut-être que la compilation à exécuter pour vérifier les modifications est correcte.

Pour les applications plus grandes nécessitant une navigation de 30 secondes pour obtenir la page que vous testez, cela s'avère très coûteux.

DefenestrationDay
la source
1

Je souhaite ajouter un nouveau côté (en fait un peu ancien) à ceci: les tests unitaires ne sont pas très utiles si votre code est bien conçu .

Je sais que la plupart des programmeurs ne font plus la conception de programme, je le fais toujours, et j’ai trouvé que les tests unitaires étaient une nécessité plutôt fastidieuse pour s’intégrer à une culture TDD, mais jusqu’à présent, je n’ai rencontré qu’une ou deux mineures. bugs par milliers de lignes de tests de mon code - pas seulement ce que j'ai écrit, mais ce que les testeurs officiels ont également écrit.

Je suppose que vous ne ferez plus la conception de programme non plus - les gens actuels vont faire pression sur vous pour ne pas le faire - mais il est peut-être utile de rappeler que le test unitaire est une méthode très très efficace par rapport à la conception.

Ceci est un argument dijsktraian: le test unitaire ne peut être exécuté que sur un programme suffisamment détaillé pour être exécuté.

Si vous dessinez des organigrammes / diagrammes d'état / d'action, des diagrammes de séquence, des inventaires d'objets (et enfin, des diagrammes de classes) pour votre code avant de l'écrire, vous serez en mesure de supprimer la plupart des bogues potentiellement menaçants en traçant une trace vos lignes et vérifier vos noms.

De nos jours, les diagrammes de classes sont générés à partir de code, contenant des centaines, parfois des milliers de classes, et sont complètement inutilisables - tout ce qui contient plus de 15 éléments dépasse la reconnaissance humaine.

Vous devez savoir quelles classes 10 + -5 sont importantes ou ce que vous faites actuellement, et pouvoir vérifier votre code de plusieurs points de vue, chaque diagramme représentant EXACTEMENT les points de vue que vous regardez et vous allez tuer des milliers de bogues. sur papier.

  • Vérifier dans un code dynamique si les types sont respectés (avec simplement montrer les types d'entrée / sortie sur un diagramme et les connecter avec un crayon ou une couleur différente),
  • vérifier si tous les états sont traités (en vérifiant la plénitude de vos conditions),
  • traçant les lignes pour s'assurer que tout a une fin (chaque organigramme doit être un automate d'états finis déterministe entièrement défini, pour les esprits mathématiques
  • s'assurer que certains composants n'ont rien à faire les uns avec les autres (en extrayant toutes leurs dépendances) (bon pour la sécurité)
  • simplifier le code en convertissant les dépendances en associations (les dépendances proviennent des classes utilisées par les méthodes membres)
  • vérifier les noms, rechercher les préfixes communs, effacer les synonymes, etc.

il y a tellement plus facile ...

De plus, j'ai découvert que mes applications sont plus utilisables si elles proviennent directement de cas d'utilisation ... si les cas d'utilisation sont bien écrits (sujet du verbe ACTOR, demandes du mainteneur d'ouvrir le guichet automatique bancaire ...)

J'ai utilisé du code avec plus de 95% des couvertures de code. Bien sûr, je fais parfois des tests unitaires, en particulier. pour les vérifications des limites dans les calculs, mais je n’ai pas encore rencontré de régressions sérieuses (grave: ne disparaît pas au bout de 24 heures) pour ne pas utiliser les tests unitaires, même pour les modifications.

Parfois, je ne fais pas une seule ligne de code pendant 3-4 jours d'affilée, je dessine. Puis, en une journée, je tape 1500-2000 lignes. Dès le lendemain, ils sont généralement prêts pour la production. Parfois, les tests unitaires sont écrits (avec plus de 80% de couverture), parfois (en plus), les testeurs sont invités à essayer de le casser, à chaque fois, certaines personnes sont invitées à le vérifier en le regardant.

Je n'ai pas encore vu ces tests unitaires trouver quoi que ce soit.

J'aimerais que le design-pensée remplace le TDD ... mais le TDD est tellement plus facile, c'est comme si on utilisait un marteau pilon ... il faut penser à ses besoins, et la plupart du temps, vous êtes absent pour le clavier.

Aadaam
la source
Je pense que vous pouvez concevoir au clavier. Mais la planification et l’organisation du code exigent beaucoup plus de réflexion que de simplement trébucher entre entrée et sortie dans des classes qui pourraient aussi bien être des fonctions monolithiques.
Erik Reppen
Croyez-moi, les fonctions monolithiques ne conviennent pas à un papier A4 (ou lettre US). Parfois, quand je suis paresseux, je «conçois» au clavier, mais ce n'est pas la même qualité. Chaque fois que je fais du développement sérieux, je conçois avec UML. Lorsque vous dessinez ces éléments, vous essayez d'expliquer à vous-même et aux autres de manière très limitée mais néanmoins structurée ce qui se passe, et lorsque vous êtes en mesure d'expliquer le code de toutes les perspectives, alors seulement et tous vos bugs sont au plus des fautes de frappe ...
Aadaam