2010-05-04 20 views
6

Meine Mitarbeiter und ich hatten letzte Nacht ein wenig Meinungsverschiedenheiten über Komponententests in unserer PHP/MySQL-Anwendung. Die Hälfte von uns argumentierte, dass wenn Sie eine Funktion innerhalb einer Klasse testen, Sie alles außerhalb dieser Klasse und ihrer Eltern verspotten sollten. Die andere Hälfte von uns argumentierte, dass Sie nichts verspotten sollten, was eine direkte Abhängigkeit der Klasse ist.Unit Testing-- grundlegendes Ziel?

Das spezielle Beispiel war unser Protokollierungsmechanismus, der durch eine statische Protokollierungsklasse erfolgte und wir hatten eine Reihe von Logging :: log() - Aufrufen an verschiedenen Stellen in unserer Anwendung. Die erste Hälfte von uns sagte, dass der Logging-Mechanismus gefälscht (verspottet) werden sollte, weil er in den Logging-Unit-Tests getestet würde. Die zweite Hälfte von uns argumentierte, dass wir die ursprüngliche Protokollierungsklasse in unseren Komponententest einbeziehen sollten. Wenn wir Änderungen an unserer Protokollierungsschnittstelle vornehmen, können wir sehen, ob Probleme in anderen Teilen der Anwendung aufgrund eines Fehlers auftreten um die Anrufschnittstelle zu aktualisieren.

Also die grundlegende Frage ist, ob Unit Tests dazu dienen, die Funktionalität einer einzelnen Einheit in einer geschlossenen Umgebung zu testen oder die Konsequenzen von Änderungen an einer einzelnen Einheit in einer größeren Umgebung aufzuzeigen? Wenn es einer von diesen ist, wie bewerkstelligen Sie den anderen?

+0

+1 Dies ist eine gute Frage, weil es etwas enthüllt, von dem ich denke, dass viele Leute mit Komponententests verwirrt sind. – Fenton

Antwort

11

Sie und Ihre Kollegen sind auf den Unterschied zwischen Komponententests und Integrationstests gestoßen. Verspottung wurde für die erstgenannte gemacht; Für letztere würden keine spöttischen Abhängigkeiten entstehen.

Natürlich ist es auch subjektiv, wo Sie die Linie für die Granularität zeichnen - aber auf der feinsten Detailebene für Komponententests sollten Sie sich nicht um irgendetwas außerhalb des spezifischen Themas jedes Tests sorgen.

+2

Manchmal, wenn Sie sich entscheiden, dass etwas getestet wurde und Teil der * Plattform * ist, ist es in Ordnung, es selbst innerhalb von Komponententests zu verwenden. Zum Beispiel würden Sie nicht Standardbibliothek fälschen oder vielleicht nicht ein Framework, dem Sie vertrauen, um richtig zu funktionieren. Wenn Sie sich ein solches Vertrauen leisten können, müssen Sie möglicherweise einige Codezeilen einsparen. –

+0

Ja, sehr wahr - das typische Mocking ist für Komponenten reserviert, die als Teil Ihres Projekts entwickelt wurden, einfach nicht das, was gerade getestet wird. – Amber

+0

+1 - Stimmen Sie zu, dass Komponententests isoliert durchgeführt werden und 100% Ihres Codes abdecken sollten. Integrationstests werden einheitlich durchgeführt und die Abdeckung muss nicht so hoch sein - Sie testen die Interaktion und nicht die Funktion. http://www.enhance-php.com/Content/About-Unit-Testing/ – Fenton

1

Die Worte geben einige Hinweise auf die Antwort:

Einheit bedeutet 1: Sie eine Sache zu testen versuchen. Sie können Abhängigkeiten wie das Protokollierungs-Framework nachahmen, wenn dies nicht der primäre Schwerpunkt Ihrer Tests ist. Wie die getestete Einheit mit ihren Abhängigkeiten interagiert, ist oft Teil des Testfalls, und das Mocking macht das viel einfacher.

