the art of unit testingroy osherove the art of unit testing deutsche ausgabe Übersetzung aus dem...

15

Upload: others

Post on 12-Mar-2020

14 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: The Art of Unit TestingRoy Osherove The Art of Unit Testing Deutsche Ausgabe Übersetzung aus dem Englischen von Olaf Neuendorf
Page 2: The Art of Unit TestingRoy Osherove The Art of Unit Testing Deutsche Ausgabe Übersetzung aus dem Englischen von Olaf Neuendorf
Page 3: The Art of Unit TestingRoy Osherove The Art of Unit Testing Deutsche Ausgabe Übersetzung aus dem Englischen von Olaf Neuendorf

Roy Osherove

The Art of Unit Testing

Deutsche Ausgabe

Übersetzung aus dem Englischenvon Olaf Neuendorf

Page 4: The Art of Unit TestingRoy Osherove The Art of Unit Testing Deutsche Ausgabe Übersetzung aus dem Englischen von Olaf Neuendorf

Bibliografische Information der Deutschen NationalbibliothekDie Deutsche Nationalbibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über <http://dnb.d-nb.de> abrufbar.

ISBN 978-3-8266-8721-12. Auflage 2015

www.mitp.deE-Mail: [email protected]: +49 7953 / 7189 - 079Telefax: +49 7953 / 7189 - 082

Übersetzung der amerikanischen Originalausgabe: Roy Osherove: The Art of Unit Testing: With Examples in C#, Second Edition, ISBN 978-1617290893.Original English language edition published by Manning Publications, 178 South Hill Drive, Westampton, NJ 08060 USA. Copyright © 2013 by Manning Publications. German edition copyright © 2015 by mitp Verlags GmbH & Co. KG. All rights reserved.

© 2015 mitp Verlags GmbH & Co. KG

Dieses Werk, einschließlich aller seiner Teile, ist urheberrechtlich geschützt. Jede Verwertung außerhalb der engen Grenzen des Urheberrechtsgesetzes ist ohne Zustimmung des Verlages unzulässig und strafbar. Dies gilt insbesondere für Vervielfältigungen, Übersetzungen, Mikroverfilmungen und die Einspeicherung und Verarbeitung in elektronischen Systemen.

Die Wiedergabe von Gebrauchsnamen, Handelsnamen, Warenbezeichnungen usw. in diesem Werk berechtigt auch ohne besondere Kennzeichnung nicht zu der Annahme, dass solche Namen im Sinne der Warenzeichen- und Markenschutz-Gesetzgebung als frei zu betrachten wären und daher von jedermann benutzt werden dürften.

Lektorat: Sabine SchulzSprachkorrektorat: Petra Heubach-Erdmann, Maren FeilenCoverbild: © Sebastian Duda, Bildnummer 33776850Satz: III-satz, Husby, www.drei-satz.de

Page 5: The Art of Unit TestingRoy Osherove The Art of Unit Testing Deutsche Ausgabe Übersetzung aus dem Englischen von Olaf Neuendorf

Inhaltsverzeichnis

Vorwort zur zweiten Auflage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

Vorwort zur ersten Auflage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

Einleitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

Teil I Erste Schritte 23

1 Die Grundlagen des Unit Testings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

1.1 Unit Testing – Schritt für Schritt definiert . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

1.1.1 Die Bedeutung guter Unit Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

1.1.2 Wir alle haben schon Unit Tests geschrieben (irgendwie). . . . . . . . . 27

1.2 Eigenschaften eines »guten« Unit Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

1.3 Integrationstests. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

1.3.1 Nachteile von nicht automatisierten Integrationstests im Vergleich zu automatisierten Unit Tests . . . . . . . . . . . . . . . . . . . . . . . 31

1.4 Was Unit Tests »gut« macht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

1.5 Ein einfaches Unit-Test-Beispiel. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

1.6 Testgetriebene Entwicklung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

1.7 Die drei Schlüsselqualifikationen für erfolgreiches TDD . . . . . . . . . . . . . . . . . 41

1.8 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

2 Ein erster Unit Test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

2.1 Frameworks für das Unit Testing. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

2.1.1 Was Unit-Testing-Frameworks bieten . . . . . . . . . . . . . . . . . . . . . . . . . 44

2.1.2 Die xUnit-Frameworks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

