Je suis vraiment tombé amoureux des tests unitaires et du TDD - je suis infecté par le test.
Cependant, les tests unitaires sont normalement utilisés pour les méthodes publiques. Parfois, même si je dois également tester certaines hypothèses-assertions dans des méthodes privées, car certaines d'entre elles sont "dangereuses" et la refactorisation ne peut pas aider davantage. (Je sais, les frameworks de test permettent de tester des méthodes privées).
Il est donc devenu une de mes habitudes que la première et la dernière ligne d'une méthode privée soient toutes deux des affirmations.
Cependant, j'ai remarqué que j'ai tendance à utiliser des assertions dans les méthodes publiques (ainsi que privées) juste "pour être sûr". Serait-ce «tester la duplication» puisque les hypothèses de la méthode publique sont testées de l'extérieur par le cadre de tests unitaires?
Quelqu'un pourrait-il penser à trop d'assertions comme une odeur de code?
la source
Réponses:
Ces assertions sont vraiment utiles pour tester vos hypothèses, mais elles servent également un autre objectif très important: la documentation. Tout lecteur d'une méthode publique peut lire les assertions pour déterminer rapidement les conditions de pré et post, sans avoir à regarder la suite de tests. Pour cette raison, je vous recommande de conserver ces assertions pour des raisons de documentation, plutôt que pour des raisons de test. Techniquement, vous dupliquez les assertions, mais elles servent à deux fins différentes et sont très utiles dans les deux.
Il est préférable de les conserver sous forme d'affirmations plutôt que de simplement utiliser des commentaires, car ils vérifient activement les hypothèses chaque fois qu'elles sont exécutées.
la source
On dirait que vous essayez de faire la conception par contrat à la main.
Faire DbC est une bonne idée, mais vous devriez au moins envisager de passer à un langage qui le prend en charge nativement (comme Eiffel ) ou au moins utiliser un cadre de contrat pour votre plate-forme (par exemple, Microsoft Code Contracts for .NETest plutôt sympa, sans doute le framework de contrat le plus sophistiqué, encore plus puissant qu'Eiffel). De cette façon, vous pouvez mieux exploiter la puissance des contrats. Par exemple, en utilisant un cadre existant, vous pouvez faire apparaître les contrats dans votre documentation ou un IDE (par exemple, les contrats de code pour .NET sont affichés dans IntelliSense et, si vous avez VS Ultimate, peuvent même être vérifiés statiquement par un prouveur de théorème automatique au moment de la compilation pendant que vous tapez; de même de nombreux frameworks de contrats Java ont des doclets JavaDoc qui extrairont automatiquement les contrats dans votre documentation API JavaDoc).
Et même s'il s'avère que dans votre situation, il n'y a pas d'alternative à le faire manuellement, vous savez maintenant au moins comment il s'appelle et pouvez le lire.
Donc, en bref: si vous faites effectivement du DbC, même si vous ne le savez pas, alors ces affirmations sont parfaitement bien.
la source
Chaque fois que vous n'avez pas un contrôle total sur vos paramètres d'entrée, c'est une très bonne idée de tester à l'avance les erreurs simples. Échec sur null par exemple.
Ce n'est pas une duplication de vos tests, car ils devraient tester que le code échoue de manière appropriée en raison de mauvais paramètres d'entrée, puis documenter cela .
Je ne pense pas que vous devriez affirmer sur les paramètres de retour (sauf si vous avez explicitement un invariant que vous voulez que le lecteur comprenne). C'est aussi le travail des non-testés.
Personnellement, je n'aime pas la
assert
déclaration en Java, car ils peuvent être désactivés et c'est une fausse sécurité.la source
Je pense que l'utilisation d'assertions dans les méthodes publiques est encore plus importante, car là vous ne contrôlez pas les entrées et il est plus probable que l'hypothèse soit brisée.
Le test des conditions d'entrée doit être effectué dans toutes les méthodes publiques et protégées. Si les entrées sont transmises directement à une méthode privée, tester ses entrées peut être redondant.
Le test des conditions de sortie (par exemple l'état de l'objet ou cette valeur de retour! = Null) doit être effectué dans les méthodes internes (par exemple les méthodes privées). Si les sorties sont transmises directement d'une méthode privée à la sortie d'une méthode publique sans calculs supplémentaires ni changements d'état interne, le test des conditions de sortie de la méthode publique peut être redondant.
Je suis d'accord avec Oleksi, cependant, que la redondance peut augmenter la lisibilité et elle peut également augmenter la maintenabilité (si l'affectation directe ou le retour n'est plus le cas à l'avenir).
la source
Il est difficile d'être indépendant de la langue à propos de ce problème, car les détails de la façon dont les assertions et la gestion «correcte» des erreurs / exceptions sont implémentées ont une incidence sur la réponse. Voici mon 0,02 $, basé sur ma connaissance de Java et C ++.
Les affirmations dans les méthodes privées sont une bonne chose, en supposant que vous n'allez pas trop loin et ne les mettez pas partout . Si vous les appliquez à des méthodes très simples ou vérifiez à plusieurs reprises des choses comme des champs immuables, vous encombrez le code inutilement.
Il vaut mieux éviter les affirmations dans les méthodes publiques. Vous devriez toujours faire des choses comme vérifier que le contrat de méthode n'est pas violé, mais si c'est le cas, vous devriez lancer des exceptions de type approprié avec des messages significatifs, revenir à l'état lorsque cela est possible, etc. (ce que @rwong appelle "le plein traitement correct des erreurs ").
De manière générale, vous ne devez utiliser que des assertions pour faciliter votre développement / débogage. Vous ne pouvez pas supposer que quiconque utilise votre API aura même des assertions activées lorsqu'il utilisera votre code. Bien qu'ils aient une certaine utilité pour aider à documenter le code, il existe souvent de meilleures façons de documenter les mêmes choses (c.-à-d. Documentation de méthode, exceptions).
la source
Ajout à la liste des réponses (principalement) exceptionnelles, une autre raison pour beaucoup d'affirmations et de duplication, c'est que vous ne savez pas comment, quand ni par qui la classe sera modifiée au cours de sa durée de vie. Si vous écrivez du code à jeter qui sera mort dans un an, ce n'est pas un problème. Si vous écrivez du code qui sera utilisé dans plus de 20 ans, il sera très différent - et une supposition que vous avez faite peut ne plus être valide. Le gars qui fait ce changement vous remerciera pour les assertions.
De plus, tous les programmeurs ne sont pas parfaits - encore une fois, les assertions signifient que l'un de ces "dérapages" ne se propagera pas trop loin.
Ne sous-estimez pas l'effet que ces affirmations (et d'autres vérifications sur les hypothèses) auront sur la réduction des coûts de maintenance.
la source
Avoir des assertions en double n'est pas mauvais en soi, mais avoir les assert "juste pour être sûr" n'est pas le meilleur. Cela se résume vraiment à ce que chaque test essaie d'accomplir. N'affirmez que ce qui est absolument nécessaire. Si un test utilise Moq pour vérifier qu'une méthode est invoquée, peu importe ce qui se passe après l'invocation de cette méthode, le test ne vise qu'à s'assurer que la méthode est invoquée.
Si chaque test unitaire a le même ensemble d'assertions, sauf un ou deux, alors lorsque vous refactorisez un peu tous les tests peuvent échouer pour la même raison exacte, au lieu de vous montrer le véritable impact du refactor. Vous pourriez vous retrouver dans une situation où vous exécutez tous les tests, ils échouent tous parce que chaque test a les mêmes assertions, vous corrigez cet échec, réexécutez les tests, ils échouent pour une autre raison, vous corrigez cet échec. Répétez jusqu'à ce que vous ayez terminé.
Pensez également à la maintenance de votre projet de test. Que se passe-t-il lorsque vous ajoutez un nouveau paramètre ou que la sortie est légèrement modifiée, devrez-vous revenir en arrière à travers un tas de tests et modifier une assertion ou ajouter une assertion? Et, selon votre code, vous pourriez avoir à configurer beaucoup plus juste pour vous assurer que toutes les assertions passent.
Je peux comprendre l'attrait de vouloir inclure des assertions en double dans le test unitaire, mais c'est vraiment exagéré. J'ai suivi le même chemin avec mon premier projet de test. Je m'en suis éloigné car l'entretien seul me rendait dingue.
la source
Si votre infrastructure de test autorise les accesseurs, alors les tests unitaires des méthodes privées sont également une bonne idée (IMO).
Je fais. Les affirmations sont correctes, mais votre premier objectif devrait être de faire en sorte que le scénario ne soit même pas possible ; pas seulement que cela n'arrive pas.
la source
C'est une mauvaise pratique.
Vous ne devez pas tester les méthodes publiques / privées. Vous devez tester la classe dans son ensemble. Assurez-vous simplement d'avoir une bonne couverture.
Si vous optez pour la méthode (primitive) de tester chaque méthode séparément en règle générale, vous aurez du mal à refactoriser votre classe à l'avenir. Et c'est l'une des meilleures choses que TDD vous permet de faire.
Par ailleurs, il est double emploi. De plus, cela suggère que l'auteur du code ne savait pas vraiment ce qu'il faisait. Et le plus drôle, c'est que vous le faites .
Certaines personnes traitent leurs tests avec moins de soin que leur code de production. Ils ne devraient pas. Si quoi que ce soit, mon expérience suggère même de traiter les tests avec plus de soin. Ils en valent la peine.
la source