The Art of Unit Testing - Roy Osherove - E-Book

The Art of Unit Testing E-Book

Roy Osherove

0,0

Beschreibung

Lesbare, wartbare und zuverlässige Tests entwickeln Fakes, Stubs, Mock-Objekte und Isolation-(Mocking-)Frameworks Einfache Dependency-Injection-Techniken und das Refactoring von Legacy Code Sie wissen, dass Sie Unit Tests durchführen sollten – warum machen Sie es noch nicht? Wenn Sie Anfänger auf dem Gebiet der Unit Tests sind, wenn Sie Unit Tests mühsam finden oder wenn Sie, gemessen am Aufwand, einfach kein ausreichendes Ergebnis erzielen, dann sollten Sie dieses Buch lesen. Roy Osherove führt Sie Schritt für Schritt vom Schreiben Ihres ersten, einfachen Unit Tests bis hin zum Erstellen kompletter Test-Sets, die wartbar, lesbar und zuverlässig sind. Sie werden schnell zu fortgeschrittenen Themen wie Mocks und Stubs hingeführt, während Sie die Verwendung von Isolation-(Mocking-)Frameworks wie Moq, FakeItEasy und Typemock Isolator erlernen. Sie erfahren eine Menge zu Testmustern und zur Testorganisation, führen Refactoring durch und lernen, wie man »untestbaren« Code testet. Nebenbei zeigt Ihnen der Autor das Integration Testing sowie Techniken zum Testen mit Datenbanken. Die Beispiele im Buch verwenden C#, sind aber auch für jeden nützlich, der eine Sprache mit statischen Typen wie Java oder C++ benutzt. Aus dem Inhalt: Grundlagen des Unit Testings Frameworks für das Unit Testing Einsatz von NUnit Stubs zum Auflösen von Abhängigkeiten Interaction Testing mit Mock-Objekten Isolation-(Mocking-)Frameworks Testhierarchie und Organisation Die Säulen guter Unit Tests Integration von Unit Tests in das Unternehmen Umgang mit Legacy Code Design und Testbarkeit Tools und Frameworks Stimmen zum Buch: »Dieses Buch ist etwas Besonderes. Die Kapitel bauen aufeinander auf und entwickeln eine erstaunliche Tiefe.« – Aus dem Vorwort von Robert C. Martin, cleancoder.com »Die beste Art, Unit Testing zu lernen. Bereits ein Klassiker auf dem Gebiet.« – Raphael Faria, LG Electronics »Bringt Ihnen sowohl die Philosophie des effektiven Unit Testings bei als auch die praktischen Grundlagen.« – Pradeep Chellappan, Microsoft »Wenn meine Teammitglieder fragen, wie sie Unit Tests richtig schreiben sollen, antworte ich einfach: mit diesem Buch!« – Alessandro Campeis, Vimar SpA

Sie lesen das E-Book in den Legimi-Apps auf:

Android
iOS
von Legimi
zertifizierten E-Readern
Kindle™-E-Readern
(für ausgewählte Pakete)

Seitenzahl: 465

Veröffentlichungsjahr: 2015

Das E-Book (TTS) können Sie hören im Abo „Legimi Premium” in Legimi-Apps auf:

Android
iOS
Bewertungen
0,0
0
0
0
0
0
Mehr Informationen
Mehr Informationen
Legimi prüft nicht, ob Rezensionen von Nutzern stammen, die den betreffenden Titel tatsächlich gekauft oder gelesen/gehört haben. Wir entfernen aber gefälschte Rezensionen.