2.2 Das LogAn-Projekt wird vorgestellt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

2.3 Die ersten Schritte mit NUnit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

2.3.1 Die Installation von NUnit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

2.3.2 Das Laden der Projektmappe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49

2.3.3 Die Verwendung der NUnit-Attribute in Ihrem Code . . . . . . . . . . . . 52

2.4 Sie schreiben Ihren ersten Test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

2.4.1 Die Klasse Assert . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

2.4.2 Sie führen Ihren ersten Test mit NUnit aus . . . . . . . . . . . . . . . . . . . . 54

2.4.3 Sie fügen positive Tests hinzu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

2.4.4 Von Rot nach Grün: das erfolgreiche Ausführen der Tests . . . . . . . . 56

2.4.5 Test-Code-Gestaltung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57

2.5 Refactoring zu parametrisierten Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57

5

Page 6: The Art of Unit TestingRoy Osherove The Art of Unit Testing Deutsche Ausgabe Übersetzung aus dem Englischen von Olaf Neuendorf

Inhaltsverzeichnis

6

2.6 Weitere NUnit-Attribute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

2.6.1 Aufbau und Abbau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

2.6.2 Auf erwartete Ausnahmen prüfen. . . . . . . . . . . . . . . . . . . . . . . . . . . . 64

2.6.3 Das Ignorieren von Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66

2.6.4 Die fließende Syntax von NUnit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67

2.6.5 Das Festlegen der Testkategorien . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67

2.7 Das Testen auf Zustandsänderungen des Systems statt auf Rückgabewerte. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68

2.8 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73

Teil II Zentrale Methoden 75

3 Die Verwendung von Stubs, um Abhängigkeiten aufzulösen . . . . . . . . . . . . . 77

3.1 Die Stubs werden vorgestellt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

3.2 Die Identifizierung einer Dateisystemabhängigkeit in LogAn . . . . . . . . . . . . 78

3.3 Die Entscheidung, wie LogAnalyzer am einfachsten getestet werden kann . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

3.4 Design-Refactoring zur Verbesserung der Testbarkeit. . . . . . . . . . . . . . . . . . . 82

3.4.1 Extrahiere ein Interface, um die dahinter liegende Implementierung durch eine andere ersetzen zu können . . . . . . . . 83

3.4.2 Dependency Injection: Injiziere eine Fake-Implementierung in die zu testende Unit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86

3.4.3 Injiziere einen Fake auf Konstruktor-Ebene (Construktor Injection) 86

3.4.4 Simuliere Ausnahmen über Fakes . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

3.4.5 Injiziere ein Fake als Property Get oder Set . . . . . . . . . . . . . . . . . . . . 92

3.4.6 Injiziere einen Fake unmittelbar vor einem Methodenaufruf . . . . . 93

3.5 Variationen der Refactoring-Technik. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101

3.5.1 Die Verwendung von Extract and Override, um Fake-Resultate zu erzeugen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101

3.6 Die Überwindung des Kapselungsproblems. . . . . . . . . . . . . . . . . . . . . . . . . . . 103

3.6.1 Die Verwendung von internal und [InternalsVisibleTo] . . . . . . . . . . 104

3.6.2 Die Verwendung des Attributs [Conditional] . . . . . . . . . . . . . . . . . . . 104

3.6.3 Die Verwendung von #if und #endif zur bedingten Kompilierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105

3.7 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106

4 Interaction Testing mit Mock-Objekten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107

4.1 Wertbasiertes Testen versus zustandsbasiertes Testen versus Testen versus Interaction Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107

4.2 Der Unterschied zwischen Mocks und Stubs . . . . . . . . . . . . . . . . . . . . . . . . . . 110

4.3 Ein einfaches manuelles Mock-Beispiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111

4.4 Die gemeinsame Verwendung von Mock und Stub . . . . . . . . . . . . . . . . . . . . . 114

4.5 Ein Mock pro Test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119

Page 7: The Art of Unit TestingRoy Osherove The Art of Unit Testing Deutsche Ausgabe Übersetzung aus dem Englischen von Olaf Neuendorf

Inhaltsverzeichnis

4.6 Fake-Ketten: Stubs, die Mocks oder andere Stubs erzeugen . . . . . . . . . . . . . . 119

