Mocks / Stubs für ein Objekt schreiben, bevor Sie die Klasse für dieses Objekt geschrieben haben?

8

Ich entwerfe eine Klasse mit zwei Abhängigkeiten. Eine der Abhängigkeitsklassen wurde geschrieben und getestet. Der andere wurde noch nicht geschrieben.

Es ist mir eingefallen, weil die verbleibende Abhängigkeit geschrieben wird, um die Klasse, die es benutzen wird, zu erleichtern, dass ich die letztere zuerst schreiben soll, und die Schnittstelle der ersteren so gestalten soll, wie ich es verstehe.

Das scheint mir eine großartige Möglichkeit zu sein, Code zu schreiben. Immerhin, solange die Hauptklasse in ihrem Konstruktor einen Schein erhält, kann ich sie schreiben und testen, ohne dass mir bewusst ist, dass ihre Abhängigkeit nicht existiert, dann kann ich die Abhängigkeit erstellen, sobald ich sicher bin, dass ich weiß, was ich brauche .

Also: Wie mache ich das? Erstelle eine Skelettklasse, die ich modifiziere, während ich weitergehe. Vielleicht etwas wie:

%Vor%

und dann spötteln Sie es mit PHPUnit, und Einrichten von Stubs, etc., um meine Klasse in der Entwicklung glücklich zu halten?

Ist das der richtige Weg?

Es scheint eine nette Art zu sein, Code zu entwickeln - und scheint mir mehr Sinn zu machen, als eine Abhängigkeit zu entwickeln, ohne wirklich genau zu wissen, wie sie benutzt wird.

    
Lewis Bassett 18.01.2012, 09:24
quelle

2 Antworten

8

Kurz gesagt:

Ja. Zumindest mache ich das gerade.

Längere Version:

Wenn die erwarteten Mitarbeiter Ihrer Klasse zu dem Zeitpunkt, zu dem Sie sie in Ihren Tests für die Klasse, die Sie erstellen, benötigen, nicht vorhanden sind, haben Sie einige Optionen :

  • Mock nicht existierende Klassen (was phpunit tun kann)
  • Erstellen Sie Klassenskeltionen und stellen Sie diese vor
  • Einfach Schnittstellen erstellen und Mocks für diese bekommen (was phpunit auch kann)
  • Vielleicht brauchen Sie keine der oben genannten Funktionen, abhängig vom Objekt

Wenn Sie gegen eine Schnittstelle programmieren , müssen Sie lediglich diese Schnittstelle erstellen und PHPUnit mitteilen, dass es eine Stub / Mock daraus erstellen soll

  • + Keine neue Klasse ohne Test
  • + Die Verwendung von Schnittstellen wird als netter / besser angesehen als nur als Hinweis auf Klassen

Wenn nicht existierende Klassen verspottet werden , bekommst du einige Nachteile, die ich nicht mag:

  • - Hohe Wartungskosten
  • - Die Methoden für diese Klassen zu verwalten ist langsam und langwierig
  • - Wenn Sie die Klasse erstellt haben, sollten Sie die Mocks erneut bearbeiten

also würde ich dagegen raten.

Der Mittelweg wäre, einfach das leere Klassenskelett mit seiner Methode zu erstellen und diese für das Mocking zu verwenden.

Ich mag diesen Weg in Fällen, in denen es keine Schnittstelle gibt, auf die man hinweisen kann, weil es schnell ist und einen stabilen Testcode erzeugt.

Barebone-Klassen mit öffentlichen Apis zu haben, ist für mich keine Verletzung von TDD.

Es gibt Klassen, die Sie nicht verspotten müssen.

Datenübertragungsobjekte und Wertobjekte können immer mit dem new in Ihrem Produktionscode erstellt werden, so dass Ihre Tests auch nur die echten Objekte .

Es hilft, Ihre Tests ein wenig sauberer zu halten, da Sie nicht viele Getter / Setter-Methoden und vieles mehr erwarten müssen.

    
edorian 18.01.2012, 11:22
quelle
7

Wenn Sie eine Entwicklungsmethodik verfolgen dann ist der übliche Ansatz wie folgt:

  1. Finden Sie heraus, was Ihre Klassen tun sollen und was ihre öffentlich zugänglichen APIs sein sollen.
  2. Implementieren Sie "leere" Klassen, die aus nichts anderem bestehen als den öffentlichen Methoden-Signaturen mit leeren Körpern (wie Sie es in dem von Ihnen angegebenen Codebeispiel getan haben).
  3. Erarbeiten Sie eine Implementierungsstrategie. Dies bedeutet, herauszuarbeiten, welche Klassen voneinander abhängig sind und sie in einer Reihenfolge zu implementieren, die bedeutet, dass abhängige Klassen erst dann implementiert werden, wenn die Klassen, von denen sie abhängt, fertig sind oder zumindest ausreichend funktional sind, um dagegen zu entwickeln. Das bedeutet, dass zuerst die Klassen ohne Abhängigkeiten ausgeführt werden, dann die Klassen, die nur von den abgeschlossenen Klassen abhängen, und so weiter.
  4. Schreiben Sie Ihre Tests. Es ist jetzt möglich, die Tests zu schreiben, weil Sie wissen, wie die Blackbox für Ihre Klassen aussieht, was sie als Eingabe nehmen müssen und was sie als Ausgabe zurückgeben sollen.
  5. Führen Sie die Tests aus. Sie sollten 0% Erfolg, aber auch 100% Code-Abdeckung erhalten. Dies ist jetzt deine Grundlinie.
  6. Beginnen Sie, Ihre Klassen entsprechend Ihrer Implementierungsstrategie zu implementieren. Führen Sie Ihre Komponententests während dieses Vorgangs von Zeit zu Zeit durch, z. B. wenn Sie eine Klasse abgeschlossen haben, um sicherzustellen, dass sie den Spezifikationen entspricht, die im Komponententest festgelegt sind. Idealerweise sollte jeder Test eine Erhöhung der Testdurchläufe bei einer 100% igen Codeabdeckung zeigen.

EDIT: Wie edorian sagte, sind PHP-Interfaces eine große Hilfe, da PHPUnit sowohl von Interfaces als auch von Klassen Mocks und Stubs generieren kann. Sie sind auch ein hervorragendes Werkzeug, um die Kopplung zu reduzieren und die Substituierbarkeit allgemein zu verbessern. Sie ermöglichen es Ihnen, jede Klasse zu ersetzen, die die erwartete Schnittstelle implementiert, und nicht nur Unterklassen der erwarteten Klasse.

    
GordonM 18.01.2012 10:57
quelle

Tags und Links