In der TDD-Entwicklung erstellen Sie normalerweise als Erstes Ihre Schnittstelle und beginnen dann mit dem Schreiben Ihrer Komponententests für diese Schnittstelle. Während Sie den TDD-Prozess durchlaufen, erstellen Sie am Ende eine Klasse, die die Schnittstelle implementiert, und irgendwann wird Ihr Komponententest bestanden.
Meine Frage bezieht sich nun auf die privaten und geschützten Methoden, die ich möglicherweise in meine Klasse schreiben muss, um die von der Schnittstelle bereitgestellten Methoden / Eigenschaften zu unterstützen:
Sollten die privaten Methoden in der Klasse ihre eigenen Unit-Tests haben?
Sollten die geschützten Methoden in der Klasse ihre eigenen Komponententests haben?
Meine Gedanken:
Insbesondere weil ich für Schnittstellen codiere, sollte ich mir keine Gedanken über geschützte / private Methoden machen, da es sich um Black Boxes handelt.
Da ich Schnittstellen verwende, schreibe ich Komponententests, um zu überprüfen, ob der definierte Vertrag von den verschiedenen Klassen, die die Schnittstelle implementieren, ordnungsgemäß implementiert wurde. Daher sollte ich mich auch hier nicht um die privaten / geschützten Methoden kümmern und sie sollten über Komponententests ausgeführt werden, die die aufrufen Von der Schnittstelle definierte Methoden / Eigenschaften.
Wenn meine Codeabdeckung nicht anzeigt, dass die geschützten / privaten Methoden getroffen werden, habe ich nicht die richtigen Komponententests oder ich habe Code, der nicht verwendet wird und entfernt werden sollte.
quelle
Antworten:
Nein, ich denke nicht daran, private oder geschützte Methoden zu testen. Die privaten und geschützten Methoden einer Klasse sind nicht Teil der öffentlichen Schnittstelle, sodass sie kein öffentliches Verhalten offenlegen. Im Allgemeinen werden diese Methoden durch Refactorings erstellt, die Sie anwenden, nachdem Ihr Test grün geworden ist.
Diese privaten Methoden werden also implizit durch die Tests getestet, die das Verhalten Ihrer öffentlichen Schnittstelle bestätigen.
Denken Sie philosophischer daran, dass Sie das Verhalten testen, nicht die Methoden. Wenn Sie also an die Dinge denken, die die zu testende Klasse tun kann, solange Sie testen und behaupten können, dass sich die Klasse wie erwartet verhält, ob es private (und geschützte) Methoden gibt, die von der Klasse intern zur Implementierung verwendet werden Dieses Verhalten ist irrelevant. Diese Methoden sind Implementierungsdetails des öffentlichen Verhaltens.
quelle
Ich bin mit den meisten Postern nicht einverstanden.
Die wichtigste Regel lautet: ARBEITSCODE TRUMPT THEORETISCHE REGELN über öffentlich / geschützt / privat.
Ihr Code sollte gründlich getestet werden. Wenn Sie dorthin gelangen können, indem Sie Tests für die öffentlichen Methoden schreiben, die die geschützten / privaten Methoden ausreichend ausüben, ist das großartig.
Wenn Sie dies nicht können, können Sie entweder den Refactor so gestalten, dass Sie dies können, oder die geschützten / privaten Regeln biegen.
Es gibt eine großartige Geschichte über einen Psychologen, der Kindern einen Test gegeben hat. Er gab jedem Kind zwei Holzbretter mit einem Seil an jedem Ende und bat sie, so schnell wie möglich einen Raum zu durchqueren, ohne mit den Füßen den Boden zu berühren. Alle Kinder benutzten die Bretter wie kleine Skier, einen Fuß auf jedem Brett, hielten sie an den Seilen und rutschten über den Boden. Dann gab er ihnen die gleiche Aufgabe, benutzte aber nur EIN Brett. Sie drehten sich über den Boden, einen Fuß an jedem Ende des einzelnen Bretts - und sie waren SCHNELLER!
Nur weil Java (oder eine andere Sprache) eine Funktion hat (privat / geschützt / öffentlich), heißt das nicht unbedingt, dass Sie besseren Code schreiben, weil Sie ihn verwenden!
Jetzt wird es immer Möglichkeiten geben, diesen Konflikt zu optimieren / zu minimieren. In den meisten Sprachen können Sie eine Methode schützen (anstatt öffentlich) und die Testklasse in dasselbe Paket (oder was auch immer) einfügen. Die Methode steht dann zum Testen zur Verfügung. Es gibt Anmerkungen, die helfen können, wie auf anderen Postern beschrieben. Sie können Reflexion verwenden, um zu den privaten Methoden zu gelangen (yuck).
Der Kontext ist auch wichtig. Wenn Sie eine API zur Verwendung durch externe Personen schreiben, ist öffentlich / privat wichtiger. Wenn es ein internes Projekt ist - wen interessiert das wirklich?
Aber denken Sie am Ende des Tages darüber nach, wie viele Fehler durch fehlende Tests verursacht wurden. Vergleichen Sie dann, wie viele Fehler durch "übermäßig sichtbare" Methoden verursacht wurden. Diese Antwort sollte Ihre Entscheidung bestimmen.
quelle
Sie schrieben:
Bitte lassen Sie mich dies in BDD- Sprache umformulieren :
Aus diesem Grund testen Sie keine privaten Methoden, da ein Test ein Beispiel für die Verwendung der Klasse ist und Sie sie nicht verwenden können. Wenn Sie möchten, können Sie die Verantwortlichkeiten in den privaten Methoden an eine kollaborierende Klasse delegieren und dann diesen Helfer verspotten / stubben.
Mit geschützten Methoden sagen Sie, dass eine Klasse, die Ihre Klasse erweitert, ein bestimmtes Verhalten haben und einen gewissen Wert liefern sollte. Sie können dann Erweiterungen Ihrer Klasse verwenden, um dieses Verhalten zu demonstrieren. Wenn Sie beispielsweise eine geordnete Sammlungsklasse schreiben, möchten Sie möglicherweise demonstrieren, dass zwei Erweiterungen mit demselben Inhalt Gleichheit aufweisen.
Hoffe das hilft!
quelle
Wenn Sie die Komponententests für Ihre Klasse schreiben, sollte es Ihnen nicht unbedingt wichtig sein, ob die Funktionalität der Klasse direkt in der Methode auf der öffentlichen Schnittstelle implementiert ist oder ob sie in einer Reihe privater Methoden implementiert ist. Ja, Sie sollten Ihre privaten Methoden testen, aber Sie sollten sie nicht direkt aus Ihrem Testcode aufrufen müssen, um dies zu tun (das direkte Testen der privaten Methoden koppelt Ihre Implementierung eng mit Ihren Tests und macht das Refactoring unnötig schwierig).
Geschützte Methoden bilden einen anderen Vertrag zwischen Ihrer Klasse und ihren zukünftigen Kindern. Sie sollten ihn daher in einem ähnlichen Umfang wie Ihre öffentliche Schnittstelle testen, um sicherzustellen, dass der Vertrag genau definiert und ausgeübt wird.
quelle
Nein! Nur Testschnittstellen.
Einer der großen Vorteile von TDD besteht darin, sicherzustellen, dass die Schnittstelle funktioniert, unabhängig davon, wie Sie die privaten Methoden implementiert haben.
quelle
Wenn ich das vervollständige, was andere oben gesagt haben, würde ich sagen, dass geschützte Methoden Teil einer Schnittstelle sind: Es ist einfach diejenige, die der Vererbung statt der Komposition ausgesetzt ist, woran jeder denkt, wenn er Schnittstellen in Betracht zieht.
Wenn eine Methode als geschützt statt als privat markiert wird, wird erwartet, dass sie von Code von Drittanbietern verwendet wird. Daher muss eine Art Vertrag definiert und getestet werden, wie dies bei normalen Schnittstellen der Fall ist, die durch öffentliche Methoden definiert sind, die sowohl für die Vererbung als auch für die Komposition offen sind .
quelle
Es gibt zwei Gründe, Tests zu schreiben:
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:
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.
quelle
Nein, Sie sollten keine privaten Methoden testen (wie würden Sie es trotzdem tun, ohne etwas Schreckliches wie Reflexion zu verwenden). Mit geschützten Methoden ist es in C # etwas weniger offensichtlich, dass Sie Dinge intern schützen können, und ich denke, es ist in Ordnung, dies zu tun, um abgeleitete Klassen zu testen, die ihre gesamte Funktionalität durch Vorlagenmustermethoden implementieren.
Wenn Sie jedoch der Meinung sind, dass Ihre öffentlichen Methoden zu viel bewirken, ist es im Allgemeinen an der Zeit, Ihre Klassen in atomarere Klassen umzugestalten und diese Klassen dann zu testen.
quelle
Ich stimme auch der Antwort von @ kwbeam zu, keine privaten Methoden zu testen. Ein wichtiger Punkt, den ich hervorheben möchte: Geschützte Methoden sind Teil der exportierten API einer Klasse und MÜSSEN daher getestet werden.
Geschützte Methoden sind möglicherweise nicht öffentlich zugänglich, aber Sie bieten Unterklassen definitiv die Möglichkeit, sie zu verwenden / zu überschreiben. Etwas außerhalb der Klasse kann auf sie zugreifen, und daher müssen Sie sicherstellen, dass sich diese geschützten Mitglieder wie erwartet verhalten. Testen Sie also keine privaten Methoden, sondern öffentliche und geschützte Methoden.
Wenn Sie glauben, eine private Methode zu haben, die kritische Logik enthält, würde ich versuchen, sie in ein separates Objekt zu extrahieren, zu isolieren und eine Möglichkeit zum Testen des Verhaltens bereitzustellen.
Ich hoffe es hilft!
quelle
Wenn Sie eine hohe Codeabdeckung anstreben (ich schlage vor, Sie sollten dies tun), sollten Sie alle Methoden testen, unabhängig davon, ob sie privat oder geschützt sind.
Geschützt ist eine Art anderer Diskussionspunkt, aber zusammenfassend sollte er überhaupt nicht vorhanden sein. Entweder wird die Kapselung für bereitgestellten Code unterbrochen, oder Sie werden gezwungen, von dieser Klasse zu erben, nur um sie einem Komponententest zu unterziehen, selbst wenn Sie manchmal nicht erben müssen.
Nur eine Methode für den Client auszublenden (privat zu machen), gibt ihm nicht das Privileg, nicht geprüft zu werden. Daher können sie wie oben erwähnt mit öffentlichen Methoden getestet werden.
quelle
Ich stimme allen anderen zu: Die Antwort auf Ihre Frage lautet "Nein".
In der Tat sind Sie mit Ihrem Ansatz und Ihren Gedanken, insbesondere in Bezug auf die Codeabdeckung, völlig korrekt.
Ich möchte auch hinzufügen, dass die Frage (und die Antwort "Nein") auch für öffentliche Methoden gilt, die Sie in Klassen einführen könnten.
Außerdem implementiere ich für C ++ (und ich sollte nur für C ++ denken) Schnittstellen nur mit privaten Methoden, um anzugeben, dass die Klasse nur über die von ihr implementierte Schnittstelle verwendet werden sollte. Es hält mich davon ab, aus meinen Tests fälschlicherweise neue Methoden aufzurufen, die meiner Implementierung hinzugefügt wurden
quelle
Ein gutes Design bedeutet, die Anwendung in mehrere testbare Einheiten aufzuteilen. Danach sind einige Einheiten der öffentlichen API ausgesetzt, andere möglicherweise nicht. Auch die Interaktionspunkte zwischen exponierten Einheiten und diesen "internen" Einheiten sind nicht Teil der öffentlichen API.
Ich denke, sobald wir die identifizierbare Einheit haben, würden wir von den Komponententests profitieren, unabhängig davon, ob sie über eine öffentliche API verfügbar gemacht werden oder nicht.
quelle