4.7 Die Probleme mit handgeschriebenen Mocks und Stubs. . . . . . . . . . . . . . . . . 121

4.8 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122

5 Isolation-(Mock-Objekt-)Frameworks. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123

5.1 Warum überhaupt Isolation-Frameworks? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123

5.2 Das dynamische Erzeugen eines Fake-Objekts . . . . . . . . . . . . . . . . . . . . . . . . . 125

5.2.1 Die Einführung von NSubstitute in Ihre Tests . . . . . . . . . . . . . . . . . . 126

5.2.2 Das Ersetzen eines handgeschriebenen Fake-Objekts durch ein dynamisches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127

5.3 Die Simulation von Fake-Werten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130

5.3.1 Ein Mock, ein Stub und ein Ausflug in einen Test. . . . . . . . . . . . . . . 131

5.4 Das Testen auf ereignisbezogene Aktivitäten . . . . . . . . . . . . . . . . . . . . . . . . . . 137

5.4.1 Das Testen eines Event Listeners . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137

5.4.2 Der Test, ob ein Event getriggert wurde . . . . . . . . . . . . . . . . . . . . . . . 139

5.5 Die aktuellen Isolation-Frameworks für .NET . . . . . . . . . . . . . . . . . . . . . . . . . . 139

5.6 Die Vorteile und Fallstricke von Isolation-Frameworks . . . . . . . . . . . . . . . . . . 141

5.6.1 Fallstricke, die man bei der Verwendung von Isolation-Frameworks besser vermeidet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141

5.6.2 Unlesbarer Testcode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142

5.6.3 Die Verifizierung der falschen Dinge . . . . . . . . . . . . . . . . . . . . . . . . . 142

5.6.4 Die Verwendung von mehr als einem Mock pro Test . . . . . . . . . . . . 142

5.6.5 Die Überspezifizierung von Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142

5.7 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143

6 Wir tauchen tiefer ein in die Isolation-Frameworks . . . . . . . . . . . . . . . . . . . . . 145

6.1 Eingeschränkte und uneingeschränkte Frameworks . . . . . . . . . . . . . . . . . . . . 145

6.1.1 Eingeschränkte Frameworks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145

6.1.2 Uneingeschränkte Frameworks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146

6.1.3 Wie Profiler-basierte uneingeschränkte Frameworks arbeiten . . . . . 148

6.2 Werte guter Isolation-Frameworks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150

6.3 Eigenschaften, die Zukunftssicherheit und Benutzerfreundlichkeit unterstützen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150

6.3.1 Rekursive Fakes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151

6.3.2 Ignoriere Argumente als Voreinstellung. . . . . . . . . . . . . . . . . . . . . . . 152

6.3.3 Umfangreiches Fälschen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152

6.3.4 Nicht striktes Verhalten von Fakes . . . . . . . . . . . . . . . . . . . . . . . . . . . 152

6.3.5 Nicht strikte Mocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153

6.4 Isolation-Framework-Design-Antimuster . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154

6.4.1 Konzept-Konfusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154

6.4.2 Aufnahme und Wiedergabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155

6.4.3 Klebriges Verhalten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157

6.4.4 Komplexe Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157

6.5 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158

7

Page 8: The Art of Unit TestingRoy Osherove The Art of Unit Testing Deutsche Ausgabe Übersetzung aus dem Englischen von Olaf Neuendorf

Inhaltsverzeichnis

8

Teil III Der Testcode 159

7 Testhierarchie und Organisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161

7.1 Automatisierte Builds, die automatisierte Tests laufen lassen . . . . . . . . . . . . 161

7.1.1 Die Anatomie eines Build-Skripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163

7.1.2 Das Anstoßen von Builds und Integration . . . . . . . . . . . . . . . . . . . . . 164

7.2 Testentwürfe, die auf Geschwindigkeit und Typ basieren . . . . . . . . . . . . . . . . 165

7.2.1 Der menschliche Faktor beim Trennen von Unit und Integrationstests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166

7.2.2 Die sichere grüne Zone . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167

7.3 Stellen Sie sicher, dass die Tests zu Ihrer Quellcodekontrolle gehören . . . . . 168

7.4 Das Abbilden der Testklassen auf den zu testenden Code. . . . . . . . . . . . . . . . 168