Inhaltsverzeichnis
Impressum
Vorwort zur zweiten Auflage
Vorwort zur ersten Auflage
Einleitung
Teil I: Erste Schritte
Kapitel 1: Die Grundlagen des Unit Testings
1.1 Unit Testing – Schritt für Schritt definiert
1.1.1 Die Bedeutung guter Unit Tests​
1.1.2 Wir alle haben schon Unit Tests geschrieben (irgendwie)
1.2 Eigenschaften eines »guten« Unit Test​​s
1.3 Integrationstests​
1.3.1 Nachteile von nicht automatisierten Integrationstests​ im Vergleich zu automatisierten Unit Tests
1.4 Was Unit Tests »gut« macht
1.5 Ein einfaches Unit-Test-Beispiel
1.6 Testgetriebene Entwicklung​
1.7 Die drei Schlüsselqualifikationen für erfolgreiches TDD
1.8 Zusammenfassung
Kapitel 2: Ein erster Unit Test
2.1 Frameworks für das Unit Testing
2.1.1 Was Unit-Testing-Frameworks bieten
2.1.2 Die xUnit-Frameworks
2.2 Das LogAn-Projekt​ wird vorgestellt
2.3 Die ersten Schritte mit NUnit
2.3.1 Die Installation von NUni​t
2.3.2 Das Laden der Projektmappe
2.3.3 Die Verwendung der NUnit​-Attribute in Ihrem Code
2.4 Sie schreiben Ihren ersten Test
2.4.1 Die Klasse Assert​
2.4.2 Sie führen Ihren ersten Test mit NUnit aus
2.4.3 Sie fügen positive Tests hinzu
2.4.4 Von Rot nach Grün: das erfolgreiche Ausführen der Tests
2.4.5 Test-Code-Gestaltung
2.5 Refactoring zu parametrisierten Tests
2.6 Weitere NUnit​-Attribute
2.6.1 Aufbau​ und Abbau​
2.6.2 Auf erwartete Ausnahmen​ prüfen
2.6.3 Das Ignorieren​ von Tests
2.6.4 Die fließende Syntax von NUnit
2.6.5 Das Festlegen der Testkategorie​n
2.7 Das Testen auf Zustandsänderungen des Systems statt auf Rückgabewerte
2.8 Zusammenfassung
Teil II: Zentrale Methoden
Kapitel 3: Die Verwendung von Stubs, um Abhängigkeiten aufzulösen
3.1 Die Stubs werden vorgestellt
3.2 Die Identifizierung einer Dateisystemabhängigkeit in LogAn
3.3 Die Entscheidung, wie LogAnalyzer am einfachsten getestet werden kann
3.4 Design-Refactoring zur Verbesserung der Testbarkeit​
3.4.1 Extrahiere ein Interface​, um die dahinter liegende Implementierung durch eine andere ersetzen zu können
3.4.2 Dependency Injection: Injiziere eine Fake-Implementierung​ in die zu testende Unit
3.4.3 Injiziere einen Fake auf Konstruktor-Ebene (Construktor Injectio​n)
3.4.4 Simuliere Ausnahmen über Fakes
3.4.5 Injiziere ein Fake als Property Get oder Set
3.4.6 Injiziere einen Fake unmittelbar vor einem Methodenaufruf
3.5 Variationen der Refactoring​-Technik
3.5.1 Die Verwendung von Extract and Override​, um Fake-Resultate zu erzeugen
3.6 Die Überwindung des Kapselungsproblems​
3.6.1 Die Verwendung von internal​ und [InternalsVisibleTo​]
3.6.2 Die Verwendung des Attributs [Conditiona​l]
3.6.3 Die Verwendung von #if und #endif zur bedingten Kompilierung​​
3.7 Zusammenfassung
Kapitel 4: Interaction Testing mit Mock-Objekten
4.1 Wertbasiertes Testen versus zustandsbasiertes Testen versus Testen versus Interaction Testing
4.2 Der Unterschied zwischen Mocks​ und Stubs​
4.3 Ein einfaches manuelles Mock-Beispiel
4.4 Die gemeinsame Verwendung von Mock​ und Stub​
4.5 Ein Mock​ pro Test
4.6 Fake-Ketten​​: Stubs, die Mocks oder andere Stubs erzeugen
4.7 Die Probleme mit handgeschriebenen Mocks​ und Stubs​
4.8 Zusammenfassung
Kapitel 5: Isolation-(Mock-Objekt-)Frameworks
5.1 Warum überhaupt Isolation-Frameworks?
5.2 Das dynamische Erzeugen eines Fake-Objekts
5.2.1 Die Einführung von NSubstitute in Ihre Tests
5.2.2 Das Ersetzen eines handgeschriebenen Fake-Objekts durch ein dynamisches
5.3 Die Simulation von Fake-Werten
5.3.1 Ein Mock, ein Stub und ein Ausflug in einen Test
5.4 Das Testen auf ereignisbezogene Aktivitäten
5.4.1 Das Testen eines Event Listeners
5.4.2 Der Test, ob ein Event getriggert wurde
5.5 Die aktuellen Isolation-Frameworks für .NET
5.6 Die Vorteile und Fallstricke von Isolation-Frameworks
5.6.1 Fallstricke, die man bei der Verwendung von Isolation-Frameworks besser vermeidet
5.6.2 Unlesbarer Testcode
5.6.3 Die Verifizierung der falschen Dinge
5.6.4 Die Verwendung von mehr als einem Mock pro Test
5.6.5 Die Überspezifizierung​ von Tests
5.7 Zusammenfassung
Kapitel 6: Wir tauchen tiefer ein in die Isolation-Frameworks
6.1 Eingeschränkte und uneingeschränkte Frameworks
6.1.1 Eingeschränkte Frameworks
6.1.2 Uneingeschränkte Frameworks
6.1.3 Wie Profiler-basierte uneingeschränkte Frameworks arbeiten
6.2 Werte guter Isolation-Frameworks
6.3 Eigenschaften, die Zukunftssicherheit und Benutzerfreundlichkeit unterstützen
6.3.1 Rekursive Fakes​​
6.3.2 Ignoriere Argumente als Voreinstellung
6.3.3 Umfangreiches Fälschen
6.3.4 Nicht striktes Verhalten von Fakes
6.3.5 Nicht strikte Mocks
6.4 Isolation-Framework-Design-Antimuster
6.4.1 Konzept-Konfusion
6.4.2 Aufnahme und Wiedergabe
6.4.3 Klebriges Verhalten​​
6.4.4 Komplexe Syntax​​
6.5 Zusammenfassung
Teil III: Der Testcode
Kapitel 7: Testhierarchie und Organisation
7.1 Automatisierte Builds, die automatisierte Tests​ laufen lassen
7.1.1 Die Anatomie eines Build-Skripts
7.1.2 Das Anstoßen von Builds und Integration
7.2 Testentwürfe, die auf Geschwindigkeit und Typ basieren
7.2.1 Der menschliche Faktor beim Trennen von Unit und Integrationstests
7.2.2 Die sichere grüne Zone
7.3 Stellen Sie sicher, dass die Tests zu Ihrer Quellcodekontrolle​ gehören
7.4 Das Abbilden der Testklassen auf den zu testenden Code
7.4.1 Das Abbilden von Tests auf Projekte
7.4.2 Das Abbilden von Tests auf Klassen
7.4.3 Das Abbilden von Tests auf bestimmte Methoden
7.5 Querschnittsbelang-Injektion
7.6 Der Bau einer Test-API für Ihre Applikation
7.6.1 Die Verwendung von Testklassen-Vererbungsmustern
7.6.2 Der Entwurf von Test-Hilfsklassen und -Hilfsmethoden
7.6.3 Machen Sie Ihre API den Entwicklern bekannt
7.7 Zusammenfassung
Kapitel 8: Die Säulen guter Unit Tests
8.1 Das Schreiben vertrauenswürdiger Tests
8.1.1 Die Entscheidung, wann Tests entfernt oder geändert werden
8.1.2 Vermeiden Sie Logik in Tests
8.1.3 Testen Sie nur einen Belang
8.1.4 Trennen Sie Unit Tests von Integrationstests
8.1.5 Stellen Sie Code-Reviews mit Codeabdeckung sicher
8.2 Das Schreiben wartbarer Tests
8.2.1 Das Testen privater oder geschützter Methoden
8.2.2 Das Entfernen von Duplizitäten
8.2.3 Die Verwendung von Setup-Methoden in einer wartbaren Art und Weise
8.2.4 Das Erzwingen der Test-Isolierung
8.2.5 Vermeiden Sie mehrfache Asserts für unterschiedliche Belange
8.2.6 Der Vergleich von Objekten
8.2.7 Vermeiden Sie eine Überspezifizierung​ der Tests
8.3 Das Schreiben lesbarer Tests
8.3.1 Die Benennung der Unit Tests
8.3.2 Die Benennung der Variablen
8.3.3 Benachrichtigen​ Sie sinnvoll
8.3.4 Das Trennen der Asserts von den Aktionen
8.3.5 Aufbauen und Abreißen
8.4 Zusammenfassung
Teil IV: Design und Durchführung
Kapitel 9: Die Integration von Unit Tests in die Organisation
9.1 Schritte, um ein Agent des Wandels zu werden
9.1.1 Seien Sie auf die schweren Fragen vorbereitet
9.1.2 Überzeugen Sie Insider​: Champions​ und Blockierer
9.1.3 Identifizieren Sie mögliche Einstiegspunkte
9.2 Wege zum Erfolg
9.2.1 Guerilla-Implementierung​ (Bottom-up​)
9.2.2 Überzeugen Sie das Management (Top-down)
9.2.3 Holen Sie einen externen Champion
9.2.4 Machen Sie Fortschritte sichtbar
9.2.5 Streben Sie bestimmte Ziele an
9.2.6 Machen Sie sich klar, dass es Hürden geben wird
9.3 Wege zum Misserfolg
9.3.1 Mangelnde Triebkraft
9.3.2 Mangelnde politische Unterstützung
9.3.3 Schlechte Implementierungen und erste Eindrücke
9.3.4 Mangelnde Teamunterstützung
9.4 Einflussfaktoren
9.5 Schwierige Fragen und Antworten
9.5.1 Wie viel zusätzliche Zeit wird der aktuelle Prozess für das Unit Testing benötigen?
9.5.2 Ist mein Job bei der QS in Gefahr wegen des Unit Testing?
9.5.3 Woher wissen wir, dass Unit Tests wirklich funktionieren?
9.5.4 Gibt es denn einen Beweis, dass Unit Testing hilft?
9.5.5 Warum findet die QS​ immer noch Bugs?
9.5.6 Wir haben eine Menge Code ohne Tests: Wo fangen wir an?
9.5.7 Wir arbeiten mit mehreren Sprachen: Ist Unit Testing da praktikabel?
9.5.8 Was ist, wenn wir eine Kombination aus Soft- und Hardware entwickeln?
9.5.9 Wie können wir wissen, dass wir keine Bugs in unseren Tests haben?
9.5.10 Mein Debugger zeigt mir, dass mein Code funktioniert: Wozu brauche ich Tests?
9.5.11 Müssen wir Code im TDD-Stil schreiben?
9.6 Zusammenfassung
Kapitel 10: Der Umgang mit Legacy-Code
10.1 Wo soll man mit dem Einbauen der Tests beginnen?
10.2 Bestimmen Sie eine Auswahlstrategie
10.2.1 Vor- und Nachteile der Strategie »Einfaches zuerst​«
10.2.2 Vor- und Nachteile der Strategie »Schwieriges zuerst​«
10.3 Schreiben Sie Integrationstests, bevor Sie mit dem Refactoring beginnen
10.4 Wichtige Tools für das Unit Testing von Legacy-Code
10.4.1 Abhängigkeiten isolieren Sie leicht mit uneingeschränkten Isolation-Frameworks
10.4.2 Verwenden Sie JMockit für Java-Legacy-Code
10.4.3 Verwenden Sie Vise​ beim Refactoring Ihres Java-Codes
10.4.4 Verwenden Sie Akzeptanztests, bevor Sie mit dem Refactoring beginnen
10.4.5 Lesen Sie das Buch von Michael Feathers zu Legacy-Code
10.4.6 Verwenden Sie NDepend, um Ihren Produktionscode zu untersuchen
10.4.7 Verwenden Sie ReSharper für die Navigation und das Refactoring des Produktionscodes
10.4.8 Spüren Sie Code-Duplikate (und Bugs) mit Simian und TeamCity auf
10.5 Zusammenfassung
Kapitel 11: Design und Testbarkeit
11.1 Warum sollte ich mir Gedanken um die Testbarkeit in meinem Design​ machen?
11.2 Designziele für die Testbarkeit
11.2.1 Deklarieren Sie Methoden standardmäßig als virtuell
11.2.2 Benutzen Sie ein Interface-basiertes Design
11.2.3 Deklarieren Sie Klassen standardmäßig als nicht versiegelt
11.2.4 Vermeiden Sie es, konkrete Klassen innerhalb von Methoden mit Logik zu instanziieren
11.2.5 Vermeiden Sie direkte Aufrufe von statischen Methoden
11.2.6 Vermeiden Sie Konstruktoren und statische Konstruktoren, die Logik enthalten
11.2.7 Trennen Sie die Singleton-Logik und Singleton-Halter
11.3 Vor- und Nachteile des Designs zum Zwecke der Testbarkeit
11.3.1 Arbeitsumfang
11.3.2 Komplexität
11.3.3 Das Preisgeben von sensiblem IP
11.3.4 Manchmal geht’s nicht
11.4 Alternativen des Designs zum Zwecke der Testbarkeit
11.4.1 Design-Argumente und Sprachen mit dynamischen Typen
11.5 Beispiel eines schwer zu testenden Designs
11.6 Zusammenfassung
11.7 Zusätzliche Ressourcen
Anhang A: Tools und Frameworks
A.1 Isolation-Frameworks
A.1.1 Moq
A.1.2 Rhino Mocks
A.1.3 Typemock Isolator
A.1.4 JustMock
A.1.5 Microsoft Fakes (Moles)
A.1.6 NSubstitute
A.1.7 FakeItEasy
A.1.8 Foq
A.1.9 Isolator++
A.2 Test-Frameworks
A.2.1 Mighty Moose (auch bekannt als ContinuousTests) Continuous Runner
A.2.2 NCrunch Continuous Runner
A.2.3 Typemock Isolator Test Runner
A.2.4 CodeRush Test Runner
A.2.5 ReSharper Test Runner
A.2.6 TestDriven.NET Runner
A.2.7 NUnit GUI Runner
A.2.8 MSTest Runner
A.2.9 Pex
A.3 Test-APIs
A.3.1 MSTest-API – Microsofts Unit-Testing-Framework
A.3.2 MSTest für Metro Apps (Windows Store)
A.3.3 NUnit API
A.3.4 xUnit.net
A.3.5 Fluent Assertions Helper API
A.3.6 Shouldly Helper API
A.3.7 SharpTestsEx Helper API
A.3.8 AutoFixture Helper API
A.4 IoC-Container
A.4.1 Autofac
A.4.2 Ninject
A.4.3 Castle Windsor
A.4.4 Microsoft Unity
A.4.5 StructureMap
A.4.6 Microsoft Managed Extensibility Framework
A.5 Datenbanktests
A.5.1 Verwenden Sie Integrationstests für Ihre Datenschicht
A.5.2 Verwenden Sie TransactionScope für ein Rollback der Daten
A.6 Webtests
A.6.1 Ivonna
A.6.2 Team System Web Test
A.6.3 Watir
A.6.4 Selenium WebDriver
A.6.5 Coypu
A.6.6 Capybara
A.6.7 JavaScript-Tests
A.7 UI-Tests (Desktop)
A.8 Thread-bezogene Tests
A.8.1 Microsoft CHESS
A.8.2 Osherove.ThreadTester
A.9 Akzeptanztests
A.9.1 FitNesse
A.9.2 SpecFlow
A.9.3 Cucumber
A.9.4 TickSpec
A.10 API-Frameworks im BDD-Stil

