Ich habe gelesen diese Stelle darüber, wie man private Methoden testet. Ich teste sie normalerweise nicht, weil ich immer dachte, dass es schneller ist, nur öffentliche Methoden zu testen, die von außerhalb des Objekts aufgerufen werden. Testen Sie private Methoden? Sollte ich sie immer testen?
Antworten
Zu viele Anzeigen?Ja, ich teste private Funktionen, denn obwohl sie von Ihren öffentlichen Methoden getestet werden, ist es im TDD (Test Driven Design) schön, den kleinsten Teil der Anwendung zu testen. Aber private Funktionen sind nicht zugänglich, wenn Sie sich in Ihrer Test-Unit-Klasse befinden. Hier ist, was wir tun, um unsere privaten Methoden zu testen.
Warum haben wir private Methoden?
Private Funktionen sind in unserer Klasse hauptsächlich deshalb vorhanden, weil wir lesbaren Code in unseren öffentlichen Methoden erstellen wollen. Wir wollen nicht, dass der Benutzer dieser Klasse diese Methoden direkt aufruft, sondern über unsere öffentlichen Methoden. Außerdem wollen wir ihr Verhalten nicht ändern, wenn wir die Klasse erweitern (im Falle von protected), daher sind sie privat.
Wenn wir programmieren, verwenden wir testgetriebenes Design (TDD). Das bedeutet, dass wir manchmal über eine private Funktion stolpern, die wir testen wollen. Private Funktionen sind in phpUnit nicht testbar, da wir in der Testklasse nicht auf sie zugreifen können (sie sind privat).
Wir denken, dass es 3 Lösungen gibt:
1. Sie können Ihre Privaten durch Ihre öffentlichen Methoden testen
Vorteile
- Unkomplizierte Einheitstests (keine "Hacks" erforderlich)
Benachteiligungen
- Der Programmierer muss die öffentliche Methode verstehen, während er nur die private Methode testen möchte
- Sie testen nicht den kleinsten testbaren Teil der Anwendung
2. Wenn das Private so wichtig ist, dann ist es vielleicht ein Codesmell, eine neue separate Klasse dafür zu schaffen
Vorteile
- Sie können dies zu einer neuen Klasse refaktorisieren, denn wenn es so ist wichtig ist, brauchen andere Klassen sie vielleicht auch
- Die testbare Einheit ist jetzt eine öffentliche Methode, also testbar
Benachteiligungen
- Sie wollen keine Klasse erstellen, wenn sie nicht benötigt wird und nur von der Klasse, aus der die Methode kommt
- Potenzieller Leistungsverlust aufgrund von zusätzlichem Overhead
3. Ändern Sie den Zugriffsmodifikator in (final) protected
Vorteile
- Sie testen den kleinsten testbaren Teil der Anwendung. Wenn final protected verwendet, kann die Funktion nicht überschrieben werden (genau wie wie eine private)
- Kein Leistungsverlust
- Keine zusätzlichen Gemeinkosten
Benachteiligungen
- Sie ändern einen privaten Zugang in einen geschützten, was bedeutet, dass es sich um für seine Kinder zugänglich ist
- Sie brauchen noch eine Mock-Klasse in Ihrer Testklasse, um sie zu verwenden
Beispiel
class Detective {
public function investigate() {}
private function sleepWithSuspect($suspect) {}
}
Altered version:
class Detective {
public function investigate() {}
final protected function sleepWithSuspect($suspect) {}
}
In Test class:
class Mock_Detective extends Detective {
public test_sleepWithSuspect($suspect)
{
//this is now accessible, but still not overridable!
$this->sleepWithSuspect($suspect);
}
}
Unsere Testeinheit kann nun test_sleepWithSuspect aufrufen, um unsere ehemalige private Funktion zu testen.
Ich denke, es ist am besten, nur die öffentliche Schnittstelle eines Objekts zu testen. Aus Sicht der Außenwelt ist nur das Verhalten der öffentlichen Schnittstelle von Bedeutung, und darauf sollten Ihre Unit-Tests ausgerichtet sein.
Sobald Sie einige solide Unit-Tests für ein Objekt geschrieben haben, möchten Sie nicht zurückgehen und diese Tests ändern müssen, nur weil sich die Implementierung hinter der Schnittstelle geändert hat. In diesem Fall haben Sie die Konsistenz Ihrer Unit-Tests ruiniert.
Wenn die private Methode gut definiert ist (d.h. sie hat eine Funktion, die getestet werden kann und sich im Laufe der Zeit nicht ändern soll), dann ja. Ich teste alles, was prüfbar ist, wo es Sinn macht.
Eine Verschlüsselungsbibliothek könnte zum Beispiel die Tatsache verbergen, dass sie eine Blockverschlüsselung mit einer privaten Methode durchführt, die jeweils nur 8 Bytes verschlüsselt. Dafür würde ich einen Unit-Test schreiben - es soll sich nicht ändern, auch wenn es versteckt ist, und wenn es zu einem Bruch kommt (z. B. aufgrund zukünftiger Leistungsverbesserungen), dann möchte ich wissen, dass es die private Funktion ist, die kaputt gegangen ist, und nicht nur, dass eine der öffentlichen Funktionen kaputt gegangen ist.
Das beschleunigt die spätere Fehlersuche.
-Adam