7.4.1 Das Abbilden von Tests auf Projekte. . . . . . . . . . . . . . . . . . . . . . . . . . 168

7.4.2 Das Abbilden von Tests auf Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . 169

7.4.3 Das Abbilden von Tests auf bestimmte Methoden . . . . . . . . . . . . . . 170

7.5 Querschnittsbelang-Injektion. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170

7.6 Der Bau einer Test-API für Ihre Applikation . . . . . . . . . . . . . . . . . . . . . . . . . . 173

7.6.1 Die Verwendung von Testklassen-Vererbungsmustern . . . . . . . . . . 173

7.6.2 Der Entwurf von Test-Hilfsklassen und -Hilfsmethoden . . . . . . . . . 188

7.6.3 Machen Sie Ihre API den Entwicklern bekannt . . . . . . . . . . . . . . . . . 189

7.7 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190

8 Die Säulen guter Unit Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191

8.1 Das Schreiben vertrauenswürdiger Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191

8.1.1 Die Entscheidung, wann Tests entfernt oder geändert werden . . . . 192

8.1.2 Vermeiden Sie Logik in Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197

8.1.3 Testen Sie nur einen Belang . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199

8.1.4 Trennen Sie Unit Tests von Integrationstests . . . . . . . . . . . . . . . . . . 200

8.1.5 Stellen Sie Code-Reviews mit Codeabdeckung sicher . . . . . . . . . . . . 200

8.2 Das Schreiben wartbarer Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202

8.2.1 Das Testen privater oder geschützter Methoden . . . . . . . . . . . . . . . . 202

8.2.2 Das Entfernen von Duplizitäten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204

8.2.3 Die Verwendung von Setup-Methoden in einer wartbaren Art und Weise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208

8.2.4 Das Erzwingen der Test-Isolierung . . . . . . . . . . . . . . . . . . . . . . . . . . . 211

8.2.5 Vermeiden Sie mehrfache Asserts für unterschiedliche Belange . . . 217

8.2.6 Der Vergleich von Objekten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219

8.2.7 Vermeiden Sie eine Überspezifizierung der Tests. . . . . . . . . . . . . . . 222

8.3 Das Schreiben lesbarer Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224

8.3.1 Die Benennung der Unit Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225

8.3.2 Die Benennung der Variablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226

8.3.3 Benachrichtigen Sie sinnvoll . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227

8.3.4 Das Trennen der Asserts von den Aktionen . . . . . . . . . . . . . . . . . . . . 228

8.3.5 Aufbauen und Abreißen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229

8.4 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229

Page 9: The Art of Unit TestingRoy Osherove The Art of Unit Testing Deutsche Ausgabe Übersetzung aus dem Englischen von Olaf Neuendorf

Inhaltsverzeichnis

Teil IV Design und Durchführung 231

9 Die Integration von Unit Tests in die Organisation . . . . . . . . . . . . . . . . . . . . . 233

9.1 Schritte, um ein Agent des Wandels zu werden . . . . . . . . . . . . . . . . . . . . . . . . 233

9.1.1 Seien Sie auf die schweren Fragen vorbereitet . . . . . . . . . . . . . . . . . . 234

9.1.2 Überzeugen Sie Insider: Champions und Blockierer. . . . . . . . . . . . . 234

9.1.3 Identifizieren Sie mögliche Einstiegspunkte . . . . . . . . . . . . . . . . . . . 235

9.2 Wege zum Erfolg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237

9.2.1 Guerilla-Implementierung (Bottom-up) . . . . . . . . . . . . . . . . . . . . . . . 237

9.2.2 Überzeugen Sie das Management (Top-down) . . . . . . . . . . . . . . . . . . 237

9.2.3 Holen Sie einen externen Champion . . . . . . . . . . . . . . . . . . . . . . . . . 238

9.2.4 Machen Sie Fortschritte sichtbar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238

9.2.5 Streben Sie bestimmte Ziele an . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240

9.2.6 Machen Sie sich klar, dass es Hürden geben wird . . . . . . . . . . . . . . . 241

9.3 Wege zum Misserfolg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242

9.3.1 Mangelnde Triebkraft . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242

9.3.2 Mangelnde politische Unterstützung . . . . . . . . . . . . . . . . . . . . . . . . . 242

9.3.3 Schlechte Implementierungen und erste Eindrücke . . . . . . . . . . . . . 242

