Est-il correct de modifier la visibilité de la méthode pour des tests unitaires?

Plusieurs fois, je me trouve déchiré entre rendre une méthode privée pour empêcher quelqu’un de l’appeler dans un contexte qui n’a pas de sens (ou bousillerait l’état interne de l’object concerné) ou rendre la méthode publique (ou généralement interne) afin de l’exposer à l’ensemble de test unitaire. Je me demandais ce que la communauté Stack Overflow pensait de ce dilemme?

Donc, je suppose que la question est vraiment, est-il préférable de se concentrer sur la testabilité ou sur le maintien d’une encapsulation appropriée?

Dernièrement, je me suis penché sur la testabilité, car la plupart des codes ne seront exploités que par un petit groupe de développeurs, mais je pensais voir ce que tout le monde pensait?

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 par d’autres types dans le même assemblage, utilisez internal, friend, votre assembly de test unitaire et l’unité testez-le.

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 doit être protégé ou privé et ne doit être testé que indirectement par des tests unitaires de votre API publique. Si vous écrivez des tests unitaires pour des membres non publics (ou des membres 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, qui augmente la quantité de tests unitaires dont vous avez besoin, augmente la charge de travail à court terme (plus de tests unitaires) et à long terme (plus de maintenance et de modification des tests en réponse aux détails internes de la mise en œuvre). Un autre problème lié au test des membres non publics est que vous testez un code qui peut ne pas être réellement nécessaire ou utilisé. Un excellent moyen de trouver le code mort est lorsqu’il n’est couvert par aucun de vos tests unitaires lorsque votre API publique est couverte à 100%. Supprimer le code mort est un excellent moyen de garder votre base de code simple et efficace, et est impossible si vous ne faites pas attention à ce que vous insérez dans votre API publique et quelles parties de votre code vous testez.

EDIT: En guise de remarque supplémentaire rapide … avec une API publique correctement conçue, vous pouvez utiliser très efficacement un outil tel que Microsoft PEX pour générer automatiquement des tests unitaires complets qui testent chaque chemin d’exécution de votre code. Combiné à quelques tests écrits manuellement qui couvrent le comportement critique, tout ce qui n’est pas couvert peut être considéré comme du code mort et supprimé, et vous pouvez considérablement raccourcir votre processus de test unitaire.

Ce n’est pas OK pour 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 les méthodes que n’importe quel utilisateur stupide pourrait essayer d’utiliser et exploser votre application … c’est un passif dont vous n’avez pas besoin.

Vous utilisez C # oui? Découvrez les composants internes visibles pour atsortingbuer la classe. Vous pouvez déclarer vos méthodes testables comme internes et permettre à votre unité de tester l’access à vos composants internes.

C’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 (afin de ne pas tester 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 à cette question (Java) et à cette question (.NET) devraient être utiles.

Pour répondre à la question: non, vous ne devez pas modifier la visibilité de la méthode pour tester. En général, vous ne devriez pas tester des méthodes privées et, lorsque vous le faites, il existe de meilleures façons de le faire.

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

Lorsque vous essayez de travailler avec du code hérité, la clé est de le tester. Après cela, vous pouvez append des tests pour les nouvelles fonctionnalités et les bogues existants, refactor pour améliorer la conception, etc. Ceci est risqué sans tests. Le code hérité a tendance à être associé à des dépendances et il est souvent extrêmement difficile de le tester.

En travaillant efficacement avec Legacy Code , Michael Feathers suggère plusieurs techniques pour tester le code. Beaucoup de ces techniques impliquent de briser l’encapsulation ou de compliquer la conception, et l’auteur est au courant à ce sujet. Une fois les tests mis en place, le code peut être amélioré en toute sécurité.

Donc, pour le code hérité, faites ce que vous devez faire.

Dans .NET, vous devez utiliser Accessors pour les tests unitaires, même plutôt que l’atsortingbut InternalsVisibleTo. Les accesseurs vous permettent d’accéder à toute 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 object vide dérivé (voir la classe “PrivateObject”).

Fondamentalement, dans votre projet de test, vous utilisez la classe d’accesseur plutôt que la classe réelle avec les méthodes que vous souhaitez tester. La classe des accesseurs 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 les tests unitaires.

IMO est-il incorrect de dire que vous ne devriez pas tester les méthodes privées. 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.