Java >> Tutoriel Java >  >> Tag >> private

C'est correct de tester des méthodes privées

Google l'expression "devrais-je tester des méthodes privées", et vous obtiendrez une multitude d'opinions qui se résument à "non". Heureusement, je suis ici pour vous dire que vous pouvez tester des méthodes privées.

Quel est le problème ?

En ce moment, je suis en formation pour enseigner un cours de logiciel dans mon université, et je travaillais sur une classe utilitaire en Java qui avait une tonne de méthodes d'assistance privées. Dans mon cas particulier, il n'y avait en fait aucune méthode publique exposée au-delà de main , et je trouve difficile d'écrire des tests qui interagissent avec les flux d'entrée. En conséquence, je voulais écrire des tests JUnit pour prouver la fonctionnalité des méthodes privées.

Cependant, lorsque je me suis tourné vers Google, j'ai constaté que la plupart des experts disaient de ne pas tester les méthodes privées :

  • Pourquoi les tests en boîte blanche sont-ils déconseillés en POO ?
  • Faut-il tester les méthodes privées ?
  • Comment testez-vous les méthodes privées ?
  • Effectuez-vous des tests unitaires de méthodes privées ?

Au lieu de cela, ils soutiennent que nous devrions tester nos méthodes publiques qui appellent nos méthodes privées. Dans les sous-sections suivantes, je vais essayer de décomposer leur argument.

Les méthodes privées sont des détails de mise en œuvre

Un argument courant contre le test des méthodes privées est que les méthodes privées sont des détails d'implémentation :

Une méthode privée est un détail d'implémentation qui doit être caché aux utilisateurs de la classe. Tester des méthodes privées rompt l'encapsulation.

jop, 2008

En d'autres termes, la façon dont une solution est mise en œuvre n'est pas pertinente du point de vue des tests. En fin de compte, nous voulons tester notre solution en fonction de son comportement attendu pour l'utilisateur.

Les tests de méthodes privées sont fragiles

Étant donné que les méthodes privées sont des détails d'implémentation, nous sommes libres de modifier ces détails avec peu ou pas de frais pour nous. Cependant, si nous choisissons de tester nos méthodes privées, nous courons le risque de casser nos tests. En conséquence, nos tests deviennent cassants, ce qui signifie qu'ils se cassent facilement. En fait, je pense qu'un utilisateur de Stack Overflow l'a dit le mieux :

Le problème ici est que ces "futurs changements de code" signifient invariablement la refactorisation du fonctionnement interne de certaines classes. Cela arrive si souvent que l'écriture de tests crée un obstacle à la refactorisation.

Programmeur hors-la-loi, 2008

En d'autres termes, les tests fragiles peuvent entraver la refactorisation, ce qui constitue un obstacle à l'amélioration du code.

Les échecs des tests de méthodes privées peuvent ne pas avoir d'importance

L'un des arguments les plus intéressants que j'ai vus ressemble à ceci :

Si vous ne pouvez pas casser la méthode publique, est-ce que ce que font les méthodes privées est vraiment important ?

Rig, 2012

En d'autres termes, nous pouvons peut-être casser nos méthodes privées, mais les méthodes exposées peuvent être soumises à des contraintes différentes qui font que l'erreur dans la méthode privée ne se manifeste jamais.

Un cas pour tester des méthodes privées

En général, je suis d'accord avec tous les arguments contre le test des méthodes privées. En fait, si je n'avais pas rencontré mes propres besoins pour tester des méthodes privées, j'aurais peut-être été de ce côté de la clôture. Comme toujours, cependant, la question est un peu plus nuancée.

Les méthodes publiques dépendent des détails de mise en œuvre

Lorsque nous soutenons que nous ne devrions pas nous soucier des détails de mise en œuvre, nous courons le risque de manquer des cas extrêmes où nos méthodes publiques tombent en panne. En d'autres termes, savoir comment notre système est conçu sous le capot est essentiel pour s'assurer qu'il fonctionne correctement. Comment pourrions-nous prouver que cela fonctionne autrement ?

Comme une sorte d'exemple idiot, imaginez une méthode de séquence de Fibonacci qui génère le terme dans la séquence en fonction d'un indice. Si nous testons cette méthode, comment savons-nous combien d'entrées essayer de vérifier que la méthode fonctionne ? Avec les tests de boîte noire, nous devrions tous les essayer. Avec les tests en boîte blanche (qui dépendent des détails de mise en œuvre), nous n'aurions qu'à toucher toutes les branches.

Bien sûr, je ne pense pas que quiconque fasse valoir que les méthodes publiques ne devraient pas être testées en boîte blanche, mais cela m'amène à mon deuxième point :les tests de méthodes publiques sont tout aussi fragiles que les tests de méthodes privées, et ils sont souvent gonflé.

Les tests de méthodes publiques sont fragiles et souvent gonflés

Étant donné que les tests de méthodes privées dépendent des détails d'implémentation, il est possible que les tests se cassent à mesure que les exigences changent. Cela dit, je ne suis pas sûr que les méthodes publiques soient claires à cet égard non plus.

