Was sind die Londoner und Chicagoer Schulen von TDD?

88

Ich habe über den London-Stil gegen den Chicago-Stil (manchmal Detroit-Stil genannt) von Test Driven Development (TDD) gehört.

Workshop der Utah Extreme Programming Users Group:

TDD im Interaktionsstil wird nach dem Londoner Club Extreme Tuesday, in dem es populär wurde, auch Mockist-Style oder London-Style genannt . Es wird normalerweise mit Detroit-Art oder klassischem TDD kontrastiert, das staatsbasierter ist.

Jason Gormans Werkstatt :

Der Workshop befasst sich sowohl mit der Chicagoer Schule für TDD (State-based Behaviour Testing and Triangulation) als auch mit der Londoner Schule , die sich mehr auf Interaktionstests, Spott und durchgängige TDD konzentriert, mit besonderem Schwerpunkt auf Responsibility-Driven Design und Erklären Sie, fragen Sie nicht Ansatz zu OO, der kürzlich von Steve Freemans und Nat Pryces ausgezeichnetem Buch " Wachsende objektorientierte Software unter Anleitung von Tests" wieder populär gemacht wurde .

Die Post Classic TDD oder "London School"? von Jason Gorman war hilfreich, aber seine Beispiele verwirrten mich, weil er bei beiden Ansätzen zwei verschiedene Beispiele anstelle eines Beispiels verwendet. Was sind die Unterschiede? Wann benutzt du jeden Stil?

Arturo Herrero
quelle

Antworten:

76

Angenommen, Sie haben eine Klasse namens "ledger", eine Methode namens "berechne", die einen "Rechner" verwendet, um verschiedene Arten von Berechnungen durchzuführen, abhängig von den Argumenten, die an "berechne" übergeben wurden, zum Beispiel "multipliziere (x, y)" oder "subtrahiere (subtrahiere)". x, y) ".

Angenommen, Sie möchten testen, was passiert, wenn Sie ledger.calculate ("5 * 7") aufrufen.

Bei der London / Interaction-Schule müssten Sie angeben, ob Calculator.multiply (5,7) aufgerufen wurde. Hierfür sind die verschiedenen Mock-Frameworks hilfreich, und dies kann sehr hilfreich sein, wenn Sie beispielsweise nicht Eigentümer des "Calculator" -Objekts sind (vorausgesetzt, es handelt sich um eine externe Komponente oder einen externen Dienst, den Sie nicht direkt testen können, dies jedoch tun) wissen, dass Sie auf eine bestimmte Weise anrufen müssen).

An der Chicago / State School müssen Sie angeben, ob das Ergebnis 35 ist. Die jUnit / nUnit-Frameworks sind im Allgemeinen darauf ausgerichtet.

Beides sind gültige und wichtige Tests.

Matthew Flynn
quelle
Sehr schönes Beispiel.
Sevenseacat
1
Ich füge noch ein paar Gründe für die Verwendung hinzu: Wenn es darauf ankommt, dass sich aufgrund der durchgeführten Aktion etwas geändert hat oder nicht (z. B. wird der Wert für ledger.bucket zu 35, wenn ledger.calculate ("5 * 7 ") heißt), Sie wollen Aussagen des Staates (Chicagoer Schule) verwenden. Dies ist am hilfreichsten, wenn Sie vor dem Aufrufen der Methode die vollständige Kontrolle über den Systemstatus haben und tatsächlich steuern, was die Methode tut.
Matthew Flynn
1
Wenn es wichtig ist zu wissen, dass eine zweite Methode aufgerufen wird (z. B. Calculator.multiply (5, 7)), möchten Sie Aktivitätszusagen wie über ein Scheinobjekt verwenden. Dies ist am hilfreichsten, wenn die aufgerufene Methode den gewünschten Nebeneffekt hat (z. B. Speichern von Daten, Inkrementieren eines Zählers, Senden einer Nachricht usw.) oder wenn Sie nicht wirklich steuern, was die Methode tut, sodass der Rückgabewert möglicherweise inkonsistent ist . Wenn Sie den Status des Systems nicht einfach steuern können, können Sie möglicherweise auch bestimmen, welche Aktivitäten stattfinden.
Matthew Flynn
Der London-Ansatz ist nützlich, wenn die Calculator-Klasse aus irgendeinem Grund möglicherweise zu lange ausgeführt wird oder ein Netzwerk umfasst und daher in dev / qa-Setups möglicherweise unübersichtlich ist. Das heißt, durch das Verspotten können Ihre Tests schnell und zuverlässig durchgeführt werden, wenn dies ansonsten nicht möglich wäre.
Kevin
1
Der Londoner Ansatz spricht auch dafür, klarere Rückmeldungssignale zu liefern, da bei einer CalculatorRegression multiplyzwei Tests fehlschlagen: der Hauptbuch-Test und der Taschenrechner-Test, aber nur ein Test schlägt fehl, wenn Sie den Taschenrechner verspotten. Dies könnte es einfacher machen, den Ursprung des Fehlers zu lokalisieren, insbesondere wenn das System komplex ist.
Matthias
30

Der Artikel Mocks Arn't Stubs von Martin Fowler ist eine gute Einführung in das Thema.

Abhängig von dem von Ihnen gewählten Entwurfsstil (und den Entwurfsprinzipien, auf denen Sie Ihre Programme aufbauen) gibt es mindestens zwei Möglichkeiten, ein Objekt zu sehen:

  1. Als eine Einheit, die Berechnungen basierend auf Eingaben ausführt. Als Ergebnis dieser Berechnung kann das Objekt einen Wert zurückgeben oder seinen Zustand ändern.
  2. Als aktives Element, das über die Nachrichtenübermittlung mit anderen Elementen im System kommuniziert.

Im ersten Fall interessiert Sie, was bei der Verarbeitung herauskommt oder in welchem ​​Zustand das Objekt nach der Verarbeitung übrig bleibt. Hier geben Methoden wie assertEquals()das Bild ein. In diesem Fall spielt es keine Rolle, welche anderen Objekte an der Verarbeitung beteiligt waren, welche Methoden aufgerufen wurden usw. Diese Art der Überprüfung wird als zustandsbasierte Überprüfung bezeichnet und ist der "klassische" Stil.

Im zweiten Fall voidinteressiert es Sie mehr, wie die Objekte miteinander kommunizieren und ob sie unter den vom Test auferlegten Umständen die richtigen Nachrichten weitergeben , da die meisten Objekte nicht einmal ein Ergebnis zurückgeben (z. B. Methoden in Java). Diese Wechselwirkungen werden in der Regel mit Hilfe von Mock-Frameworks überprüft. Diese Art der Überprüfung wird als verhaltensbasierte oder interaktionsbasierte Überprüfung bezeichnet. Eine der Auswirkungen ist die Technik der verhaltensgesteuerten Entwicklung, mit der Sie eine Klasse entwickeln, die davon ausgeht, dass ihre Mitarbeiter bereits vorhanden sind (auch wenn sie möglicherweise noch nicht vorhanden sind), sodass Sie anhand ihrer Schnittstellen programmieren können.

Beachten Sie, dass dies keine Wahlmöglichkeit ist. Sie können einen Designstil haben, der beide Ansätze kombiniert, um das Beste aus jedem herauszuholen.

Otavio Macedo
quelle