9.3.4 Mangelnde Teamunterstützung. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243

9.4 Einflussfaktoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243

9.5 Schwierige Fragen und Antworten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245

9.5.1 Wie viel zusätzliche Zeit wird der aktuelle Prozess für das Unit Testing benötigen? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245

9.5.2 Ist mein Job bei der QS in Gefahr wegen des Unit Testing? . . . . . . . 247

9.5.3 Woher wissen wir, dass Unit Tests wirklich funktionieren? . . . . . . . 247

9.5.4 Gibt es denn einen Beweis, dass Unit Testing hilft? . . . . . . . . . . . . . 248

9.5.5 Warum findet die QS immer noch Bugs? . . . . . . . . . . . . . . . . . . . . . . 248

9.5.6 Wir haben eine Menge Code ohne Tests: Wo fangen wir an? . . . . . . 249

9.5.7 Wir arbeiten mit mehreren Sprachen: Ist Unit Testing da praktikabel? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249

9.5.8 Was ist, wenn wir eine Kombination aus Soft- und Hardware entwickeln? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250

9.5.9 Wie können wir wissen, dass wir keine Bugs in unseren Tests haben? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250

9.5.10 Mein Debugger zeigt mir, dass mein Code funktioniert: Wozu brauche ich Tests? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250

9.5.11 Müssen wir Code im TDD-Stil schreiben? . . . . . . . . . . . . . . . . . . . . . 250

9.6 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251

10 Der Umgang mit Legacy-Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253

10.1 Wo soll man mit dem Einbauen der Tests beginnen? . . . . . . . . . . . . . . . . . . . 254

10.2 Bestimmen Sie eine Auswahlstrategie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256

10.2.1 Vor- und Nachteile der Strategie »Einfaches zuerst« . . . . . . . . . . . . . 256

10.2.2 Vor- und Nachteile der Strategie »Schwieriges zuerst« . . . . . . . . . . . 256

10.3 Schreiben Sie Integrationstests, bevor Sie mit dem Refactoring beginnen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257

9

Page 10: The Art of Unit TestingRoy Osherove The Art of Unit Testing Deutsche Ausgabe Übersetzung aus dem Englischen von Olaf Neuendorf

Inhaltsverzeichnis

10

10.4 Wichtige Tools für das Unit Testing von Legacy-Code . . . . . . . . . . . . . . . . . . . 258

10.4.1 Abhängigkeiten isolieren Sie leicht mit uneingeschränkten Isolation-Frameworks. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259

10.4.2 Verwenden Sie JMockit für Java-Legacy-Code . . . . . . . . . . . . . . . . . . 260

10.4.3 Verwenden Sie Vise beim Refactoring Ihres Java-Codes. . . . . . . . . . 262

10.4.4 Verwenden Sie Akzeptanztests, bevor Sie mit dem Refactoring beginnen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263

10.4.5 Lesen Sie das Buch von Michael Feathers zu Legacy-Code . . . . . . . . 264

10.4.6 Verwenden Sie NDepend, um Ihren Produktionscode zu untersuchen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265

10.4.7 Verwenden Sie ReSharper für die Navigation und das Refactoring des Produktionscodes . . . . . . . . . . . . . . . . . . . . . . . . . . . 265

10.4.8 Spüren Sie Code-Duplikate (und Bugs) mit Simian und TeamCity auf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265

10.5 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266

11 Design und Testbarkeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267

11.1 Warum sollte ich mir Gedanken um die Testbarkeit in meinem Design machen? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267

11.2 Designziele für die Testbarkeit. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268

11.2.1 Deklarieren Sie Methoden standardmäßig als virtuell . . . . . . . . . . . 269

11.2.2 Benutzen Sie ein Interface-basiertes Design . . . . . . . . . . . . . . . . . . . 270

11.2.3 Deklarieren Sie Klassen standardmäßig als nicht versiegelt . . . . . . . 270

11.2.4 Vermeiden Sie es, konkrete Klassen innerhalb von Methoden mit Logik zu instanziieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270

11.2.5 Vermeiden Sie direkte Aufrufe von statischen Methoden. . . . . . . . . 271

11.2.6 Vermeiden Sie Konstruktoren und statische Konstruktoren, die Logik enthalten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271

