Vous pouvez trouver une liste interminable de blogs, d'articles et de sites Web faisant la promotion des avantages du test unitaire de votre code source. Il est presque garanti que les développeurs qui ont programmé les compilateurs pour Java, C ++, C # et d'autres langages typés ont utilisé des tests unitaires pour vérifier leur travail.
Alors pourquoi alors, malgré sa popularité, les tests sont-ils absents de la syntaxe de ces langages?
Microsoft a introduit LINQ to C # , alors pourquoi ne pourraient-ils pas ajouter des tests?
Je ne cherche pas à prédire quels seraient ces changements linguistiques, mais à préciser pourquoi ils sont absents.
Par exemple: nous savons que vous pouvez écrire une for
boucle sans la syntaxe de l' for
instruction. Vous pouvez utiliser while
ou if
/ goto
déclarations. Quelqu'un a décidé qu'une for
déclaration était plus efficace et l'a introduite dans une langue.
Pourquoi les tests n'ont-ils pas suivi la même évolution des langages de programmation?
la source
Réponses:
Comme pour beaucoup d'autres choses, le test unitaire est mieux pris en charge au niveau de la bibliothèque, pas au niveau de la langue. En particulier, C # a de nombreuses bibliothèques de tests unitaires disponibles, ainsi que des éléments natifs du .NET Framework tels que
Microsoft.VisualStudio.TestTools.UnitTesting
.Chaque bibliothèque de tests unitaires a une philosophie et une syntaxe de test quelque peu différentes. Toutes choses étant égales par ailleurs, plus de choix valent mieux que moins. Si les tests unitaires étaient intégrés à la langue, vous seriez soit enfermé dans les choix du concepteur de langue, soit vous utiliseriez ... une bibliothèque et évitiez totalement les fonctionnalités de test de langue.
Exemples
Nunit - Un cadre de test unitaire idiomatique et à but général, tirant pleinement parti des fonctionnalités du langage C #.
Moq - Cadre moqueur qui tire pleinement parti des expressions lambda et des arbres d'expression, sans métaphore d'enregistrement / de lecture.
Il y a beaucoup d'autres choix. Des bibliothèques telles que Microsoft Fakes peuvent créer des "shims ..." qui ne vous obligent pas à écrire vos classes à l'aide d'interfaces ou de méthodes virtuelles.
Linq n'est pas une langue (malgré son nom)
Linq est une fonctionnalité de la bibliothèque. Nous avons gratuitement beaucoup de nouvelles fonctionnalités dans le langage C # lui-même, comme les expressions lambda et les méthodes d'extension, mais l'implémentation réelle de Linq se trouve dans le .NET Framework.
Un certain sucre syntaxique a été ajouté à C # pour rendre les instructions linq plus propres, mais ce sucre n'est pas requis pour utiliser linq.
la source
var
mot clé :)Il y a beaucoup de raisons. Eric Lippert a répété à maintes reprises que la raison
feature X
pour laquelle il n'était pas en C # était parce que ce n'était tout simplement pas dans son budget. Les concepteurs de langage ne disposent ni d'un temps infini ni de l'argent pour mettre en œuvre des éléments et chaque nouvelle fonctionnalité entraîne des coûts de maintenance. Garder le langage le plus petit possible n'est pas seulement plus facile pour les concepteurs de langage, il est également plus facile pour quiconque écrit des implémentations et des outils alternatifs (par exemple, des IDE). portabilité gratuite. Si le test unitaire est implémenté en tant que bibliothèque, il vous suffit de l'écrire une seule fois et cela fonctionnera dans n'importe quelle implémentation conforme du langage.Il convient de noter que D dispose d’un support au niveau de la syntaxe pour les tests unitaires . Je ne sais pas pourquoi ils ont décidé de le mentionner, mais il convient de noter que D est censé être un "langage de programmation système de haut niveau". Les concepteurs ont voulu que ce soit viable pour le type de code non sécurisé et de bas niveau utilisé traditionnellement par C ++, et une erreur dans le code non sécurisé est incroyablement coûteuse - un comportement indéfini. Je suppose donc que cela leur semblait logique de déployer des efforts supplémentaires pour tout ce qui peut vous aider à vérifier que certains codes non sécurisés fonctionnent. Par exemple, vous pouvez imposer que seuls certains modules sécurisés peuvent effectuer des opérations non sécurisées telles que des accès à des tableaux non contrôlés ou une arithmétique de pointeur.
Le développement rapide était également une priorité pour eux, à tel point qu'ils en ont fait un objectif de conception que le code D compile assez rapidement pour le rendre utilisable en tant que langage de script. Cuire des tests unitaires directement dans la langue afin que vous puissiez exécuter vos tests en transmettant simplement un indicateur supplémentaire au compilateur vous aide dans cette tâche.
Cependant, je pense qu'une bonne bibliothèque de tests unitaires fait beaucoup plus que simplement trouver des méthodes et les exécuter. Prenez par exemple QuickCheck de Haskell , qui vous permet de tester des choses telles que "pour tout x et y
f (x, y) == f (y, x)
". QuickCheck est mieux décrit comme un générateur de test unitaire et vous permet de tester des choses à un niveau supérieur à "pour cette entrée, je m'attends à cette sortie". QuickCheck et Linq ne sont pas si différents, ce sont deux langues spécifiques à un domaine. Par conséquent, plutôt que de vous limiter au support de tests unitaires dans une langue, pourquoi ne pas ajouter les fonctionnalités nécessaires pour rendre les DSL pratiques? Vous obtiendrez ainsi non seulement des tests unitaires, mais une meilleure langue.la source
Parce que les tests, et en particulier les développements pilotés par les tests, constituent un phénomène profondément contre-intuitif.
Presque tous les programmeurs commencent leur carrière en pensant qu'ils maîtrisent beaucoup mieux la complexité qu'ils ne le sont réellement. Le fait que même le plus grand programmeur ne puisse pas écrire de programmes volumineux et complexes sans erreurs graves à moins d'utiliser de nombreux tests de régression est sérieusement décevant et même honteux pour de nombreux praticiens. D'où la réticence face aux tests réguliers, même parmi les professionnels qui devraient déjà savoir mieux.
Je pense que le fait que les tests religieux deviennent de plus en plus courants et attendus est en grande partie dû au fait que, avec l'explosion de la capacité de stockage et de la puissance de calcul, de plus grands systèmes sont en cours de construction - et les très grands systèmes sont particulièrement sujets à l'effondrement de la complexité qui ne peut pas être géré sans le filet de sécurité des tests de régression. En conséquence, même les développeurs particulièrement obstinés et désemparés admettent maintenant à contrecœur qu'ils ont besoin de tests et qu'ils en auront toujours besoin (si cela ressemble à la confession lors d'une réunion des AA, c'est tout à fait intentionnel - il est psychologiquement difficile d'admettre qu'il existe un filet de sécurité personnes).
La plupart des langues populaires d’aujourd’hui datent d’avant ce changement d’attitude, de sorte qu’elles ont peu d’assistance intégrée pour les tests: elles ont
assert
, mais pas de contrat. Je suis à peu près sûr que si la tendance se maintient, les futures langues auront davantage de soutien au niveau de la langue plutôt qu'au niveau de la bibliothèque.la source
Beaucoup de langues ont un support pour les tests. Les affirmations de C sont des tests que le programme peut échouer. C’est là que la plupart des langues s’arrêtent, mais Eiffel et plus récemment Ada 2012 ont des préinvariants (choses que les arguments d’une fonction doivent passer) et postinvariants (choses que la sortie d’une fonction doit passer), Ada offrant la possibilité de référencer les arguments initiaux dans le fichier. postinvariant. Ada 2012 propose également des invariants de types. Ainsi, chaque fois qu'une méthode est appelée sur une classe Ada, l'invariant de types est vérifié avant le renvoi.
Ce n'est pas le type de test complet qu'un bon framework de test peut vous offrir, mais c'est un type de test important que les langues peuvent le mieux prendre en charge.
la source
Certains partisans de langages fonctionnels fortement typés affirment que ces fonctionnalités réduisent ou suppriment le recours aux tests unitaires.
Deux, à mon humble avis, bon exemple de cela, c’est de F # pour le plaisir et le profit ici et ici
Personnellement, je continue de croire en la valeur des tests unitaires, mais certains points sont valables. Par exemple, si un état illégal n'est pas représentable dans le code, il est non seulement inutile d'écrire un test unitaire pour ce cas, c'est impossible.
la source
Je dirais que vous avez manqué l’ajout de certaines fonctionnalités nécessaires car elles n’étaient pas mises en avant pour les tests unitaires .
Par exemple, les tests unitaires en C # reposent principalement sur l'utilisation d'attributs. La fonctionnalité Attributs personnalisés fournit un mécanisme d'extension riche qui permet aux infrastructures telles que NUnit d'itérer et de rivaliser avec des éléments tels que les tests basés sur la théorie et les tests paramétrés .
Cela m'amène à mon deuxième point majeur - nous ne savons pas assez ce qui fait une bonne testabilité pour l'incorporer dans une langue. Le rythme des innovations en matière de test étant beaucoup plus rapide que celui des autres concepts linguistiques, nous devons disposer de mécanismes flexibles dans nos langues pour laisser la liberté d'innover.
Je suis un utilisateur mais je ne suis pas un fanatique de TDD - cela est très utile dans certains cas, en particulier pour améliorer votre pensée conceptuelle. Il n'est pas forcément utile pour les systèmes hérités plus importants: des tests de niveau supérieur avec de bonnes données et une automatisation produiront probablement plus d'avantages avec une culture de contrôle du code forte .
Autre lecture pertinente:
la source