2010-02-25 7 views
38

Plusieurs fois je me trouve déchiré entre faire une méthode privée pour empêcher quelqu'un de l'appeler dans un contexte qui n'a pas de sens (ou bousiller l'état interne de l'objet impliqué), ou rendre la méthode publique (ou typiquement interne) afin de l'exposer à l'ensemble de test unitaire. Je me demandais juste ce que la communauté Stack Overflow pensait de ce dilemme?Est-il acceptable de modifier la visibilité de la méthode pour des tests unitaires?

Donc, je suppose que la question est vraiment, est-il préférable de se concentrer sur la testabilité ou sur le maintien de l'encapsulation appropriée? Dernièrement, je me suis orienté vers la testabilité, car la plupart du code ne sera utilisé que par un petit groupe de développeurs, mais je pensais que je verrais ce que les autres pensaient.

Répondre

15

Cela dépend si la méthode fait partie d'une API publique ou non. Si une méthode n'appartient pas à une partie d'une API publique, mais est appelée publiquement à partir d'autres types au sein du même assembly, utilisez internal, friend votre ensemble de test unitaire et testez-la.

Cependant, si la méthode n'est pas/ne doit pas faire partie d'une API publique et qu'elle n'est pas appelée par d'autres types internes à l'assembly, NE la TESTEZ PAS directement. Il devrait être protégé ou privé, et il devrait seulement être testé indirectement par des tests unitaires de votre API publique. Si vous écrivez des tests unitaires pour des membres non publics (ou qui devraient être non publics) de vos types, vous liez le code de test aux détails d'implémentation internes.

C'est un mauvais type de couplage, augmente la quantité de tests unitaires dont vous avez besoin, augmente la charge de travail à court terme (plus de tests unitaires) et à long terme (maintenance et modification du test en réponse à la refactorisation interne). Détails d'implémentation). Un autre problème lié au test de membres non publics est que vous testez du code qui peut ne pas être nécessaire ou utilisé. Une excellente façon de trouver du code mort est quand il n'est couvert par aucun de vos tests unitaires lorsque votre API publique est couverte à 100%. Supprimer le code mort est une excellente façon de garder votre base de code légère et méchante, et est impossible si vous ne faites pas attention à ce que vous mettez dans votre API publique, et aux parties de votre code que vous testez. En guise de note complémentaire rapide ... avec une API publique correctement conçue, vous pouvez très efficacement utiliser un outil comme Microsoft PEX pour générer automatiquement des tests unitaires de couverture complète qui testent chaque chemin d'exécution de votre code.Combiné avec quelques tests écrits manuellement qui couvrent le comportement critique, tout ce qui n'est pas couvert peut être considéré comme un code mort et supprimé, et vous pouvez grandement raccourcir votre processus de test unitaire.

+0

Vous avez atteint le point crucial de mon problème - les méthodes internes sont encore trop exposées beaucoup, car ce sont des méthodes que les autres classes de l'assembly ne devraient pas appeler. Je suis tout à fait d'accord avec vous sur le fait que tester ce qui devrait être des méthodes non-publiques lie trop étroitement le code de test à la mise en œuvre. – Eric

+0

@Eric: alors vous documentez et appliquez que ces méthodes ne doivent pas être appelées. La nouvelle fonction Diagrammes de couche de VS2010 peut y aider, car on peut créer des restrictions sur la manière dont une couche peut interagir avec une autre - ces restrictions peuvent être appliquées au cours des générations. –

+0

Content d'être utile. :) J'ai ajouté une mise à jour concernant PEX qui pourrait vous intéresser. – jrista

23

Ce n'est PAS correct de changer la visibilité de la méthode sur les méthodes que les clients ou les utilisateurs peuvent voir. Faire cela est moche, un hack, expose des méthodes que tout utilisateur stupide pourrait essayer d'utiliser et d'exploser votre application ... c'est une responsabilité dont vous n'avez pas besoin.

Vous utilisez C# oui? Découvrez la classe d'attributs internals visible to. Vous pouvez déclarer vos méthodes testables comme internes et autoriser l'accès de votre unité de test à vos composants internes.

+0

Comme vous pouvez le dire à partir de ma question, je suis conscient que je peux rendre une méthode interne et visible uniquement aux autres classes de l'assemblage (ou des assemblées d'amis). Je trouve que parfois même les méthodes internes rendent un modèle d'objet moins concis ou bien pensé à ceux qui se développent dans le même assemblage, d'où la question :) – Eric

2

Ceci est une pensée commune.

Il est généralement préférable de tester les méthodes privées en testant les méthodes publiques qui les appellent (vous ne testez donc pas explicitement les méthodes privées). Cependant, je comprends qu'il y a des moments où vous voulez vraiment tester ces méthodes privées.

Les réponses à this question (Java) et this question (.NET) devraient être utiles.

Pour répondre à la question: non, vous ne devez pas modifier la visibilité de la méthode pour des raisons de test. Vous ne devriez généralement pas tester des méthodes privées, et quand vous le faites, il y a de meilleures façons de le faire.

1

En général, je suis d'accord avec @jrista. Mais, comme d'habitude, cela dépend.

Lorsque vous essayez de travailler avec le code existant, la clé est d'obtenir sous test. Après cela, vous pouvez ajouter des tests pour les nouvelles fonctionnalités et les bogues existants, refactoriser pour améliorer la conception, etc. C'est risqué sans tests. Le code hérité tend à être envahi par les dépendances, et il est souvent extrêmement difficile de le tester.

En Working Effectively with Legacy Code, Michael Feathers suggère plusieurs techniques pour obtenir le code en cours de test. Beaucoup de ces techniques impliquent de rompre l'encapsulation ou de compliquer la conception, et l'auteur est au premier plan à ce sujet. Une fois les tests en place, le code peut être amélioré en toute sécurité.

Donc, pour le code existant, faites ce que vous avez à faire.

0

Dans .NET, vous devez utiliser accesseurs pour les tests unitaires, même plutôt que l'attribut InternalsVisibleTo. Les accesseurs vous permettent d'accéder à n'importe quelle méthode de la classe même si elle est privée. Ils vous permettent même de tester des classes abstraites en utilisant un objet dérivé d'un objet vide (voir la classe "PrivateObject").

Fondamentalement dans votre projet de test que vous utilisez la classe accesseur plutôt que la classe réelle avec les méthodes que vous souhaitez tester. La classe accesseur est la même que la classe "real", sauf que tout est public pour votre projet de test. Visual Studio peut générer des accesseurs pour vous. NE JAMAIS rendre un type plus visible pour faciliter le test unitaire.

est l'OMI, il faux de dire que vous ne devriez pas des méthodes privées de tests unitaires. Les tests unitaires sont d'une valeur exceptionnelle pour les tests de régression et il n'y a aucune raison pour que les méthodes privées ne soient pas testées par régression avec des tests unitaires granulaires.

Questions connexes