Integration bedeutet mehr als eine Sache zusammen: Sie versuchen, mehr als eine Sache zusammen einen Test als Ganzes zu kombinieren. Mocking spielt eine geringere Rolle, aber es kann immer noch nützlich sein, um Abhängige zu emulieren, die im Testszenario schwierig einzurichten wären.

Ich würde sagen, dass das Argument, das Logging-System in Unit-Tests nicht zu verspotten, um zu sehen, ob Änderungen etwas brechen, ziemlich schwach ist. Wenn im Logging-System etwas kaputt ist, sollte dies durch einen fehlgeschlagenen Komponententest für das Logging-System abgefangen werden.

Einheitentests einfach, klar und fokussiert zu halten ist eine gute Faustregel. Yuu braucht diesen Grundstein der Einfachheit, wenn es den Umfang der Tests erweitert. Integrationstests können schnell komplex werden, besonders wenn sie als Ersatz für fehlende Komponententests verwendet werden - es ist wie "Testen aus der Ferne" und je weiter man sich von einer Komponente entfernt, desto schwieriger ist es, Fehler zu testen und zu diagnostizieren. Das Testen einer entfernten Abhängigkeit durch einen Komponententest ist wie eine Person, die versucht, die TV-Fernbedienung von der anderen Seite des Raums aus mit einer Angelrute zu bedienen.

5

Komponententest ist wie Testen einer einzelnen Komponente in einem elektronischen Gerät.

Wenn Sie einen einzelnen Transistor in einem Gitarrenverstärker testen möchten, stecken Sie keine Gitarre ein, drehen Sie die Lautstärke hoch und prüfen Sie die ausgegebenen Töne. Das wäre dumm. Um einen Transistor zu prüfen, haken Sie Ausrüstung bis zu den Leitungen von , dass Transistor und messen Sie nur seine Eingänge und Ausgänge.

Irgendwann testen Sie das ganze Ding (Gitarre macht Geräusche, etc.), aber das ist etwas anderes, als einen einzelnen Transistor zu testen.

0

@David, ich sehe, dass Unit-Testing für Sie die Arbeit macht, die es tun soll.

Sie denken über das Design Ihrer Software nach.

Von der Art, wie Sie Ihre Frage zu geschlossener Umgebung und offener Umgebung stellen, würde ich glauben, dass Sie kurz vor der Frage stehen müssen, ob State-based versus Behaviour Unit-Testing für Ihren Code erforderlich ist.

Es gibt keine feste Schnellregel für die Verwendung eines realen Objekts oder eines Mocks für Komponententests. NUR GUIDING PRINCIPLES! Das Problem der Komponententests mit einem echten Logging Objekt besteht darin, dass die Tests für dieses Objekt nicht nur in den Komponententests für den Logger, sondern auch in den Komponententests für die Objekte, die den Logger verwenden, durchgeführt werden.

Wenn also 20 Objekte den Logger verwenden und wenn Sie die Logger-Schnittstelle ändern, werden mindestens 21 Tests fehlgeschlagen sein. Dies kann beim Refactoring ziemlich schmerzhaft sein. Auf der anderen Seite, wenn Sie die Logger-Klasse nicht in den 20 Objekteinheitstests verwenden und die Loggerschnittstelle ändern, haben Sie nur einen fehlgeschlagenen Test und 20 andere Komponententests, die grün werden, obwohl sie in der Produktion ausfallen.

Die einzige Erkenntnis, die ich Ihnen wirklich geben kann, ist, dass Sie nicht die richtigen Abstraktionen an Ort und Stelle haben. Vielleicht möchten Sie nachschlagen SOLID. Diese sollten Leitprinzipien sein.

Denken Sie daran, wenn Fragen auftauchen, wie Sie es fragen, ist es der Code, der Ihnen Feedback gibt. Beachten Sie das Feedback. Es wird dir später viel Schmerz ersparen.