Ich bin ein ziemlicher Anfänger im Testen von Code und war assert
vorher eine Hure. Eine Sache, die mich bei Unit-Tests beunruhigt, ist, dass Sie häufig public
(oder zumindest internal
) Felder private
ausfüllen readonly
müssen, die sonst wären, um sie zu entfernen , stattdessen private
Methoden zu erstellen protected virtual
usw.
Ich habe kürzlich entdeckt, dass Sie dies vermeiden können, indem Sie Dinge wie die PrivateObject- Klasse verwenden, um über Reflektion auf alles in einem Objekt zuzugreifen . Dies macht Ihre Tests jedoch weniger wartbar (Fehler bei der Ausführung und nicht beim Kompilieren, Fehler durch einfaches Umbenennen, schwierigeres Debuggen ...). Wie ist Ihre Meinung dazu? Was sind die Best Practices bei Unit-Tests zur Zugriffsbeschränkung?
Bearbeiten: Nehmen wir zum Beispiel an, Sie haben eine Klasse mit einem Cache in einer Datei auf der Festplatte und möchten in Ihren Tests stattdessen in den Speicher schreiben.
quelle
Antworten:
Das solltest du niemals müssen
Insbesondere das Nicht-Lesen eines Feldes kann ein unveränderliches Objekt veränderbar machen, und das wäre eine Katastrophe.
Bei Ihren Tests sollten Ihre Objekte als Black Boxes ( Wikipedia ) betrachtet werden. Das bedeutet, dass sie sich nur mit der öffentlichen Schnittstelle der Objekte befassen sollten, nicht mit Details zu ihrer Implementierung.
Wenn ein Objekt mit seiner öffentlichen Schnittstelle nicht ausreichend getestet werden kann, müssen Sie Möglichkeiten finden, seine Schnittstelle mit formalen und nützlichen Erweiterungen zu versehen, die das Testen erleichtern. Beispielsweise würde ein Registrierungssystem mit nur einem Paar von Register / Deregister-Methoden möglicherweise von einer IsRegistered-Methode profitieren, selbst wenn dies für die vorliegende Anwendung nicht erforderlich ist. Trotzdem handelt es sich um eine formale und nützliche Erweiterung der Benutzeroberfläche, die im Übrigen für Tests geeignet ist.
Wichtig ist, dass Sie beim Ändern der Implementierung des Objekts nicht den Komponententest ändern müssen. Theoretisch sollten Sie in der Lage sein, den Komponententest einmal zu schreiben und dann mehrere Programmierer aufzufordern, mehrere völlig unterschiedliche Implementierungen des zu testenden Objekts zu codieren, um mit dem Komponententest zu arbeiten.
quelle
private
Methodenprotected virtual
zu entwickeln, die beim Verspotten von Tests helfen?In C # können Sie mit dem
InternalsVisibleToAttribute
Befehl zulassen, dass Ihre Testassemblyinternal
Klassen in der zu testenden Assembly sieht . Es hört sich so an, als wüsstest du das schon.In den meisten Fällen möchte ich nur die öffentliche API meiner Assembly testen. In einem Fall, in dem ich White-Box-Tests für eine Einheit durchführen möchte, verschiebe ich den Code in eine
internal
Klasse und mache sie zu einerpublic
Methode dieser Klasse. Dann kann ich einen Unit-Test für diese Klasse programmieren.Dies eignet sich gut für die Abhängigkeitsinjektion und das Strategiemuster. Sie können die Methode in eine Schnittstelle abstrahieren, die Schnittstelle in den Konstruktor Ihres übergeordneten Objekts einfügen und einfach testen, ob das übergeordnete Objekt die entsprechenden Delegierungen vornimmt. Dann können Sie testen, ob sich das untergeordnete Objekt ordnungsgemäß verhält. Das macht alles modularer.
quelle
Nach meiner Erfahrung ist es am besten, die Interna Ihrer Klasse nicht speziell für den Test freizulegen. Auch wenn dies den Test scheinbar einfacher zu schreiben macht. Der Test ist der erste Client Ihrer Klasse. Wenn es also schwierig ist, Ihre Klasse über die öffentliche Schnittstelle zu testen, ist es wahrscheinlich schwierig, Ihre Klasse auch an anderen Orten zu verwenden.
Wie einfach es ist, die Klasse über ihre öffentliche API zu testen, hängt davon ab, wie einfach die Klasse zu verwenden sein wird. Stellen Sie sich die Tests teilweise als eine Möglichkeit vor, die Verwendung Ihrer Klasse zu prototypisieren.
Überlegen Sie, warum Ihr Test etwas über die Klasse erfassen muss, das nicht über die öffentliche API verfügbar ist. Vielleicht tut Ihre Klasse zu viel und muss stattdessen in eine Gruppe kooperierender Klassen zerlegt werden? Anschließend können Sie einige der zusammenarbeitenden Klassen verspotten, um festzustellen, was die getestete Klasse tut.
Versuchen Sie, das Prinzip der Abhängigkeitsinversion anzuwenden und Schnittstellen zwischen Ihren Klassen einzuführen, die Sie in Ihren Tests nachahmen können. Sie können die Mitarbeiter zu Ihrem Test bereitstellen, indem Sie die Steuerung umkehren .
Ziehen Sie auch in Betracht, das Prinzip "Tell Don't Ask" anzuwenden , um die Struktur Ihrer Klassenschnittstelle in einer robusten, locker gekoppelten Art und Weise zu strukturieren, in der die richtigen Informationen offengelegt und der Rest verborgen wird.
quelle
Ich persönlich bevorzuge es, den Code, den ich teste, so rein wie möglich zu lassen. Wenn der Testcode Hacks benötigt (und in C ++ böse Zeiger usw.), mache ich das gerne.
quelle
Die Sichtbarkeit Ihres Codes hat nichts mit Ihren Unit-Tests zu tun!
Sie machen Ihre Methoden privat, nicht mit dem Ziel, sie vor dem Testen zu verbergen, und Sie machen sie nicht öffentlich, um sie zum Testen freizugeben, oder? Dies ist Ihre Implementierung, die hier wesentlich ist, nicht die Tests - diese Server als Beweis für Ihren Code, aber sie sind nicht Ihr Code .
Es gibt viele Möglichkeiten, den Zugriff auf verborgene (private oder interne) Methoden und Eigenschaften zu ermöglichen. Viele Test-Frameworks und IDEs (z. B. Visual Studio) unterstützen Sie dabei, indem sie alles generieren, was für den Zugriff benötigt wird. Sie müssen lediglich Ihre Testfälle erstellen. Warum also Sorgen machen? Halten Sie Ihren Code besser sauber und ordentlich.
quelle