11.2.7 Trennen Sie die Singleton-Logik und Singleton-Halter . . . . . . . . . . 272

11.3 Vor- und Nachteile des Designs zum Zwecke der Testbarkeit . . . . . . . . . . . . 273

11.3.1 Arbeitsumfang . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274

11.3.2 Komplexität . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274

11.3.3 Das Preisgeben von sensiblem IP . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274

11.3.4 Manchmal geht’s nicht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275

11.4 Alternativen des Designs zum Zwecke der Testbarkeit . . . . . . . . . . . . . . . . . . 275

11.4.1 Design-Argumente und Sprachen mit dynamischen Typen . . . . . . . 275

11.5 Beispiel eines schwer zu testenden Designs . . . . . . . . . . . . . . . . . . . . . . . . . . . 277

11.6 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281

11.7 Zusätzliche Ressourcen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282

A Tools und Frameworks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285

A.1 Isolation-Frameworks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285

A.1.1 Moq . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286

A.1.2 Rhino Mocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286

A.1.3 Typemock Isolator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287

A.1.4 JustMock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287

Page 11: The Art of Unit TestingRoy Osherove The Art of Unit Testing Deutsche Ausgabe Übersetzung aus dem Englischen von Olaf Neuendorf

Inhaltsverzeichnis

A.1.5 Microsoft Fakes (Moles) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287

A.1.6 NSubstitute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288

A.1.7 FakeItEasy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288

A.1.8 Foq . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289

A.1.9 Isolator++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289

A.2 Test-Frameworks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289

A.2.1 Mighty Moose (auch bekannt als ContinuousTests) Continuous Runner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290

A.2.2 NCrunch Continuous Runner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290

A.2.3 Typemock Isolator Test Runner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290

A.2.4 CodeRush Test Runner. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290

A.2.5 ReSharper Test Runner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291

A.2.6 TestDriven.NET Runner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291

A.2.7 NUnit GUI Runner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292

A.2.8 MSTest Runner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292

A.2.9 Pex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292

A.3 Test-APIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293

A.3.1 MSTest-API – Microsofts Unit-Testing-Framework. . . . . . . . . . . . . . 293

A.3.2 MSTest für Metro Apps (Windows Store) . . . . . . . . . . . . . . . . . . . . . . 293

A.3.3 NUnit API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294

A.3.4 xUnit.net . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294

A.3.5 Fluent Assertions Helper API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294

A.3.6 Shouldly Helper API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294

A.3.7 SharpTestsEx Helper API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295

A.3.8 AutoFixture Helper API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295

A.4 IoC-Container. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295

A.4.1 Autofac . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296

A.4.2 Ninject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297

A.4.3 Castle Windsor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297

A.4.4 Microsoft Unity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297

A.4.5 StructureMap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297

A.4.6 Microsoft Managed Extensibility Framework . . . . . . . . . . . . . . . . . . . 297

A.5 Datenbanktests. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298

A.5.1 Verwenden Sie Integrationstests für Ihre Datenschicht . . . . . . . . . . 298

A.5.2 Verwenden Sie TransactionScope für ein Rollback der Daten . . . . . 298

A.6 Webtests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299

A.6.1 Ivonna . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 300

A.6.2 Team System Web Test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 300

A.6.3 Watir. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 300

A.6.4 Selenium WebDriver. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 300

A.6.5 Coypu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301

A.6.6 Capybara . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301

A.6.7 JavaScript-Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301

A.7 UI-Tests (Desktop) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301

11

Page 12: The Art of Unit TestingRoy Osherove The Art of Unit Testing Deutsche Ausgabe Übersetzung aus dem Englischen von Olaf Neuendorf

Inhaltsverzeichnis

12

A.8 Thread-bezogene Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302

A.8.1 Microsoft CHESS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302

A.8.2 Osherove.ThreadTester . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302

A.9 Akzeptanztests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302

A.9.1 FitNesse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303

A.9.2 SpecFlow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303

A.9.3 Cucumber . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303

A.9.4 TickSpec . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304

A.10 API-Frameworks im BDD-Stil . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304

Stichwortverzeichnis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305

Page 13: The Art of Unit TestingRoy Osherove The Art of Unit Testing Deutsche Ausgabe Übersetzung aus dem Englischen von Olaf Neuendorf

Vorwort zur zweiten Auflage