The Art of Unit Testing

Deutsche Ausgabe

Roy Osherove

Übersetzung aus dem Englischen von Olaf Neuendorf

Impressum

Bibliografische Information der Deutschen Nationalbibliothek

Die 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-8722-8

2. Auflage 2015

www.mitp.de

E-Mail: [email protected]

Telefon: +49 7953 / 7189 - 079

Telefax: +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 Schulz

Sprachkorrektorat: Petra Heubach-Erdmann, Maren Feilen

Coverbild: © Sebastian Duda, Bildnummer 33776850

electronic publication: III-satz, Husby, www.drei-satz.de

Dieses Ebook verwendet das ePub-Format und ist optimiert für die Nutzung mit dem iBooks-reader auf dem iPad von Apple. Bei der Verwendung anderer Reader kann es zu Darstellungsproblemen kommen.

Der Verlag räumt Ihnen mit dem Kauf des ebooks das Recht ein, die Inhalte im Rahmen des geltenden Urheberrechts zu nutzen. Dieses Werk, einschließlich aller seiner Teile, ist urheberrechtlich geschützt. Jede Verwertung außerhalb der engen Grenzen des Urheherrechtsgesetzes ist ohne Zustimmung des Verlages unzulässig und strafbar. Dies gilt insbesondere für Vervielfältigungen, Übersetzungen, Mikroverfilmungen und Einspeicherung und Verarbeitung in elektronischen Systemen.

