Ziehen Sie das Testen der Schnittstelle dem Testen der Implementierung vor.
Ich verstehe, dass private Methoden nicht testbar sind
Dies hängt von Ihrer Entwicklungsumgebung ab (siehe unten).
[Private Methoden] sollten sich keine Sorgen machen, da die öffentliche API genügend Informationen zur Überprüfung der Objektintegrität bereitstellt.
Richtig, TDD konzentriert sich auf das Testen der Schnittstelle.
Private Methoden sind ein Implementierungsdetail, das sich während eines Re-Faktor-Zyklus ändern kann. Es sollte möglich sein, Änderungen vorzunehmen, ohne die Benutzeroberfläche oder das Black-Box- Verhalten zu ändern . Tatsächlich ist dies Teil des Vorteils von TDD. Die Leichtigkeit, mit der Sie das Vertrauen erzeugen können, dass sich klasseninterne Änderungen ergeben, wirkt sich nicht auf Benutzer dieser Klasse aus.
Nun, es ist mir möglich, ein Objekt zu erstellen, das nur über private Methoden verfügt und mit anderen Objekten interagiert, indem ich deren Ereignisse abhöre. Dies wäre sehr gekapselt, aber völlig unprüfbar.
Auch wenn die Klasse über keine öffentlichen Methoden verfügt, sind die Event-Handler die öffentlichen Schnittstellen , und sie richten sich gegen diese öffentlichen Schnittstellen , die Sie testen können.
Da die Ereignisse die Schnittstelle sind, müssen Sie diese Ereignisse generieren, um das Objekt zu testen.
Prüfen Sie, ob Sie Scheinobjekte als Klebstoff für Ihr Testsystem verwenden können. Es sollte möglich sein, ein einfaches Mock-Objekt zu erstellen, das ein Ereignis generiert und die resultierende Statusänderung aufnimmt (möglich durch ein anderes Empfänger-Mock-Objekt).
Es wird auch als schlechte Praxis angesehen, Methoden zu Testzwecken hinzuzufügen.
Auf jeden Fall sollten Sie sehr vorsichtig sein , wenn Sie den internen Zustand offenlegen .
Bedeutet dies, dass TDD im Widerspruch zur Kapselung steht? Was ist das richtige Gleichgewicht?
Absolut nicht.
TDD sollte die Implementierung Ihrer Klassen nur ändern, um sie zu vereinfachen (indem Sie YAGNI von einem früheren Punkt aus anwenden ).
Best Practice mit TDD ist identisch mit Best Practice ohne TDD. Sie müssen nur herausfinden, warum dies früher der Fall ist, da Sie die Benutzeroberfläche während der Entwicklung verwenden.
Ich bin geneigt, die meisten oder alle meiner Methoden jetzt zu veröffentlichen ...
Dies würde eher das Baby mit dem Badewasser werfen.
Sie sollten nicht müssen alle Methoden öffentlich zu machen, so dass Sie in einem TDD - Weise entwickeln können. Sehen Sie sich meine Notizen unten an, um zu sehen, ob Ihre privaten Methoden wirklich nicht testbar sind.
Ein detaillierterer Blick auf das Testen privater Methoden
Wenn Sie unbedingt ein privates Verhalten einer Klasse testen müssen , haben Sie je nach Sprache / Umgebung drei Möglichkeiten:
- Ordnen Sie die Tests der Klasse zu, die Sie testen möchten.
- Fügen Sie die Tests in eine andere Klassen- / Quelldatei ein und legen Sie die privaten Methoden, die Sie testen möchten, als öffentliche Methoden offen.
- Verwenden Sie eine Testumgebung, mit der Sie Test- und Produktionscode getrennt halten und dennoch den Testcode-Zugriff auf private Methoden des Produktionscodes ermöglichen können.
Offensichtlich ist die 3. Option bei weitem die beste.
1) Ordnen Sie die Tests der Klasse zu, die Sie testen möchten (nicht ideal).
Das Speichern von Testfällen in derselben Klasse / Quelldatei wie der zu testende Produktionscode ist die einfachste Option. Ohne viele Pre-Prozessor-Direktiven oder -Anmerkungen wird Ihr Testcode jedoch unnötigerweise aufgebläht, und je nachdem, wie Sie Ihren Code strukturiert haben, können Sie den Benutzern dieses Codes versehentlich die interne Implementierung zugänglich machen.
2) Machen Sie die privaten Methoden, die Sie testen möchten, als öffentliche Methoden verfügbar (wirklich keine gute Idee).
Wie bereits erwähnt, handelt es sich hierbei um eine sehr schlechte Praxis, die die Kapselung zerstört und die interne Implementierung für Benutzer des Codes verfügbar macht.
3) Verwenden Sie eine bessere Testumgebung (beste Option, falls verfügbar)
In der Eclipse-Welt kann 3. durch die Verwendung von Fragmenten erreicht werden . In der C # Welt könnten wir verwenden Teilklassen . Andere Sprachen / Umgebungen verfügen häufig über ähnliche Funktionen. Sie müssen sie nur finden.
Die blinde Annahme, dass 1. oder 2. die einzigen Optionen sind, würde wahrscheinlich dazu führen, dass die Produktionssoftware mit Testcode oder bösen Schnittstellen vollgestopft ist, die ihre schmutzige Wäsche in der Öffentlichkeit waschen. * 8 ')
- Alles in allem ist es jedoch viel besser, nicht gegen eine private Implementierung zu testen.