Sollten private / geschützte Methoden einem Unit-Test unterzogen werden?

82

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.

Raj Rao
quelle
1
Wenn Sie Ihre geschützten Methoden aus Ihren Tests nicht anwenden, indem Sie sie überschreiben oder aufrufen, warum sind sie dann geschützt und nicht privat? Indem Sie sie schützen, treffen Sie eine bewusste Entscheidung, den Erweiterungspunkt / die Funktionalität freizulegen. Wenn Sie TDD folgen, sollte diese Entscheidung für mich von den Tests abhängen, die Sie schreiben.
Forsvarir
2
Sie sollten den Teil über Ihre eigenen Gedanken in einer separaten Antwort einfügen. Lassen Sie mich wissen, wann Sie es tun, und ich werde mich dafür entscheiden.
Keith Pinson
Gleiches gilt nur für Privatpersonen: stackoverflow.com/questions/105007/…
Ciro Santilli 11 冠状 病 六四 事件 11
Sie haben Recht mit aktiven Komponententests, dh solchen, die so eingerichtet sind, dass sie kontinuierlich ausgeführt werden. Für diese möchten Sie nur öffentliche und geschützte Schnittstellen testen. Sie können und könnten davon profitieren, auch Tests für private Methoden zu schreiben. Diese Tests sollten nicht Teil Ihrer fortlaufenden Suite sein, aber als einmalige Überprüfung Ihrer Implementierung kann sie ein äußerst wertvolles Werkzeug sein.
Didier A.

Antworten:

107

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
22
Ich mag die Tatsache, dass Sie gesagt haben, dass Unit-Tests das Verhalten und nicht die Methoden testen! Das klärt die Dinge sehr.
Raj Rao
1
Ich stimme @rajah zu. Dies sollte die erste Aussage in jedem Tutorial sein. Ich habe mich gefragt, wie ich meine Methoden testen soll, jetzt weiß ich, dass ich das nicht muss. +1
frostymarvelous
3
Würden Sie sagen, dass dies immer noch in Fällen gilt, in denen Basisklassen geschütztes Verhalten implementieren, das von der Öffentlichkeit geerbt und verwendet werden soll? Dann sind die geschützten Methoden immer noch Teil der öffentlichen Schnittstelle, nicht wahr?
Nick Udell
1
Im Allgemeinen eignen sich Muster, die die Trennung von Bedenken begünstigen, besser für isolierte Komponententests, während Muster, die die Kapselung begünstigen, einfacher zu verwendende APIs sind.
6.
3
Dies klärt den Fall einer geschützten Sichtbarkeit nicht auf. Es scheint, dass eine geschützte Methode auch Teil einer Schnittstelle ist. Oft handelt es sich um einen Erweiterungspunkt, der absichtlich als solche geschützt wurde. Ich würde in diesen Fällen sagen, Sie sollten sie auch Unit-testen. Sie möchten nicht, dass jemand in Zukunft Dinge ändert und Klassen bricht, deren Verhalten von diesen Erweiterungspunkten abhängt.
Didier A.
45

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.

Charles Roth
quelle
3
Wenn eine Methode kritisch ist und eine komplizierte Logik aufweist, ist die Behauptung ihres Verhaltens sehr nützlich, um Fehler zu vermeiden. Das Schreiben eines Komponententests für eine solche Methode kann sogar hilfreich sein, wenn Sie die Methode auf eine Art explorative Weise implementieren. Selbst wenn es privat ist, würde ich sagen, dass es sich lohnt, Unit-Tests durchzuführen. ABER, und es gibt ein großes, aber Sie müssen sich daran erinnern, dass Tests Codekopplung sind. Wenn Sie einen Test für eine Methode schreiben, verhindern Sie das Refactoring.
Didier A.
6
Bevor Sie also Tests für private Methoden schreiben, sollten Sie Ihr Design immer überdenken. Sehen Sie, ob Dinge verallgemeinert und in reine Funktionsmethoden umgewandelt werden können. In diesem Fall können Sie sie in ein eigenes Konstrukt extrahieren. Dieses Konstrukt kann dann eine eigene öffentliche Schnittstelle haben und Unit-getestet werden. Denken Sie daran, dass kompliziertes Verhalten bei privaten Methoden oft ein Zeichen dafür sein kann, dass eine Klasse mehr als eine einzige Verantwortung hat. Überdenken Sie also bitte zuerst Ihr Design.
Didier A.
Ja, aber was ist "Arbeitscode"? Das Testen einer privaten Methode sagt nichts darüber aus, ob Ihr Objekt das richtige Verhalten aufweist oder nicht. Das ist der Hauptgrund, warum wir nur die öffentlichen Methoden testen. Nur öffentliche Methoden weisen ein Verhalten auf, das dem Benutzer eines Codes wichtig ist.
Sammi
1
"Arbeitscode" ist Code, der funktioniert. Wenn Ihre private (oder quasi-private) Methode einen Fehler aufweist, der von den Tests für Ihre öffentlichen Methoden nicht erfasst wird, stimmt etwas nicht. Vielleicht ist Ihr Design falsch, fair genug: Ich stimme zu, dass die beste Lösung Tests sind, die die öffentlichen Methoden aufrufen. Dies ist jedoch nicht immer möglich, insbesondere wenn Sie Legacy-Code hinzufügen oder reparieren. (Ich spreche aus Erfahrung bei einem Projekt mit 1 Million Codezeilen.) Getesteter Code ist immer besser als nicht getesteter Code. Auch wenn wir nette Regeln brechen, um nur öffentliche Methoden zu testen!
Charles Roth
Das Bit (oben) über "Tests sind Codekopplung ... Refactoring verhindern" ist zu 100% falsch. In der architektonischen Metapher sind Tests Gerüste, keine konkreten. Dinge ändern sich, Tests ändern sich, werden weggeworfen, neue Tests werden geschrieben. Ich bin damit einverstanden, dass gutes Design das Umschreiben von Tests minimiert. Aber auch bei den besten Designs kommt es zu Veränderungen.
Charles Roth
34