Der Verlag schützt seine ebooks vor Missbrauch des Urheberrechts durch ein digitales Rechtemanagement. Bei Kauf im Webshop des Verlages werden die ebooks mit einem nicht sichtbaren digitalen Wasserzeichen individuell pro Nutzer signiert.

Bei Kauf in anderen ebook-Webshops erfolgt die Signatur durch die Shopbetreiber. Angaben zu diesem DRM finden Sie auf den Seiten der jeweiligen Anbieter.

Vorwort zur zweiten Auflage

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

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

Nun, diejenigen von Ihnen, die mich kennen, wissen, dass das Anstimmen eines Liedes mitten in einem technischen Vortrag über Software zu den Dingen gehört, die ich vielleicht tue, wenn mir danach ist. Als ich mich wieder meinem Publikum zuwandte, dachte ich so bei mir, dass dieser Osherove wohl ein Gleichgesinnter sei und ich ihn besser kennenlernen müsse.

Und ich lernte ihn besser kennen. In der Tat trug er erheblich zu meinem aktuellen Buch Clean 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 weitere geben.

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

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

Lassen Sie sich nicht beirren, wenn Sie die ersten Seiten durchblättern. Dies ist keine bloße Einführung ins Unit Testing. Es beginnt so, aber wenn Sie bereits Erfahrung haben, können Sie diese ersten Kapitel schnell überfliegen. Während das Buch dann aber voranschreitet, 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 tatsächlich, dass das nächste wohl vom Weltfrieden handeln müsse – denn im Ernst, womit sonst kann man weitermachen, nachdem man das Problem gelöst hat, Unit Testing in starrsinnige Organisationen mit alten, überkommenen Systemen einzuführen.

