web-dev-qa-db-fra.com

Dois-je tester la méthode privée/protégée?

C'est en réalité une langue agnostique. Mais je vais vous donner le contexte en python.

J'ai cette classe de parent

class Mammal(object):
    def __init__(self):
        """ do some work """

    def eat(self, food):
        """Eat the food"""
        way_to_eat = self._eating_method()
        self._consume(food)

    def _eating_method(self):
        """Template method"""

    def _consume(self, food):
        """Template method"""

Ici, eat est la seule méthode publique alors que _consume et _eating_method sont en réalité des méthodes protégées qui seront implémentées par des classes enfants.

Que testerez-vous lorsque vous aurez écrit uniquement la classe Mammal?

Évidemment toutes les 4 méthodes.

Présentons maintenant un enfant

class Tiger(Mammal):    
    def _eating_method(self):
        """Template method"""

    def _consume(self, food):
        """Template method"""

Regardez cette classe. Il n'a que 2 méthodes protected.

Devrais-je tester les 4 méthodes de Tiger (dont 2 héritées) ou simplement tester les modifications introduites (seulement 2 méthodes remplacées)?

Quel est le cas idéal?

20
Shiplu Mokaddim

D'un point de vue théorique, il vous suffit de tester les méthodes publiques de vos classes instanciables (dans les langues standard OOP). Il est inutile de tester le comportement interne car tout ce que vous voulez, c'est "quelle sortie pour cette entrée" (pour une méthode particulière ou pour toute la classe). Vous devriez essayer de la respecter autant que vous le pouvez car cela vous oblige à poser quelques questions sur le encapsulation } de votre classe et l'interface fournie qui peut être déterminante pour votre architecture.

D'un point de vue pragmatique, vous pouvez parfois avoir des classes abstraites d'assistance sans sous-classe concrète implémentée ou une classe abstraite factorisant plus de 90% de ses classes enfants et où il serait trop difficile de tester le résultat sans se connecter une méthode protégée. Dans ce genre de cas, vous pouvez simuler une sous-classe.

Dans votre exemple simple, je vous suggérerais de ne tester que la classe Tiger (et uniquement la méthode publique eat).

Juste une note pour les personnes qui pensent à TDD . En TDD, vous n'auriez pas dû commencer à coder la classe Mammal avant la classe Tiger car Mammal devrait être le résultat d'une phase de refactoring. Donc, vous n’auriez certainement pas de test spécifique pour Mammal.

33
Gnucki

La façon dont j'aborderais ceci est:

  • Créez une sous-classe minimale testable de Mammal qui fournit une implémentation minimale des deux méthodes protégées, ce qui vous permet de tester le comportement des méthodes publiques.
  • Ecrivez des tests unitaires distincts pour chaque sous-classe, qui teste à nouveau les méthodes publiques sur Mammal, mais affirme le comportement spécifique à cette sous-classe.

Cela devrait vous donner la couverture de tests nécessaire avec un nombre minimal de tests.

Une approche alternative consisterait à tester les sous-classes uniquement, et sur l'un des tests unitaires de la sous-classe, affirmerons également les caractéristiques propres à Mammal. Cela évite de créer une sous-classe de test spécifique. Toutefois, les deux inconvénients sont les suivants:

  • Vous ne testez plus Mammal isolément et, par conséquent, les tests du code spécifique à Mammal sont susceptibles d'échouer à cause de problèmes dans la sous-classe.
  • Cela sera peut-être moins évident pour d’autres comment et où les propriétés de Mammal sont testées.
5
robjohncox

Lors des tests, vous devez vous concentrer sur le comportement extérieur de votre code, et non sur les détails de la mise en œuvre. Je ne connais pas le contexte, je vais donc faire quelques hypothèses énormes ici. 

Vous souciez-vous vraiment du comportement d'une super-classe de mammifères (potentiellement abstraite)? La relation de réutilisation par héritage est-elle importante? Que faire si vous décidez de remplacer la relation d'héritage par une stratégie basée sur la composition?

Je me concentrerais sur le test du comportement des cours qui vous intéressent: "Un tigre mange-t-il comme prévu?" au lieu de tester une superclasse abstraite introduite uniquement pour la réutilisation du code.

0
prgmtc