2014-12-30 9 views
11

Dies ist eigentlich Sprache agnostic. Aber ich gebe dir Kontext in Python.Sollte ich privat/geschützte Methode unittest

Ich habe diese Elternklasse

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""" 

Hier eat die einzige öffentliche Methode während _consume und _eating_method sind Methoden tatsächlich geschützt, die von untergeordneten Klassen umgesetzt werden.

Was werden Sie testen, wenn Sie nur die Mammal Klasse geschrieben haben?

Offensichtlich alle 4 Methoden.

Lassen Sie uns jetzt

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

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

Schauen Sie sich diese Klasse ein Kind vorstellen. Es hat nur 2 geschützt Methoden.

Sollte ich alle 4 Methoden von Tiger testen (einschließlich 2 geerbt) oder nur die Änderungen testen (nur übersteuert 2 Methoden)?

Was ist der Idealfall?

+0

Das hängt davon ab. Normalerweise wird die "Essen" -Methode mit allen möglichen Ergebnissen von "Trainingsmethode" und "Consumer" getestet. Also müssen nur die veränderten Methoden getestet werden. – Daniel

Antwort

16

Aus theoretischer Sicht, müssen Sie nur öffentliche Methoden Ihrer instantiable Klassen (in Standard OOP-Sprachen) testen. Es hat keinen Sinn, das interne Verhalten zu testen, weil Sie nur wollen, "welche Ausgabe für diese Eingabe" (für eine bestimmte Methode oder für die gesamte Klasse). Sie sollten versuchen, es so gut wie möglich zu respektieren, weil es Sie zwingt, einige Fragen über die encapsulation Ihrer Klasse und die bereitgestellte Schnittstelle zu stellen, die für Ihre Architektur entscheidend sein kann.

Aus pragmatischer Sicht, können Sie manchmal ohne implementiert konkrete Unterklasse oder einer abstrakten Klasse 90 + Factoring einige abstrakte Hilfsklassen haben% ihres Kindes Klassen und wo es wäre zu hart sein, um die Ausgabe zu testen, ohne dass Einstecken in eine geschützte Methode. In diesen Fällen können Sie eine Unterklasse mock.

In Ihrem einfachen Beispiel würde ich vorschlagen, dass Sie nur die Klasse Tiger testen (und nur die öffentliche Methode eat).

Nur eine Anmerkung für Leute, die an TDD denken. In TDD sollten Sie nicht begonnen haben, die Klasse Mammal vor der Klasse Tiger zu codieren, da Mammal das Ergebnis einer Refaktorisierungsphase sein sollte. Sie hätten also bestimmt keinen spezifischen Test für Mammal.

+0

Also sollte ich 'Tiger.eat()' testen, oder? –

+1

Ja, Sie können diese Methode nur testen (die einzige, die öffentlich ist). – Gnucki

5

So wie ich diesen Ansatz würde, ist:

  • erstellen minimal prüfbar Unterklasse von Mammal der minimalen Implementierungen der beiden geschützten Methoden bietet, die Sie Unit-Test das Verhalten der öffentlichen Methoden ermöglichen.
  • Schreiben Sie separate Komponententests für jede Unterklasse, die wiederum die öffentlichen Methoden auf Mammal testen, aber das für diese Unterklasse spezifische Verhalten bestätigen.

Dies sollte Ihnen die notwendige Testabdeckung mit einer minimalen Anzahl von Tests geben.

Ein alternativer Ansatz wäre, nur die Unterklassen zu testen, und bei einem der Unterklassen-Komponententests auch die für spezifischen Merkmale. Dies vermeidet die Notwendigkeit eine spezifische Testunterklasse zu erstellen, jedoch zwei Nachteile sind:

  • Sie sind nicht mehr testen Mammal in Isolation und damit die Tests auf dem Mammal spezifischen Code anfällig sind aufgrund von Problemen in der Unterklasse zu Versagen .
  • Es mag für andere weniger offensichtlich sein, wie und wo die Eigenschaften von Mammal getestet werden.
0

Beim Testen sollten Sie sich auf das äußere Verhalten Ihres Codes konzentrieren, nicht auf Implementierungsdetails. Ich kenne den Kontext nicht, also werde ich hier nur ein paar große Annahmen machen.

Interessiert Sie wirklich das Verhalten einer (möglicherweise abstrakten) Säugersuperklasse? Ist die Wiederverwendung durch Vererbung wichtig? Was, wenn Sie sich dazu entscheiden, die Vererbungsbeziehung durch eine kompositionsbasierte Strategie zu ersetzen?

Ich würde mich darauf konzentrieren, das Verhalten der Klassen zu testen, die Sie wirklich interessieren: "Isst ein Tiger wie erwartet?" anstatt eine abstrakte Oberklasse zu testen, die nur für die Wiederverwendung von Code eingeführt wird.