Dieses Buch ist ein Fachbuch – und zutiefst ein Fachbuch. Es gibt eine Menge Code. Und das ist gut so. Doch Roy beschränkt sich nicht auf die technischen Aspekte. Gelegentlich holt er seine Gitarre hervor, beginnt zu singen und erzählt Geschichten aus seinem Berufsleben. Oder er stellt philosophische Betrachtungen an über die Bedeutung von Design oder die Definition von Integration. Er scheint Gefallen daran zu finden, uns mit Geschichten aus jenen dunklen, längst vergangenen Tagen des Jahres 2006 zu verwöhnen, als ihm so manches 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 Java erklären? Oder? Und abgesehen davon spielt es auch keine Rolle. Er mag zwar C# als Vehikel benutzen, um seine Intention klar zu machen, aber die Lektionen in diesem Buch gelten genauso für Java, C, Ruby, Python, PHP oder jede andere Programmiersprache (vielleicht mit Ausnahme von COBOL).

Egal, ob Sie ein Anfänger auf dem Gebiet des Unit Testings und der testgetriebenen Entwicklung sind oder ein alter Hase, dieses Buch hält für Sie alle etwas bereit. Also viel Vergnü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

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 gewachsen, aber es gibt einen relativen Mangel an Material zum Unit Testing. Wenn ich mein Bücherregal betrachte, dann sehe ich Bücher zur testgetriebenen Entwicklung im Besonderen und Bücher zum Testen im Allgemeinen, aber bis jetzt gab es keine umfassende Referenz zum Unit Testing – kein Buch, das in das Thema einführt, den Leser an die Hand nimmt und von den ersten Schritten bis zu den allgemein akzeptierten besten Vorgehensweisen führt. Diese Tatsache ist verblüffend. Unit Testing ist keine neue Praxis. Wie konnte es dazu kommen?

Es ist beinahe ein Klischee, wenn man sagt, dass wir in einer neuen Industrie arbeiten, aber es 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 Erkenntnisse auch nutzen zu können. In unserer Industrie bestand von Anfang an eine Lücke zwischen Theorie und Praxis und erst jetzt entdecken wir, wie sich das auf unser Fachgebiet ausgewirkt hat.

In den frühen Jahren waren Rechenzeiten teuer. Wir ließen die Programme im Batchbetrieb laufen. Programmierer hatten ein planmäßiges Zeitfenster, sie mussten ihre Programme in Kartenstapel stanzen und in den Maschinenraum tragen. War ein Programm nicht in Ordnung, hatten sie ihre Zeit vergeudet, also überprüften sie es zuvor mit Papier und Stift am Schreibtisch und gingen in Gedanken alle möglichen Szenarien, alle Grenzfä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 sie doch zur Lösung bestimmter Probleme gebaut worden war? Der Mangel hielt uns in der Dunkelheit gefangen.

Später wurden die Maschinen schneller und wir berauschten uns am interaktiven Computing. 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 verloren etwas 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 Zeilen und Symbole änderten, bis wir die magische Zauberformel, die funktionierte, gefunden hatten.

Wir kamen vom Mangel zum Überfluss und verpassten den Mittelweg, aber nun erobern wir ihn zurück. Automatisiertes Unit Testing verbindet die Disziplin der Schreibtischprüfung mit einer neu gefundenen Wertschätzung des Computers als einer Entwicklungsressource. 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 Lage sind, die Tests laufen zu lassen. Ich glaube nicht, dass es irgendein anderes Verfahren in der Softwareentwicklung gibt, das derartig mächtig ist.

Während ich dies im Jahre 2009 schreibe, bin ich froh zu sehen, wie Roys Buch in den Druck geht. Es ist eine praktische Anleitung, die Ihnen helfen wird, loszulegen, und es ist auch eine großartige Referenz, wenn Sie Ihre Aufgaben beim Testing angehen. The Art of Unit Testing ist kein Buch über idealisierte Szenarien. Es zeigt Ihnen, wie man Code testet, der im praktischen Einsatz existiert, wie man Nutzen aus weitverbreiteten Frameworks zieht und – was das Wichtigste ist – wie man Code schreibt, der wesentlich einfacher zu testen ist.

The Art of Unit Testing ist ein wichtiger Titel, der schon vor Jahren hätte geschrieben werden sollen, aber damals waren wir noch nicht bereit dafür. Jetzt sind wir bereit. Genießen Sie es!

Michael Feathers

Senior Consultant Object Mentor

Einleitung

