The Art of Unit Testing - Deutsche Ausgabe

von: Roy Osherove, Michael Feathers, Robert C. Martin

mitp Verlags GmbH & Co. KG, 2015

ISBN: 9783826687228 , 288 Seiten

2. Auflage

Format: PDF, ePUB, OL

Kopierschutz: frei

Windows PC,Mac OSX für alle DRM-fähigen eReader Apple iPad, Android Tablet PC's Apple iPod touch, iPhone und Android Smartphones Online-Lesen für: Windows PC,Mac OSX,Linux

Preis: 33,99 EUR

Mehr zum Inhalt

The Art of Unit Testing - Deutsche Ausgabe


 

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