Es muss im Jahre 2009 gewesen sein. Ich hielt einen Vortrag auf der Norwegian Develo-pers Conference in Oslo. (Ah, Oslo im Juni!) Die Veranstaltung fand in einer großen Sport-arena statt. Die Konferenz-Organisatoren unterteilten die überdachte Tribüne in Abschnitteund bauten jeweils ein Podium vor ihnen auf. Dann hängten sie dicke schwarze Stoffbah-nen auf und erstellten auf diese Weise acht verschiedene »Konferenzräume«. Ich erinneremich, dass ich gerade dabei war, meinen Vortrag zu beenden – er handelte von TDD, oderSOLID, oder Astronomie, oder irgendwas – als plötzlich von der Nachbarbühne ein lautesund raues Singen und Gitarrenspiel ertönte.

Die Stoffbahnen hingen so, dass ich zwischen ihnen hindurch spähen und den Burschenauf der Nachbarbühne sehen konnte. Natürlich war es Roy Osherove.

Nun, diejenigen von Ihnen, die mich kennen, wissen, dass das Anstimmen eines Liedesmitten in einem technischen Vortrag über Software zu den Dingen gehört, die ich vielleichttue, wenn mir danach ist. Als ich mich wieder meinem Publikum zuwandte, dachte ich sobei mir, dass dieser Osherove wohl ein Gleichgesinnter sei und ich ihn besser kennenler-nen müsse.

Und ich lernte ihn besser kennen. In der Tat trug er erheblich zu meinem aktuellen BuchClean Coder bei und unterstützte mich drei Tage lang dabei, einen Kurs in TDD zu geben.Alle meine Erfahrungen mit Roy waren sehr positiv und ich hoffe, es wird noch viele wei-tere geben.

Ich schätze, dass Ihre Erfahrungen mit Roy beim Lesen dieses Buch auch sehr positiv seinwerden, denn dieses Buch ist etwas Besonderes.

Haben Sie jemals einen Roman von Michener gelesen? Ich jedenfalls nicht – aber mirwurde gesagt, sie alle würden »mit dem Atom« beginnen. Das Buch, das Sie in Händen hal-ten, ist kein James-Michener-Roman, aber es beginnt mit dem Atom – dem Atom des UnitTestings.

Lassen Sie sich nicht beirren, wenn Sie die ersten Seiten durchblättern. Dies ist keine bloßeEinführung ins Unit Testing. Es beginnt so, aber wenn Sie bereits Erfahrung haben, kön-nen Sie diese ersten Kapitel schnell überfliegen. Während das Buch dann aber voranschrei-tet, beginnen die Kapitel aufeinander aufzubauen und entwickeln eine erstaunliche Tiefe.Und als ich das letzte Kapitel las (ich wusste nicht, dass es das letzte war), dachte ich tat-sächlich, dass das nächste wohl vom Weltfrieden handeln müsse – denn im Ernst, womitsonst kann man weitermachen, nachdem man das Problem gelöst hat, Unit Testing instarrsinnige Organisationen mit alten, überkommenen Systemen einzuführen.

Dieses Buch ist ein Fachbuch – und zutiefst ein Fachbuch. Es gibt eine Menge Code. Unddas ist gut so. Doch Roy beschränkt sich nicht auf die technischen Aspekte. Gelegentlichholt er seine Gitarre hervor, beginnt zu singen und erzählt Geschichten aus seinem Berufs-leben. Oder er stellt philosophische Betrachtungen an über die Bedeutung von Design oder

13

Page 14: The Art of Unit TestingRoy Osherove The Art of Unit Testing Deutsche Ausgabe Übersetzung aus dem Englischen von Olaf Neuendorf

Vorwort zur zweiten Auflage

14

die Definition von Integration. Er scheint Gefallen daran zu finden, uns mit Geschichtenaus jenen dunklen, längst vergangenen Tagen des Jahres 2006 zu verwöhnen, als ihm somanches misslungen ist.

Ach, und machen Sie sich keine allzu großen Sorgen, dass der komplette Code in C#geschrieben ist. Im Ernst, wer könnte überhaupt den Unterschied zwischen C# und Javaerklären? Oder? Und abgesehen davon spielt es auch keine Rolle. Er mag zwar C# als Vehi-kel benutzen, um seine Intention klar zu machen, aber die Lektionen in diesem Buch geltengenauso für Java, C, Ruby, Python, PHP oder jede andere Programmiersprache (vielleichtmit Ausnahme von COBOL).