Eines der größten Projekte, an dem ich mitgearbeitet habe und das schiefgelaufen ist, beinhaltete auch Unit Tests. Das dachte ich zumindest. Ich leitete eine Gruppe von Entwicklern, die an einer Abrechnungssoftware arbeiteten, und wir machten es komplett auf die testgetriebene Weise – wir schrieben zuerst die Tests, dann den Code, die Tests schlugen fehl, wir sorgten dafür, dass sie erfolgreich verliefen, führten ein Refactoring durch und fingen wieder von vorne an.

Die ersten paar Monate des Projekts waren großartig. Alles lief gut und wir hatten Tests, die belegten, dass unser Code funktionierte. Aber im Laufe der Zeit änderten sich die Anforderungen. Wir waren also gezwungen, unseren Code zu ändern, um diesen neuen Anforderungen gerecht zu werden, doch als wir das taten, wurden die Tests unzuverlässig und mussten nachgebessert werden. Der Code funktionierte immer noch, aber die Tests, die wir dafür geschrieben hatten, waren so zerbrechlich, dass jede kleine Änderung in unserem Code sie überforderte, auch wenn der Code selbst prima funktionierte. Die Änderung des Codes in einer Klasse oder Methode wurde zu einer gefürchteten Aufgabe, weil wir auch alle damit zusammenhängenden Unit Tests entsprechend anpassen mussten.

Schlimmer noch, einige Tests wurden sogar unbrauchbar, weil diejenigen, die sie geschrieben hatten, das Projekt verließen und keiner wusste, wie deren Tests zu pflegen waren oder was sie eigentlich testeten. Die Namen, die wir unseren Unit-Testing-Methoden gaben, waren nicht aussagekräftig genug und wir hatten Tests, die auf anderen Tests aufbauten. Schließlich warfen wir nach weniger als sechs Monaten Projektlaufzeit die meisten der Tests wieder hinaus.

Das Projekt war ein erbärmlicher Fehlschlag, weil wir zugelassen hatten, dass die Tests, die wir schrieben, mehr schadeten als nützten. Langfristig brauchten wir mehr Zeit, um sie zu pflegen und zu verstehen, als sie uns einsparten. Also hörten wir auf, sie einzusetzen. Ich machte mit anderen Projekten weiter und dort haben wir unsere Arbeit beim Schreiben der Unit Tests besser erledigt. Ihr Einsatz brachte uns großen Erfolg und sparte eine Menge Zeit beim Debuggen und bei der Integration. Seitdem dieses erste Projekt fehlschlug, trage ich bewährte Vorgehensweisen für das Unit Testing zusammen und wende sie auch im nachfolgenden Projekt an. Im Laufe jedes Projekts, an dem ich arbeite, entdecke ich weitere gute Vorgehensweisen.

Zu verstehen, wie man Unit Tests schreibt – und wie man sie wartbar, lesbar und vertrauenswürdig macht –, ist das, wovon dieses Buch handelt. Egal, welche Sprache oder welche integrierte Entwicklungsumgebung (IDE) Sie verwenden. Dieses Buch behandelt die Grundlagen für das Schreiben von Unit Tests, geht dann auf die Grundlagen des Interaction Testings ein und stellt schließlich bewährte Vorgehensweisen für das Schreiben, das Verwalten und das Warten der Unit Tests in echten Projekten vor.

Über dieses Buch

Dass man das, was man wirklich lernen möchte, unterrichten sollte, ist das vielleicht Klügste, was ich jemals irgendwen über das Lernen sagen hörte (ich vergaß, wer das war). Das Schreiben und Veröffentlichen der ersten Ausgabe dieses Buches im Jahre 2009 war nicht weniger als eine echte Lehre für mich. Ursprünglich schrieb ich das Buch, weil ich keine Lust mehr hatte, die gleichen Fragen immer wieder zu beantworten. Aber natürlich gab es auch andere Gründe. Ich wollte etwas Neues ausprobieren, ich wollte experimentieren, ich wollte herausfinden, was ich lernen konnte, indem ich ein Buch schrieb – irgendein Buch. Im Bereich Unit Testing war ich gut. Dachte ich. Aber es ist ein Fluch: Je mehr Erfahrung man hat, desto dümmer kommt man sich vor.

Es gibt Teile in der ersten Ausgabe, denen ich heute nicht mehr zustimme – bespielsweise, dass sich eine Unit auf eine Methode bezieht. Das ist einfach nicht richtig. Eine Unit ist eine Arbeitseinheit, was ich in Kapitel 1 dieser zweiten Auflage diskutiere. Sie kann so klein sein wie eine Methode oder so groß wie mehrere Klassen (möglicherweise Assemblies). Und wie Sie noch sehen werden, gibt es weitere Dinge, die sich ebenfalls geändert haben.

Was neu ist in der zweiten Auflage

In dieser zweiten Auflage habe ich Material über die Unterschiede zwischen beschränkten und unbeschränkten Isolation-Frameworks hinzugefügt. Es gibt ein neues Kapitel 6, das sich mit der Frage beschäftigt, was ein gutes Isolation-Framework ausmacht und wie ein Framework wie Typemock im Inneren funktioniert.

Ich verwende RhinoMocks nicht mehr. Lassen Sie die Finger davon. Es ist tot. Zumindest für den Augenblick. Ich benutze NSubstitute für Beispiele zu den Grundlagen von Isolation-Frameworks und ich empfehle auch FakeItEasy. Ich bin immer noch nicht begeistert von MOQ, was ich detaillierter in Kapitel 6 erläutern werde.

Dem Kapitel über die Implementation des Unit Testings auf der Organisationsebene habe ich weitere Techniken hinzugefügt.

