Es gibt zwei Gründe, Tests zu schreiben:
- Erwartetes Verhalten behaupten
- Verhinderung einer Regression des Verhaltens
Die Einstellung (1) Behauptung des erwarteten Verhaltens:
Wenn Sie das erwartete Verhalten behaupten, möchten Sie sicherstellen, dass der Code so funktioniert, wie Sie es sich vorstellen. Dies ist effektiv eine automatisierte Methode zur routinemäßigen manuellen Überprüfung, die jeder Entwickler bei der Implementierung von Code ausführen würde:
- Hat das, was ich gerade geschrieben habe, funktioniert?
- Endet diese Schleife tatsächlich?
- Schleift es in der Reihenfolge, in der ich es denke?
- Würde dies für eine Null-Eingabe funktionieren?
Das sind Fragen, die wir alle in unseren Köpfen beantworten, und normalerweise würden wir versuchen, den Code auch in unseren Köpfen auszuführen, um sicherzustellen, dass er so aussieht, als würde er funktionieren. In diesen Fällen ist es oft nützlich, wenn der Computer sie endgültig beantwortet. Also schreiben wir einen Unit-Test, der dies bestätigt. Dies gibt uns Vertrauen in unseren Code, hilft uns, Fehler frühzeitig zu finden, und kann sogar dazu beitragen, den Code tatsächlich zu implementieren.
Es ist eine gute Idee, dies überall dort zu tun, wo Sie es für notwendig halten. Jeder Code, der etwas schwierig zu verstehen oder nicht trivial ist. Sogar trivialer Code könnte davon profitieren. Es geht nur um Ihr eigenes Vertrauen. Wie oft und wie weit es geht, hängt von Ihrer eigenen Zufriedenheit ab. Hören Sie auf, wenn Sie sicher mit Ja antworten können: Sind Sie sicher, dass dies funktioniert?
Bei dieser Art von Tests kümmern Sie sich nicht um Sichtbarkeit, Schnittstellen oder ähnliches, sondern nur um funktionierenden Code. Ja, Sie würden private und geschützte Methoden testen, wenn Sie der Meinung wären, dass sie getestet werden müssten, damit Sie die Frage mit Ja beantworten können.
Die Einstellung (2) Verhinderung einer Regression des Verhaltens:
Sobald Sie Arbeitscode haben, müssen Sie über einen Mechanismus verfügen, um diesen Code vor zukünftigen Schäden zu schützen. Wenn niemand Ihre Quelle und Ihre Konfiguration jemals wieder berühren würde, würden Sie dies nicht benötigen, aber in den meisten Fällen werden Sie oder andere die Quelle und die Konfigurationen Ihrer Software berühren. Es ist sehr wahrscheinlich, dass dieses interne Fummeln Ihren Arbeitscode beschädigt.
In den meisten Sprachen gibt es bereits Mechanismen, um sich vor diesen Schäden zu schützen. Die Sichtbarkeitsmerkmale sind ein Mechanismus. Eine private Methode ist isoliert und versteckt. Die Kapselung ist ein weiterer Mechanismus, bei dem Sie Dinge unterteilen, sodass das Ändern anderer Fächer keine Auswirkungen auf andere hat.
Der allgemeine Mechanismus hierfür heißt: Codierung an die Grenze. Indem Sie Grenzen zwischen Teilen des Codes erstellen, schützen Sie alles innerhalb einer Grenze vor Dingen außerhalb des Codes. Die Grenzen werden zum Interaktionspunkt und zum Vertrag, durch den die Dinge interagieren.
Dies bedeutet, dass Änderungen an einer Grenze, entweder durch Brechen der Schnittstelle oder durch Brechen des erwarteten Verhaltens, andere Grenzen beschädigen und möglicherweise durchbrechen würden, die darauf beruhten. Deshalb ist es eine gute Idee, einen Komponententest durchzuführen, der auf diese Grenzen abzielt und behauptet, dass sie sich in der Semantik und im Verhalten nicht ändern.
Dies ist ein typischer Komponententest, über den fast jeder spricht, wenn er TDD oder BDD erwähnt. Es geht darum, die Grenzen zu verschärfen und vor Veränderungen zu schützen. Sie möchten hierfür keine privaten Methoden testen, da eine private Methode keine Grenze darstellt. Geschützte Methoden sind eine eingeschränkte Grenze, und ich würde sie schützen. Sie sind nicht der Welt ausgesetzt, aber dennoch anderen Fächern oder "Einheiten" ausgesetzt.
Was soll man daraus machen?
Wie wir gesehen haben, gibt es einen guten Grund, öffentliche und geschützte Methoden zu testen, um zu behaupten, dass sich unsere Schnittstellen nicht ändern. Und es gibt auch gute Gründe, private Methoden zu testen, um zu behaupten, dass unsere Implementierung funktioniert. Sollen wir sie alle testen?
Ja und nein.
Erstens : Testen Sie alle Methoden, von denen Sie glauben, dass Sie einen endgültigen Beweis dafür benötigen, dass sie in den meisten Fällen funktionieren, um sicher zu sein, dass Ihr Code funktioniert, unabhängig von der Sichtbarkeit. Deaktivieren Sie dann diese Tests. Sie haben dort Arbeit geleistet.
Zuletzt : Schreiben Sie Tests für Ihre Grenzen. Führen Sie für jeden Punkt, der von anderen Einheiten Ihres Systems verwendet wird, einen Komponententest durch. Stellen Sie sicher, dass dieser Test den semantischen Vertrag, den Methodennamen, die Anzahl der Argumente usw. bestätigt. Stellen Sie außerdem sicher, dass der Test das verfügbare Verhalten der Einheit bestätigt. Ihr Test sollte zeigen, wie das Gerät verwendet wird und was das Gerät kann. Lassen Sie diese Tests aktiviert, damit sie bei jedem Code-Push ausgeführt werden.
HINWEIS: Der Grund, warum Sie den ersten Test deaktiviert haben, besteht darin, dass Refactoring-Arbeiten durchgeführt werden können. Ein aktiver Test ist eine Codekopplung. Es verhindert zukünftige Änderungen des Codes, den es testet. Sie möchten dies nur für Ihre Schnittstellen und Interaktionsverträge.