Par exemple, les méthodes peuvent parfois affecter l'état d'un objet. Nous appelons généralement ces méthodes d'instance car elles interagissent directement avec une instance d'un objet. Afin de tester une méthode d'instance, nous devons généralement configurer l'état de cet objet afin de pouvoir surveiller son comportement lorsque nous appelons cette méthode dessus.

Étant donné que nous sommes bloqués à l'aide de méthodes publiques pour configurer notre objet pendant les tests, nous pouvons nous retrouver dans un scénario où les tests dépendent du comportement de plusieurs méthodes, pas nécessairement de la méthode testée. Si nous avions accès à des méthodes privées (setters par exemple), nous serions en mesure de définir l'état de l'objet sans devenir dépendant d'autres méthodes publiques qui peuvent ou non fonctionner.

Pour aggraver les choses, les tests en boîte blanche deviennent un cauchemar. Du coup, nous devons introduire toutes sortes de données dans notre API publique dans l'espoir d'obtenir une couverture de code appropriée. Il serait beaucoup plus facile de tester directement les méthodes privées et de jeter ces tests lorsque ces méthodes privées ne sont plus nécessaires.

En termes de lisibilité uniquement, imaginez essayer de nommer plus de 50 tests uniques pour une seule méthode. Après plusieurs cycles de refactorisation, vous ne sauriez même pas quels tests valaient la peine d'être supprimés. Les tests de méthode privés maintiennent la séparation des responsabilités claire.

Enfin, imaginez déprécier une méthode publique maintenue par plus de 50 tests. Non seulement tous ces tests sont gaspillés, mais le sophisme des coûts irrécupérables garantit essentiellement que nous refuserons de déprécier une méthode publique en raison de la quantité de tests derrière elle. L'élan des cas de test accumulés nous empêchera à lui seul d'améliorer notre code.

Les échecs des tests de méthodes privées sont importants

En fin de compte, nous arrivons au dernier argument :si les méthodes publiques fonctionnent, qui se soucie de ce que font les méthodes privées ? En d'autres termes, tant que l'API fonctionne, peu importe si une fonctionnalité interne échoue ou non à un test. Au moins, j'ai l'impression que c'est l'argument avancé ici, n'est-ce pas ?

Pour moi, les échecs de test de méthode privée devraient avoir de l'importance car cette erreur peut se manifester tout au long de la ligne. Après tout, le codage est un processus dynamique. En d'autres termes, un problème sous-jacent peut ne pas se manifester aujourd'hui, mais seulement 3 versions plus tard. Par conséquent, ignorer activement une méthode privée qui peut avoir un bogue est une bombe à retardement.

De plus, je ne suis pas non plus fan du sentiment suscité par cet argument. Pour être honnête, je serais vraiment inquiet si le même genre d'argument était avancé dans d'autres disciplines de l'ingénierie. Par exemple, j'espère que les constructeurs d'avions testeront minutieusement leur équipement même s'ils disposent d'une triple redondance pour couvrir les pannes.

Cela dit, je trouve que l'argument original est le plus convaincant. Nous pouvons débattre du mérite de tester des méthodes privées toute la journée, mais beaucoup de logiciels ne sont tout simplement pas critiques. Dans le monde d'aujourd'hui, les logiciels évoluent rapidement et les tests publics de méthodes suffisent probablement. Merde, je préférerais ça à la télémétrie.

Il n'y a rien de mal à tester des méthodes privées

Lorsque j'ai décidé d'écrire cet article, c'était en réponse à la quantité écrasante de littérature en ligne qui affirme que tester des méthodes privées est une mauvaise idée. Pour être honnête, je pensais que c'était un peu bizarre. Après tout, j'ai été dans des situations où une méthode publique est construite sur des couches de méthodes privées, donc tester l'interface publique devient un moyen vraiment inefficace d'isoler les bogues. En d'autres termes, comment savons-nous comment écrire le bon test pour exercer toutes les branches sur une méthode privée sous-jacente ?

Quoi qu'il en soit, s'il est réellement pratique ou non de tester des méthodes privées est une question complètement différente, mais je n'irais pas jusqu'à dire que les tests de méthodes privées sont bons ou mauvais. Comme beaucoup de débats en informatique, la question est plus nuancée.

Bien sûr, dans le processus d'écriture de cet article, je travaillais également sur une application en Kotlin, et j'ai trouvé qu'il était beaucoup plus pratique de ne tester que l'API publique. Après tout, les méthodes privées sous-jacentes étaient toutes très petites et faciles à raisonner. Cependant, je ne peux pas dire la même chose pour chaque projet que j'ai écrit, alors je vous laisse le choix :faites ce qui a du sens et rien de plus.

En ce moment, il est logique de devenir membre premium de The Renegade Coder ! Avec un abonnement premium, vous aurez un accès complet au blog, vous pourrez donc mieux me connaître. Si vous avez besoin de plus de temps pour comprendre les choses, consultez certains des articles suivants :

  • Le comportement de i=i++ en Java
  • Comment enseigner les tableaux en informatique

Pendant que vous êtes ici, pourquoi ne pas partager ce que vous pensez des tests de méthodes privées ? Est-ce que vous l'évitez strictement, ou sont leurs situations où vous pensez que cela a du sens ?


No
Balise Java