Es gibt eine Reihe von Design-Änderungen im Code, der in diesem Buch abgedruckt ist. Meist habe ich aufgehört, Property Setters zu verwenden, und benutze häufig Constructor Injection. Einige Diskussionen zu den Prinzipien von SOLID habe ich hinzugefügt – aber nur so viel, um Ihnen Appetit auf das Thema zu machen.

Die auf das Build bezogenen Teile von Kapitel 7 enthalten ebenfalls neue Informationen. Seit dem ersten Buch habe ich eine Menge zur Build-Automatisierung und zu Mustern gelernt.

Ich rate von Setup-Methoden ab und stelle Alternativen vor, um Ihre Test mit der gleichen Funktionalität auszustatten. Ich benutze auch neuere Versionen von Nunit, sodass sich einige der neueren Nunit APIs in diesem Buch geändert haben.

Den Teil von Kapitel 10, der sich mit Tools im Hinblick auf Legacy-Code beschäftigt, habe ich aktualisiert.

Die Tatsache, dass ich in den letzten drei Jahren neben .NET mit Ruby gearbeitet habe, führte bei mir zu neuen Einsichten in Bezug auf Design und Testbarkeit. Das spiegelt sich in Kapitel 11 wider. Den Anhang zu Werkzeugen und Frameworks habe ich aktualisiert, neue Tools hinzugefügt und alte entfernt.

Wer dieses Buch lesen sollte

Dieses Buch ist für jeden geeignet, der Code entwickelt und daran interessiert ist, die besten Methoden für das Unit Testing zu erlernen. Alle Beispiele sind mit Visual Studio in C# geschrieben, weshalb die Beispiele insbesondere für .NET-Entwickler nützlich sein werden. Aber was ich unterrichte, passt genau so gut auf die meisten, wenn nicht auf alle objektorientierten und statisch typisierten Sprachen (VB.NET, Java und C++, um nur ein paar zu nennen). Egal, ob Sie ein Architekt sind, ein Entwickler, ein Teamleiter, ein QS-Mitarbeiter (der Code schreibt) oder ein Anfänger in der Programmierung, dieses Buch wurde für Sie geschrieben.

Meilensteine

Wenn Sie noch nie einen Unit Test geschrieben haben, dann ist es am besten, Sie lesen das Buch vom Anfang bis zum Ende, um das komplette Bild zu erhalten. Wenn Sie aber schon Erfahrung haben, dann fühlen Sie sich frei, so in den Kapiteln zu springen, wie es Ihnen gerade passt. Das vorliegende Buch ist in vier Hauptteile gegliedert.

Teil I bringt Sie beim Schreiben von Unit Tests von 0 auf 100. Kapitel 1 und 2 beschäftigen sich mit den Grundlagen, wie etwa der Verwendung eines Test-Frameworks (NUnit), und führen die grundlegenden Testattribute ein, wie z. B. [Test] und [TestCase]. Darüber hinaus werden hier auch verschiedene Prinzipien erläutert im Hinblick auf die Assertion, das Ignorieren von Tests, das Testen von Arbeitseinheiten (Unit of Work Testing), die drei Typen von Endergebnissen eines Unit Tests und der drei dazu benötigten Arten von Tests, nämlich Value Tests, State-Based Tests und Interaction Tests.

Teil II diskutiert fortgeschrittene Methoden zum Auflösen von Abhängigkeiten: Mock-Objekte, Stubs, Isolation-Frameworks und Muster zum Refactoring Ihres Codes, um diese nutzen zu können. Kapitel 3 stellt das Konzept der Stubs vor und veranschaulicht, wie man sie von Hand erzeugen und benutzen kann. In Kapitel 4 wird das Interaction Testing mit handgeschriebenen Mock-Objekten beschrieben. Kapitel 5 führt diese beiden Konzepte schließlich zusammen und zeigt, wie sie sich mithilfe von Isolation-(Mock-)Frameworks kombinieren lassen und ihre Automatisierung erlauben. Kapitel 6 vertieft das Verständnis für beschränkte und unbeschränkte Isolation-Frameworks und wie sie unter der Haube funktionieren.

Teil III beschäftigt sich mit verschiedenen Möglichkeiten, den Testcode zu organisieren, mit Mustern, um ihn auszuführen und seine Strukturen umzubauen (Refactoring), und mit bewährten Methoden zum Schreiben von Tests. In Kapitel 7 werden Testhierarchien vorgestellt und es wird dargestellt, wie Testinfrastruktur-APIs verwendet und wie Tests in den automatisierten Build-Prozess eingebunden werden. Kapitel 7 diskutiert bewährte Vorgehensweisen beim Unit Testing, um wartbare, lesbare und vertrauenswürdige Tests zu entwickeln.

Teil IV beschäftigt sich damit, wie sich Veränderungen in einer Organisation umsetzen lassen und wie man mit existierendem Code umgehen kann. In Kapitel 9 werden Probleme und Lösungen im Zusammenhang mit der Einführung des Unit Testings in einem Unternehmen diskutiert. Dabei werden auch einige Fragen beantwortet, die Ihnen in diesem Zusammenhang vielleicht gestellt werden. Kapitel 10 behandelt die Integration des Unit Testings in vorhandenen Legacy-Code. Es werden mehrere Möglichkeiten aufgezeigt, um festzulegen, wo mit dem Testen begonnen werden sollte, und es werden mehrere Tools vorgestellt, um »untestbaren« Code zu testen. Kapitel 11 diskutiert das vorbelastete Thema des Designs um der Testbarkeit willen und die Alternativen, die derzeit existieren.