Egal, ob Sie ein Anfänger auf dem Gebiet des Unit Testings und der testgetriebenen Ent-wicklung sind oder ein alter Hase, dieses Buch hält für Sie alle etwas bereit. Also viel Ver-gnügen, während Roy für Sie sein Lied singt »The Art of Unit Testing«.

Und bitte Roy, stimme diese Gitarre!

Robert C. Martin (Uncle Bob) CLEANCODER.COM

Page 15: The Art of Unit TestingRoy Osherove The Art of Unit Testing Deutsche Ausgabe Übersetzung aus dem Englischen von Olaf Neuendorf

Vorwort zur ersten Auflage

Als mir Roy Osherove erzählte, er würde an einem Buch über das Unit Testing arbeiten,war ich sehr froh, dies zu hören. Das Test-Mem ist über die Jahre in der Industrie gewach-sen, aber es gibt einen relativen Mangel an Material zum Unit Testing. Wenn ich meinBücherregal betrachte, dann sehe ich Bücher zur testgetriebenen Entwicklung im Besonde-ren und Bücher zum Testen im Allgemeinen, aber bis jetzt gab es keine umfassende Refe-renz zum Unit Testing – kein Buch, das in das Thema einführt, den Leser an die Handnimmt und von den ersten Schritten bis zu den allgemein akzeptierten besten Vorgehens-weisen führt. Diese Tatsache ist verblüffend. Unit Testing ist keine neue Praxis. Wie konntees dazu kommen?

Es ist beinahe ein Klischee, wenn man sagt, dass wir in einer neuen Industrie arbeiten, aberes ist wahr. Mathematiker legten die Grundlagen unserer Arbeit vor weniger als 100 Jahren,aber erst seit 60 Jahren haben wir die Hardware, die schnell genug ist, um ihre Erkennt-nisse auch nutzen zu können. In unserer Industrie bestand von Anfang an eine Lücke zwi-schen Theorie und Praxis und erst jetzt entdecken wir, wie sich das auf unser Fachgebietausgewirkt hat.

In den frühen Jahren waren Rechenzeiten teuer. Wir ließen die Programme im Batchbe-trieb laufen. Programmierer hatten ein planmäßiges Zeitfenster, sie mussten ihre Pro-gramme in Kartenstapel stanzen und in den Maschinenraum tragen. War ein Programmnicht in Ordnung, hatten sie ihre Zeit vergeudet, also überprüften sie es zuvor mit Papierund Stift am Schreibtisch und gingen in Gedanken alle möglichen Szenarien, alle Grenz-fälle durch. Ich bezweifle, dass der Begriff des automatisierten Unit Testings zu dieser Zeitüberhaupt vorstellbar war. Warum sollte man die Maschine zum Testen nutzen, wo siedoch zur Lösung bestimmter Probleme gebaut worden war? Der Mangel hielt uns in derDunkelheit gefangen.

Später wurden die Maschinen schneller und wir berauschten uns am interaktiven Compu-ting. Wir konnten einfach Code eintippen und ihn aus Jux und Tollerei ändern. Die Idee,den Code am Schreibtisch zu überprüfen, schwand allmählich dahin und wir verlorenetwas von der Disziplin der frühen Jahre. Wir wussten, dass Programmieren schwierig war,aber das bedeutete nur, dass wir mehr Zeit am Computer verbringen mussten und Zeilenund Symbole änderten, bis wir die magische Zauberformel, die funktionierte, gefundenhatten.

Wir kamen vom Mangel zum Überfluss und verpassten den Mittelweg, aber nun erobernwir ihn zurück. Automatisiertes Unit Testing verbindet die Disziplin der Schreibtischprü-fung mit einer neu gefundenen Wertschätzung des Computers als einer Entwicklungsres-source. Wir können automatische Tests in der Sprache schreiben, in der wir entwickeln,um unsere Arbeit zu überprüfen – und das nicht nur einmal, sondern so oft wir in der Lagesind, die Tests laufen zu lassen. Ich glaube nicht, dass es irgendein anderes Verfahren inder Softwareentwicklung gibt, das derartig mächtig ist.

15