Suchen und Finden
Cover
1
Titel
3
Impressum
4
Inhaltsverzeichnis
5
Vorwort zur zweiten Auflage
13
Vorwort zur ersten Auflage
15
Einleitung
17
Kapitel 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
Kapitel 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
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
Kapitel 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
Kapitel 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
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
Kapitel 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
Kapitel 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
Kapitel 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
Kapitel 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
Kapitel 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
Kapitel 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
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
Kapitel 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
Anhang 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
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
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
Alle Preise verstehen sich inklusive der gesetzlichen MwSt.