Je sais que vous n'êtes pas censé tester des méthodes privées, et s'il semble que vous en ayez besoin, il pourrait y avoir une classe en attente de sortie.
Mais, je ne veux pas avoir de classes gazillion juste pour pouvoir tester leurs interfaces publiques et je trouve que pour de nombreuses classes si je teste juste les méthodes publiques, je finis par devoir me moquer de beaucoup de dépendances et les tests unitaires sont énorme et difficile à suivre.
Je préfère de beaucoup se moquer des méthodes privées lors du test des méthodes publiques et se moquer des dépendances externes lors du test des méthodes privées.
Suis-je fou?
unit-testing
mocking
Fran Sevillano
la source
la source
Réponses:
Vous avez partiellement raison - vous ne devriez pas tester directement des méthodes privées. Les méthodes privées d'une classe doivent être appelées par une ou plusieurs des méthodes publiques (peut-être indirectement - une méthode privée appelée par une méthode publique peut invoquer d'autres méthodes privées). Par conséquent, lors du test de vos méthodes publiques, vous testerez également vos méthodes privées. Si vous disposez de méthodes privées qui n'ont pas été testées, vos cas de test sont insuffisants ou les méthodes privées sont inutilisées et peuvent être supprimées.
Si vous adoptez une approche de test en boîte blanche, vous devez considérer les détails d'implémentation de vos méthodes privées lors de la construction de tests unitaires autour de vos méthodes publiques. Si vous adoptez une approche de boîte noire, vous ne devez pas tester les détails d'implémentation dans les méthodes publiques ou privées, mais contre le comportement attendu.
Personnellement, je préfère une approche en boîte blanche aux tests unitaires. Je peux créer des tests pour mettre les méthodes et les classes sous test dans différents états qui provoquent un comportement intéressant dans mes méthodes publiques et privées, puis affirmer que les résultats sont ce que j'attends.
Alors - ne vous moquez pas de vos méthodes privées. Utilisez-les pour comprendre ce que vous devez tester afin de fournir une bonne couverture des fonctionnalités que vous fournissez. Cela est particulièrement vrai au niveau du test unitaire.
la source
Je pense que c'est une très mauvaise idée.
Le problème avec la création de tests unitaires de membres privés, c'est qu'elle s'intègre mal avec le cycle de vie du produit.
La raison pour laquelle vous avez CHOISI de rendre ces méthodes privées est qu'elles ne sont pas au cœur de ce que vos classes essaient de faire - juste des aides sur la façon dont vous implémentez actuellement cette fonctionnalité. En refactorisant, ces détails privés sont susceptibles de changer et provoqueront alors des frictions avec le refactoring.
En outre, une différence clé entre les membres publics et privés est que vous devez bien réfléchir à votre API publique, la documenter correctement et la vérifier correctement (assertions, etc.). Mais avec une API privée, il serait inutile de réfléchir aussi soigneusement (un effort inutile puisque son utilisation est tellement localisée). Mettre des méthodes privées dans des tests unitaires revient à créer des dépendances externes sur ces méthodes. Cela signifie que l'API doit être stable et bien documentée (car quelqu'un doit comprendre pourquoi ces tests unitaires ont échoué si / quand ils le font).
Je vous suggère:
A appréciez votre envie de tester cette fonctionnalité et qu'il est difficile de la tester via votre API publique actuelle. Mais je préfère personnellement la modularité à la couverture des tests.
la source
Les tests unitaires testent le comportement public observable , pas le code, où "public" signifie: valeurs de retour et communication avec les dépendances.
Une "unité" est n'importe quel code, qui résout le même problème (ou plus précisément: a la même raison de changer). Cela peut être une méthode unique ou un groupe de classes.
La raison principale pour laquelle vous ne voulez pas tester
private methods
est: ce sont des détails d'implémentation et vous voudrez peut-être les changer pendant le refactoring (améliorez votre code en appliquant les principes OO sans changer la fonctionnalité). C'est exactement lorsque vous ne voulez pas que vos tests ne changent pas afin qu'ils puissent garantir que le comportement de votre CuT n'a pas changé pendant le refactoring.J'expérimente généralement le contraire: plus les classes sont petites (moins elles ont de responsabilités), moins elles ont de dépendances, et plus il est facile à la fois d'écrire et de lire.
Idéalement, vous appliquez le même niveau de modèle d' abstraction à vos classes. Cela signifie que vos classes fournissent soit une logique métier (de préférence sous forme de "fonctions pures" travaillant uniquement sur leurs paramètres sans maintenir un état propre) (x), soit des méthodes d'appel sur d'autres objets, pas les deux en même temps.
De cette façon , il n'est pas nécessaire de tester le comportement de l'entreprise et les objets de «délégation» sont généralement trop simples pour échouer (pas de branchement, pas de changement d'état) de sorte qu'aucune interruption ne soit nécessaire et que leurs tests puissent être laissés à des tests d' intégration ou de module.
la source
Les tests unitaires ont une certaine valeur lorsque vous êtes le seul programmeur à travailler sur le code, surtout si l'application est très grande ou très complexe. Lorsque les tests unitaires deviennent essentiels, c'est lorsque vous avez un plus grand nombre de programmeurs travaillant sur la même base de code. Le concept de tests unitaires a été introduit pour résoudre certaines des difficultés de travail dans ces grandes équipes.
La raison pour laquelle les tests unitaires aident les équipes plus importantes est liée aux contrats. Si mon code effectue des appels à du code écrit par quelqu'un d'autre, je fais des hypothèses sur ce que le code de l'autre personne va faire dans diverses situations. À condition que ces hypothèses soient toujours vraies, mon code fonctionnera toujours, mais comment puis-je savoir quelles hypothèses sont valides et comment savoir quand ces hypothèses ont changé?
C'est là qu'interviennent les tests unitaires. L'auteur d'une classe crée des tests unitaires pour documenter le comportement attendu de leur classe. Le test unitaire définit toutes les manières valides d'utiliser la classe et l'exécution du test unitaire valide le fonctionnement de ces cas d'utilisation comme prévu. Un autre programmeur qui souhaite utiliser votre classe peut lire vos tests unitaires pour comprendre le comportement qu'ils peuvent attendre de votre classe, et l'utiliser comme base pour leurs hypothèses sur le fonctionnement de votre classe.
De cette façon, les signatures de méthode publique de la classe et les tests unitaires forment ensemble un contrat entre l'auteur de la classe et les autres programmeurs qui utilisent cette classe dans leur code.
Dans ce scénario, que se passe-t-il si vous incluez des tests de méthodes privées? De toute évidence, cela n'a aucun sens.
Si vous êtes le seul programmeur à travailler sur votre code et que vous souhaitez utiliser les tests unitaires comme moyen de déboguer votre code, je ne vois aucun inconvénient à cela, c'est juste un outil, et vous pouvez l'utiliser de toute façon qui fonctionne pour vous, mais ce n'était pas la raison pour laquelle les tests unitaires ont été introduits, et ne fournit pas les principaux avantages des tests unitaires.
la source
Avant de répondre à une telle question, vous devez décider de ce que vous voulez réellement réaliser.
Vous écrivez du code. Vous espérez qu'il remplit son contrat (en d'autres termes, il fait ce qu'il est censé faire. Écrire ce qu'il est censé faire est un grand pas en avant pour certaines personnes).
Pour être raisonnablement convaincu que le code fait ce qu'il est censé faire, soit vous le regardez suffisamment longtemps, soit vous écrivez du code de test qui teste suffisamment de cas pour vous convaincre "si le code passe tous ces tests, alors il est correct".
Souvent, vous n'êtes intéressé que par l'interface définie publiquement d'un code. Si j'utilise votre bibliothèque, je ne me soucie comment vous l' avez fait correctement, seulement qu'il fait correctement. Je vérifie que votre bibliothèque est correcte en effectuant des tests unitaires.
Mais vous créez la bibliothèque. Le faire fonctionner correctement peut être difficile à réaliser. Disons que je me soucie seulement que la bibliothèque fasse correctement l'opération X, j'ai donc un test unitaire pour X. Vous, le développeur responsable de la création de la bibliothèque, implémentez X en combinant les étapes A, B et C, qui sont chacune totalement non triviales. Pour faire fonctionner votre bibliothèque, vous ajoutez des tests pour vérifier que A, B et C fonctionnent correctement. Vous voulez ces tests. Dire "vous ne devriez pas avoir de tests unitaires pour les méthodes privées" est tout à fait inutile. Vous voulez des tests pour ces méthodes privées. Peut-être que quelqu'un vous dit que les tests unitaires de méthodes privées sont faux. Mais cela signifie seulement que vous pourriez ne pas les appeler des "tests unitaires" mais des "tests privés" ou tout ce que vous voulez les appeler.
Le langage Swift résout le problème que vous ne voulez pas exposer A, B, C en tant que méthodes publiques juste parce que vous voulez le tester en donnant aux fonctions un attribut "testable". Le compilateur permet d'appeler des méthodes testables privées à partir de tests unitaires, mais pas à partir de code non test.
la source
Oui, vous êtes fou .... COMME UN RENARD!
Il existe plusieurs façons de tester des méthodes privées, dont certaines dépendent de la langue.
Dans l'ensemble, cependant, si vous souhaitez tester des méthodes privées, vous souhaiterez probablement les déplacer vers des méthodes publiques sur une dépendance et tester / injecter cela.
la source
Restez pragmatique. Tester des cas spéciaux dans des méthodes privées en définissant l'état de l'instance et les paramètres d'une méthode publique de sorte que ces cas se produisent là-bas, est souvent beaucoup trop compliqué.
J'ajoute un
internal
accesseur supplémentaire (avec le flagInternalsVisibleTo
l'assembly de test), clairement nomméDoSomethingForTesting(parameters)
, afin de tester ces méthodes "privées".Bien sûr, l'implémentation peut changer quelquefois, et ces tests, y compris les accesseurs de test, deviennent obsolètes. C'est encore mieux que les cas non testés ou les tests illisibles.
la source