Der Anhang listet eine Reihe von Tools auf, die Sie bei Ihren Testanstrengungen hilfreich finden könnten.

Codekonventionen und Downloads

Sie können den Quellcode von der Verlagsseite unter www.mitp.de/9712 herunterladen. Hier finden Sie den Quellcode so wie er in diesem Buch abgedruckt ist (bitte beachten Sie hier auch die Readme-Datei zu den verschiedenen Versionen des Visual Studios). Den Quellcode des Originalbuches können Sie auch auf den folgenden Webseiten herunterladen: https://github.com/royosherove/aout2, www.ArtOfUnitTesting.com oder www.manning.com/osherove2, wo Sie auch weitere englischsprachige Informationen zum Buch, zu dessen Themen und zum Autor finden.

Sämtliche in diesem Buch enthaltenen Listings sind vom normalen Text klar zu unterscheiden und in einer anderen Schriftart wie dieser gesetzt. Manche Passagen sind fett gedruckt, um sie besonders hervorzuheben, oder auch mit einem besonderen Hinweissymbol gekennzeichnet, wenn sie gesondert referenziert werden. [1]

Softwareanforderungen

Um den Code in diesem Buch benutzen zu können, benötigen Sie zumindest Visual Studio C# Express (das kostenlos ist) oder die umfangreicheren (und kostenpflichtigen) Versionen [2]. Darüber hinaus sind auch NUnit (ein freies Open-Source-Framework) und andere Tools erforderlich, auf die an den entsprechenden Stellen hingewiesen wird. Alle erwähnten Tools sind entweder kostenlos, als Open-Source-Versionen oder aber als Testversionen verfügbar, die Sie ausprobieren können, während Sie dieses Buch lesen.

Danksagung

Ein großes Dankeschön geht an Michael Stephens und Nermina Miller von Manning Publications für ihre Geduld auf dem langen Weg beim Schreiben dieses Buches. Mein Dank geht ebenso an jeden bei Manning, der an der zweiten Auflage in der Produktion und hinter den Kulissen mitgearbeitet hat.

Dank gebührt auch Jim Newkirk, Michael Feathers, Gerard Meszaros und vielen anderen, die mich mit Inspiration und Ideen unterstützt und dieses Buch zu dem gemacht haben, was es ist. Besonders danke ich dir, Uncle Bob Martin, dafür, dass du es übernommen hast, das Vorwort für die zweite Auflage zu schreiben.

Die folgenden Rezensenten haben das Manuskript in verschiedenen Phasen seiner Entwicklung gelesen. Ich möchte ihnen für ihre wertvollen Anmerkungen danken: Aaron Colcord, Alessandro Campeism, Alessandro Gallo, Bill Sorensen, Bruno Sonnino, Camal Cakar, David Madouros, Dr. Frances Buontempo, Dror Helper, Francesco Goggi, Iván Pazmino, Jason Hales, Joao Angelo, Kaleb Pederson, Karl Metivier, Mertin Skurla, Martyn Fletcher, Paul Stack, Philip Lee, Pradeep Chellappan, Raphael Faria und Tim Sloan. Dank auch an Rickard Nilsson, der das abschließende Manuskript vor der Drucklegung Korrektur gelesen hat.

Ein abschließendes Wort des Dankes auch an die ersten Leser des Buches in Mannings »Early Access Program« für ihre Kommentare im Online-Forum. Sie haben dabei geholfen, dem Buch seine endgültige Form zu geben.

[1] Anmerkung des Übersetzers: Die Kommentare innerhalb der Listings und auch der größte Teil der Strings wurden – der größeren Klarheit und der besseren Lesbarkeit wegen – übersetzt. In dieser Hinsicht unterscheiden sich die abgedruckten Listings vom englischen Quelltext, den Sie von den amerikanischen Webseiten herunterladen können. Der Quelltext auf der deutschen Seite des mitp-Verlages wurde genauso angepasst, wie Sie ihn in diesem Buch vorfinden. Sie haben also die Möglichkeit, wahlweise die unveränderten Original-Dateien von den amerikanischen Seiten oder die überarbeiteten von der deutschen Seite zu verwenden.

[2] Anmerkung des Übersetzers: Zum Zeitpunkt der Veröffentlichung des amerikanischen Originaltitels war VS 2010 die aktuelle Version von Microsoft, auf die auch in diesem Buch Bezug genommen wurde. Hier wurden in der vorliegenden deutschen Ausgabe Verweise auf die inzwischen veröffentlichte Version 2013 ergänzt oder ersetzt. Beachten Sie bitte auch die der deutschen Version des Quellcodes beiliegende Readme-Datei, die Hinweise auf die verschiedenen Versionen enthält.

Teil I: Erste Schritte

Dieser Teil des Buches behandelt die Grundlagen des Unit Testings.

In Kapitel 1 werde ich definieren, was eine Unit ist und was »gutes« Unit Testing bedeutet und ich werde das Unit Testing mit dem Integration Testing vergleichen. Anschließend werfen wir einen kurzen Blick auf das Test-Driven Development und dessen Rolle in Bezug auf das Unit Testing.

In Kapitel 2 werden Sie damit loslegen, Ihren ersten Unit Test mithilfe von NUnit zu schreiben. Sie werden die grundlegende API von NUnit kennenlernen und Sie werden sehen, wie Asserts verwendet und wie Tests mit dem NUnit Test Runner durchgeführt werden.

In diesem Teil:

Kapitel 1

Die Grundlagen des Unit Testings

Kapitel 2

Ein erster Unit Test