Sie schrieben:

In der TDD-Entwicklung erstellen Sie normalerweise zunächst 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.

Bitte lassen Sie mich dies in BDD- Sprache umformulieren :

Wenn Sie beschreiben, warum eine Klasse wertvoll ist und wie sie sich verhält, erstellen Sie in der Regel zunächst ein Beispiel für die Verwendung der Klasse, häufig über ihre Schnittstelle *. Wenn Sie das gewünschte Verhalten hinzufügen, erstellen Sie am Ende eine Klasse, die diesen Wert bereitstellt, und irgendwann funktioniert Ihr Beispiel.

* Kann eine tatsächliche Interfaceoder einfach die zugängliche API der Klasse sein, z. B.: Ruby hat keine Schnittstellen.

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!

Lunivore
quelle
1
Genialer Beitrag. Klärt viel.
frostymarvelous
17

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.

Forsvarir
quelle
13

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.

S.Lott
quelle
11

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 .

FGM
quelle
9

Es gibt zwei Gründe, Tests zu schreiben:

  1. Erwartetes Verhalten behaupten
  2. 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.

Didier A.
quelle
1
Es klingt so, als würden Sie private Methoden nicht explizit isoliert testen, sie werden von Ihren Tests nicht abgedeckt und Sie können nicht darauf vertrauen, dass sie funktionieren. Ich behaupte, das ist einfach falsch. Eine private Methode (oder ein beliebiger Codepfad darin), die nicht über eine öffentliche Methode getestet werden kann, ist toter Code und sollte entfernt werden. Der springende Punkt bei TDD ist, eine vollständige Abdeckung zu erhalten, indem nur öffentliche Methoden getestet werden, da Sie 0 LoC schreiben, die nicht vorhanden sind, um einen Test zu bestehen. Das Testen einer isolierten privaten Methode dient NUR dazu, das Refactoring zu erschweren, genau das Gegenteil von (einem) der Ziele von TDD.
Sara
@kai Ich sage ausdrücklich, dass Sie keine automatisierten Tests für private Methoden haben sollten, aber es ist manchmal wertvoll, isolierte Tests zu haben, um Ihnen bei der Implementierung zu helfen. Diese Tests sollten nicht Teil Ihrer Testsuite sein oder aus dem von Ihnen genannten Grund deaktiviert werden: Refactoring. Es liegt an Ihrem eigenen Vertrauensniveau, zu entscheiden, ob Sie einen programmatischen Test für die Implementierung einer privaten Methode bevorzugen oder nicht. Vielleicht haben Sie bis zum Ende meiner Antwort nicht gelesen?
Didier A.
Sie behaupten, dass "es auch gute Gründe gibt, private Methoden zu testen, um zu behaupten, dass unsere Implementierung funktioniert". Ich sehe keine Grundlage dafür in der Post. Es gibt nichts, was ein Test einer privaten Methode über die funktionierende Implementierung aussagen könnte, was ein Test einer öffentlichen Methode Ihnen nicht auch sagen könnte. Die private Methode funktioniert entweder oder nicht. Wenn es nicht funktioniert, schlägt ein Test einer oder mehrerer öffentlicher Methoden fehl oder es ist toter und / oder nicht getesteter Code.
Sara
@kai Sie erwähnen: "oder es ist tot und / oder ungetesteter Code". Ich spreche von ungetestetem Code. Eine private Methode könnte viele Fehler verbergen, bei denen die Randfälle nicht von den öffentlichen Methoden ausgeübt werden. Stellen Sie sich einen Fehler vor. Manchmal schaffen es die Invarianten der öffentlichen Methoden, dass dieser Fall niemals eintreten wird. In einem solchen Fall würde ich die private Methode immer noch als fehlerhaft betrachten und eine fehlerhafte Implementierung haben. Ihre Integration verhindert jedoch, dass der Fehler gefunden und abgefangen wird. In diesem Fall möchten Sie möglicherweise einige Tests durchführen, um Randfälle zu testen, damit Sie sicher sein können, dass Ihre Methode fehlerfrei ist.
Didier A.
@kai Aber verstehe, dass diese Tests, über die ich spreche, nicht deine Testsuite sind, dies ist keine TDD. Ich sage, dass einige private Methoden einfacher zu implementieren sind, wenn Sie schnell einige Tests gegen sie ausführen können. In Sprachen mit einer REPL brauchen Sie das nicht so sehr. Sie können versuchen, die Methode in Ihrem Kopf durchzugehen, aber ich empfehle stattdessen computergesteuerte Tests nur für die schwierig zu implementierenden privaten Methoden. Ich empfehle, die Tests anschließend zu löschen oder deaktiviert zu lassen oder an einem speziellen Ort, der nicht in Ihrem CI-Build ausgeführt wird.
Didier A.
4

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.

Satnhak
quelle
2

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!

Codematix
quelle
2

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.

Teoman Shipahi
quelle
1

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.

  • Wenn Sie Methoden hinzufügen (öffentlich / geschützt oder privat), weil diese einen fehlgeschlagenen Test bestehen, haben Sie das Ziel von TDD mehr oder weniger erreicht.
  • Wenn Sie Methoden hinzufügen (öffentlich / geschützt oder privat), weil Sie sich nur dazu entschließen, gegen TDD zu verstoßen, sollte Ihre Codeabdeckung diese abfangen und Sie sollten in der Lage sein, Ihren Prozess zu verbessern.

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

Quamrana
quelle
0

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.

Audrius Meskauskas
quelle