Abbildung von: Lean Testing für C++-Programmierer - dpunkt

Lean Testing für C++-Programmierer

Angemessen statt aufwendig testen
dpunkt (Verlag)
1. Auflage
Erschienen am 1. Juni 2016
248 Seiten
E-Book
ePUB mit Wasserzeichen-DRM
E-Book
PDF mit Wasserzeichen-DRM
978-3-86491-968-8 (ISBN)
29,90 €inkl. 7% MwSt.
Systemvoraussetzungen
für ePUB mit Wasserzeichen-DRM und PDF mit Wasserzeichen-DRM
(Hinweis: Die Auswahl des von Ihnen gewünschten Dateiformats und des Kopierschutzes erfolgt erst im System des E-Book Anbieters)
E-Book Einzellizenz
Als Download verfügbar
Sie programmieren - auch in C++. Sie führen regelmäßig Unit Tests durch. Sie sind sich manchmal unsicher, ob Sie ausreichend oder zu viel getestet haben. Werfen Sie einen Blick in dieses Buch, Sie werden viele Anregungen für Ihre tägliche Arbeit finden!
"Lean Testing" steht für einen Ansatz, der auf der einen Seite alle wichtigen Testfälle zur Prüfung der Software berücksichtigt, auf der anderen Seite aber den Testaufwand in einem überschaubaren Rahmen hält. Der angemessene Mittelweg zwischen zu wenig und zu viel Testen wird bei jedem Vorgehen zum Entwerfen der Testfälle diskutiert und erörtert.
Die in diesem Buch präsentierten Vorgehensweisen zum Testfallentwurf werden konkret mit den entsprechenden C++-Programmtexten und den jeweiligen Testfällen dargelegt. Sind hierzu unterstützende Werkzeuge erforderlich, beschreiben die Autoren deren Anwendung. Dabei geben sie nützliche Hinweise für die Verwendung der Testverfahren und bieten einen Leitfaden für ihren Einsatz.

Alle Testverfahren des aktuellen ISO-Standards 29119, die für den Unit Test relevant sind, werden vorgestellt und ausführlich behandelt.

Ulrich Breymann ist ein bekannter Fachautor für die Programmiersprache C++ - Andreas Spillner für den Testbereich. Beide Autoren bringen ihre Fachkompetenz ein und schlagen eine Brücke zwischen Programmierung und Test. Das Buch unterstützt die aktuelle Entwicklung, bei der Softwareerstellung keine strikte (personenbezogene) Trennung zwischen Implementierung und Test auf Unit-Ebene vorzusehen (z.B. TDD & Test-first-Ansatz).
Andreas Spillner ist Professor für Informatik an der Hochschule Bremen. Er war über 10 Jahre Sprecher der Fachgruppe TAV "Test, Analyse und Verifikation von Software" der Gesellschaft für Informatik e.V. (GI) und bis Ende 2009 Mitglied im German Testing Board e.V. Im Jahr 2007 ist er zum Fellow der GI ernannt worden. Seine Arbeitsschwerpunkte liegen im Bereich Softwaretechnik, Qualitätssicherung und Testen. Ulrich Breymann war als Systemanalytiker und Projektleiter in der Industrie und der Raumfahrttechnik tätig. Danach lehrte er als Professor Informatik an der Hochschule Bremen. Er arbeitete an dem ersten C++-Standard mit und ist ein renommierter Autor zu den Themen Programmierung in C++, C++ Standard Template Library (STL) und Java ME (Micro Edition).
1 - Inhaltsverzeichnis [Seite 7]
2 - 1 Einleitung [Seite 11]
3 - 2 Test gegen die Anforderungen [Seite 19]
4 - 3 Statische Verfahren [Seite 23]
4.1 - 3.1 Codereview [Seite 25]
4.2 - 3.2 Compiler [Seite 26]
4.3 - 3.3 Analysewerkzeuge [Seite 29]
4.4 - 3.4 Analysebeispiele [Seite 31]
4.4.1 - 3.4.1 Clang als Analysewerkzeug [Seite 31]
4.4.2 - 3.4.2 Scan-Build [Seite 33]
5 - 4 Testentwurf und Testdurchführung [Seite 35]
5.1 - 4.1 Das Google-Test-Framework [Seite 35]
5.1.1 - 4.1.1 Installation [Seite 36]
5.1.2 - 4.1.2 Anwendung [Seite 38]
5.2 - 4.2 Happy-Path-Test [Seite 41]
5.3 - 4.3 Äquivalenzklassentest [Seite 44]
5.3.1 - 4.3.1 Ein Beispiel mit einem Parameter [Seite 45]
5.3.2 - 4.3.2 Das Beispiel in C++ [Seite 48]
5.3.3 - 4.3.3 Erweiterung auf andere Datentypen [Seite 49]
5.3.4 - 4.3.4 Mehrere Parameter [Seite 52]
5.4 - 4.4 Grenzwertanalyse [Seite 65]
5.4.1 - 4.4.1 Ein Beispiel [Seite 68]
5.4.2 - 4.4.2 Mehrere Parameter [Seite 69]
5.4.3 - 4.4.3 Ergänzung: Grenzen im Programmtext [Seite 70]
5.5 - 4.5 Klassifikationsbaummethode [Seite 71]
5.5.1 - 4.5.1 Ein Beispiel [Seite 72]
5.5.2 - 4.5.2 Das Beispiel in C++ [Seite 77]
5.6 - 4.6 Kombinatorisches Testen [Seite 85]
5.6.1 - 4.6.1 Orthogonale Arrays [Seite 87]
5.6.2 - 4.6.2 Covering Arrays [Seite 87]
5.6.3 - 4.6.3 n-weises Testen [Seite 88]
5.6.4 - 4.6.4 Werkzeugnutzung [Seite 93]
5.6.5 - 4.6.5 Das Beispiel in C++ [Seite 95]
5.6.6 - 4.6.6 Ein Beispiel ohne Orakel [Seite 98]
5.7 - 4.7 Entscheidungstabellentest [Seite 102]
5.7.1 - 4.7.1 Ein Beispiel [Seite 103]
5.7.2 - 4.7.2 Ein Beispiel in C++ [Seite 107]
5.8 - 4.8 Zustandsbasierter Test [Seite 113]
5.8.1 - 4.8.1 Ein Beispiel [Seite 116]
5.8.2 - 4.8.2 Der minimale Zustandstest [Seite 119]
5.8.3 - 4.8.3 Das Beispiel in C++ [Seite 123]
5.8.4 - 4.8.4 Test von Übergangsfolgen [Seite 124]
5.9 - 4.9 Syntaxtest [Seite 134]
5.9.1 - 4.9.1 Das Beispiel in C++ - Variante 1 [Seite 137]
5.9.2 - 4.9.2 Das Beispiel in C++ - Variante 2 [Seite 139]
5.10 - 4.10 Zufallstest [Seite 143]
6 - 5 Strukturbasierte Testverfahren [Seite 151]
6.1 - 5.1 Kontrollflussbasierter Test [Seite 153]
6.1.1 - 5.1.1 Werkzeugunterstützung [Seite 154]
6.1.2 - 5.1.2 Anweisungstest [Seite 155]
6.1.3 - 5.1.3 Entscheidungstest [Seite 159]
6.1.4 - 5.1.4 Pfadtest [Seite 163]
6.1.5 - 5.1.5 Schleifentest [Seite 164]
6.2 - 5.2 Test komplexer Entscheidungen [Seite 168]
6.2.1 - 5.2.1 Einfacher Bedingungstest [Seite 169]
6.2.2 - 5.2.2 Mehrfachbedingungs- oder Bedingungskombinationstest [Seite 171]
6.2.3 - 5.2.3 Modifizierter Bedingungs-/Entscheidungstest [Seite 172]
6.3 - 5.3 Bewertung [Seite 185]
6.4 - 5.4 Bezug zu anderen Testverfahren [Seite 187]
6.5 - 5.5 Hinweise für die Praxis [Seite 188]
7 - 6 Erfahrungsbasiertes Testen [Seite 189]
7.1 - 6.1 Exploratives Testen [Seite 196]
7.2 - 6.2 Freies Testen [Seite 201]
8 - 7 Softwareteststandard ISO 29119 [Seite 207]
8.1 - 7.1 Testverfahren nach ISO 29119 [Seite 208]
8.1.1 - 7.1.1 Spezifikationsbasierte Testverfahren [Seite 208]
8.1.2 - 7.1.2 Strukturbasierte Testverfahren [Seite 211]
8.1.3 - 7.1.3 Erfahrungsbasierte Testverfahren [Seite 213]
9 - 8 Ein Leitfaden zum Einsatz der Testverfahren [Seite 215]
10 - 9 Zu berücksichtigende C++-Eigenschaften [Seite 221]
10.1 - 9.1 Automatische Typumwandlung [Seite 221]
10.2 - 9.2 Undefinierte Bitbreite [Seite 221]
10.3 - 9.3 Alignment [Seite 222]
10.4 - 9.4 32- oder 64-Bit-System? [Seite 222]
10.5 - 9.5 static-Missverständnis [Seite 223]
10.6 - 9.6 Memory Leaks [Seite 224]
11 - Glossar [Seite 229]
12 - Literaturverzeichnis [Seite 243]
13 - Stichwortverzeichnis [Seite 245]
14 - www.dpunkt.de [Seite 0]

3 Statische Verfahren


Der Begriff Software umfasst vieles. So gehören sowohl die Design- als auch die Programmdokumentation dazu und natürlich auch der Programmcode. Nur dieser wird im Folgenden betrachtet. Statische Verfahren analysieren den Programmcode, ohne ihn auszuführen - daher der Name. Zu den statischen Verfahren gehören sowohl Reviews zur Bewertung des Programmcodes und zur Aufdeckung von Fehlern als auch die automatisierte Analyse mit Werkzeugen. Es gibt verschiedene Arten von Reviews, auf die unten kurz eingegangen wird. Allen Reviews ist gemeinsam, dass sie Arbeitszeit kosten, nicht nur die des Autors, sondern auch die von Kollegen, die als Gutachter tätig werden. Uns geht es darum, die Arbeitszeit aller Beteiligten zu reduzieren, um mit demselben Aufwand bessere Qualität zu erzielen. Deshalb liegt der Schwerpunkt dieses Kapitels nicht auf Reviews, die nur der Vollständigkeit halber erwähnt werden, sondern auf Verfahren zur statischen Analyse, die automatisiert ablaufen und daher wenig Arbeitszeit kosten. Reviews werden dadurch nicht überflüssig, aber weniger aufwendig, weil ein Teil der Fehler oder Schwächen schon vorher durch die statische Analyse aufgedeckt und anschließend korrigiert werden kann. Je früher ein Fehler gefunden wird, desto leichter (und billiger) ist seine Korrektur.

Bevor es mit dem Testen unserer Software - also der Ausführung des Testobjekts mit Testdaten auf dem Rechner - losgeht, ist es sinnvoll, vorher so viele Fehler wie möglich zu entdecken, um den Aufwand für das Testen gering (»lean«) zu halten. Daher werden hier die statischen Analyseverfahren ausführlich vorgestellt.

Statische Verfahren werden typischerweise von Entwicklern eingesetzt. Diese Verfahren können natürlich nicht alle Fehler finden, insbesondere nicht diejenigen, die von externen Daten herrühren, die erst zur Laufzeit vom Programm eingelesen werden. Dafür gibt es die dynamischen Verfahren1, insbesondere die Unit Tests auf der Ebene des Entwicklers. Umgekehrt können Unit Tests verschiedene statische Eigenschaften nicht prüfen, wie etwa die Einhaltung von Programmierrichtlinien. Statische Verfahren sind besonders geeignet zur Prüfung der folgenden Elemente:

  • Syntax (Grammatik) des Programms. Bei einer nicht der Spezifikation der Programmiersprache entsprechenden Syntax gibt schon der Compiler eine Fehlermeldung aus. Voraussetzung ist natürlich, dass der Compiler die Sprachspezifikation richtig implementiert.

  • Einhaltung anerkannter Prinzipien zur Softwareentwicklung bzw. Programmierung. So kann ein Verfahren das (im Allgemeinen unerwünschte) Vorhandensein globaler Variablen entdecken oder unbeabsichtigte fehlerhafte Typumwandlungen.

  • Einhaltung der Programmierrichtlinien (sofern es welche gibt). Diese schreiben zum Beispiel vor, wie Namen von Klassen und Objekten zu bilden sind, wie Kommentare gestaltet werden sollen und ob Exceptions verwendet werden dürfen.

  • Kontrollfluss. So können nicht erreichbarer Code oder fehlerhafte Ablaufstrukturen entdeckt werden.

  • Datenfluss. Dabei wird zum Beispiel geprüft, ob eine Variable vor der Verwendung mit einem Wert initialisiert wurde oder ob ein zugewiesener Wert überhaupt verwendet wird. Wenn nicht, muss das kein Fehler sein, deutet aber daraufhin, dass der Programmcode nicht der eigentlichen Absicht entspricht.

Konkrete Beispiele finden Sie weiter unten.

Statische Verfahren können nicht nur auf den Quellcode angewendet werden, sondern auch auf Bytecode (wie etwa das Werkzeug FindBugs2 für die Programmiersprache Java) oder auf binäre ausführbare Programme. Wir beschränken uns hier auf den Quellcode.

Beschränkungen in der Praxis

Ein Werkzeug ist ein Werkzeug, nicht mehr und nicht weniger. Insbesondere kann es nicht die Gedanken des Programmierers lesen und daraufhin die korrekte Umsetzung in Programmcode überprüfen. Das bedeutet, dass die Entwickler eines Werkzeugs bestimmte Vorstellungen haben, wie Anweisungen und Programmstrukturen aussehen sollen, und diese Annahmen im Werkzeug implementieren. Diese Annahmen können sich an manchen Stellen als falsch erweisen. Aus diesem Grund kann es sein, dass ein Werkzeug

  • einen »Fehler« meldet, der tatsächlich keiner ist (falsch positive Meldung), oder

  • einen vorhandenen Fehler nicht meldet (falsch negative Meldung).

Ein besonders gründliches Werkzeug erzeugt möglicherweise eine Menge falsch positiver Meldungen, sodass die Gefahr besteht, das wichtige Meldungen in der schieren Menge untergehen. Die Entwickler solcher Werkzeuge bemühen sich, die Anzahl der falsch positiven Ergebnisse zu reduzieren.

Praktischer Einsatz

Um die Menge an Fehlermeldungen und Warnungen zu reduzieren und die Anzahl der Tests zu beschränken, empfiehlt sich die nachstehende Reihenfolge:

  1. Das Testobjekt (Programmcode) compilieren und ggf. korrigieren, bis die Compilation fehlerlos durchläuft. Dabei die höchste Warnstufe einschalten und die Warnungen des Compilers berücksichtigen.

  2. Statische Verfahren einsetzen und alle gefundenen Fehler korrigieren. Die Anzahl der jetzt noch notwendigen Tests wird durch jeden in dieser Phase gefundenen Fehler reduziert.

  3. Erst dann die Unit Tests durchführen.

3.1 Codereview


Review ist der Oberbegriff für verschiedene statische Prüfverfahren, die von Personen durchgeführt werden. Das Prüfobjekt kann eine Designdokumentation sein, ein zu erstellendes Produkt oder ein Teil davon oder auch der Ablauf eines Prozesses. Ein Autor ist oft »betriebsblind« und sieht bestimmte Dinge nicht mehr, deshalb ist es wichtig, dass er den Code einem Kollegen zeigt. Ein großer Vorteil eines Reviews: Andere Personen sehen das Prüfobjekt unter einem ganz anderen Blickwinkel. In diesem Abschnitt geht es aber nur um Codereviews, die hauptsächlich in zwei Arten vorkommen:

Walkthrough

Das Vorgehen ist für kleine Teams von bis zu fünf Personen geeignet und verursacht relativ wenig Aufwand. Dabei stellt der Programmautor den Code einigen Experten vor, zum Beispiel fachlich versierten Kollegen - möglichst aus anderen Projekten - oder Testern. Mit ihnen zusammen werden verschiedene Benutzungsabläufe durchgespielt. Ziel ist das gegenseitige Lernen und Verständnis über das Prüfobjekt und natürlich, Fehler zu finden.

Inspektion

Eine Inspektion folgt einem formalisierten Ablauf, in dem es verschiedene Rollen gibt, wie etwa einen Moderator und verschiedenen Gutachter (ebenfalls fachlich versierte Kollegen). Einer der Gutachter trägt den Inhalt des Prüfobjekts vor, wobei die anderen entsprechend Fragen stellen. Die Gutachter bereiten sich auf die Sitzung vor, was beim Walkthrough entfallen kann. Während der Inspektion werden auch Daten gesammelt, die zur Qualitätsbeurteilung des Entwicklungs- und Inspektionsprozesses herangezogen werden. Ziel der Inspektion ist das Finden von Fehlern und ggf. deren Ursachen.

Codereviews tragen sehr zur Qualität einer Software bei. Deswegen werden sie hier als statisches Verfahren erwähnt, auch wenn sie nicht weiter behandelt werden.

Ausführliche Beschreibungen zu den unterschiedlichen Arten der Reviews sind in [Spillner & Linz 12, Kap. 4] und in [Rösler et al. 13] zu finden.

3.2 Compiler


Ein Compiler muss zwangsläufig ein Programm analysieren, wenn er lauffähigen Code daraus herstellen soll. Typischerweise baut er einen abstrakten Syntaxbaum auf, abgekürzt AST (abstract syntax tree) genannt. Im Prinzip hat ein Compiler alle im Programmcode liegenden Informationen zur Verfügung, sodass er einige Fehler leicht entdecken kann, wie etwa die fehlende Deklaration einer Variablen oder den Aufruf einer Funktion mit einem falschen Parametertyp.

Was ein Compiler aber nicht oder nur zum Teil kennt, sind Empfehlungen für einen defensiven Programmierstil oder die gewünschten Programmierrichtlinien.

Es gibt eine Menge verschiedener Compiler, sowohl Open Source als auch kommerziell. Die hier und im Folgenden beschriebene Problematik ist bei allen Compilern strukturell ähnlich, weswegen wir uns auf die Open-Source-Compiler GNU C++ (G++) und Clang (Aufruf clang++) beschränken.

G++

G++ gibt es für Mac OS und Linux [URL: gcc]. Die Distribution für Mac OS hinkt bezüglich der Versionsnummern gegenüber Linux etwas hinterher. Unsere Empfehlung: Auf dem Mac lieber Clang verwenden (siehe unten). In beiden Fällen wird die mehrere Gigabytes umfassende Entwicklungsumgebung Xcode benötigt.

G++ gibt es auch für Windows, wobei die MinGW- und die Cygwin-Distribution am weitesten verbreitet sind. Aber auch hier hinken die Versionsnummern denen für Linux hinterher.

Clang

Clang [URL: clang] ist ein Frontend für die C-Sprachfamilie (C/C++, Objective C/C++), das für LLVM3, eine modulare Compilerarchitektur, entwickelt wurde. Clang/LLVM ist Open Source. LLVM ist aus einem Projekt der Compilerforschung entstanden. Clang/LLVM ist besser als G++ für die statische Analyse eines...

Dateiformat: ePUB
Kopierschutz: Wasserzeichen-DRM (Digital Rights Management)

Systemvoraussetzungen:

  • Computer (Windows; MacOS X; Linux): Verwenden Sie eine Lese-Software, die das Dateiformat ePUB verarbeiten kann: z.B. Adobe Digital Editions oder FBReader – beide kostenlos (siehe E-Book Hilfe).
  • Tablet/Smartphone (Android; iOS): Installieren Sie die App Adobe Digital Editions oder eine andere Leseapp für E-Books, z.B. PocketBook (siehe E-Book Hilfe).
  • E-Book-Reader: Bookeen, Kobo, Pocketbook, Sony, Tolino u.v.a.m. (nicht Kindle)

Das Dateiformat ePUB ist sehr gut für Romane und Sachbücher geeignet - also für „fließenden” Text ohne komplexes Layout. Bei E-Readern oder Smartphones passt sich der Zeilen- und Seitenumbruch automatisch den kleinen Displays an.
Mit Wasserzeichen-DRM wird hier ein „weicher” Kopierschutz verwendet. Daher ist technisch zwar alles möglich – sogar eine unzulässige Weitergabe. Aber an sichtbaren und unsichtbaren Stellen wird der Käufer des E-Books als Wasserzeichen hinterlegt, sodass im Falle eines Missbrauchs die Spur zurückverfolgt werden kann. 

Weitere Informationen finden Sie in unserer  E-Book Hilfe.

Dateiformat: PDF
Kopierschutz: Wasserzeichen-DRM (Digital Rights Management)

Systemvoraussetzungen:

  • Computer (Windows; MacOS X; Linux): Verwenden Sie zum Lesen die kostenlose Software Adobe Reader, Adobe Digital Editions oder einen anderen PDF-Viewer Ihrer Wahl (siehe E-Book Hilfe).
  • Tablet/Smartphone (Android; iOS): Installieren Sie bereits vor dem Download die kostenlose App Adobe Digital Editions oder die App PocketBook (siehe E-Book Hilfe).
  • E-Book-Reader: Bookeen, Kobo, Pocketbook, Sony, Tolino u.v.a.m. (nur bedingt: Kindle)

Das Dateiformat PDF zeigt auf jeder Hardware eine Buchseite stets identisch an. Daher ist eine PDF auch für ein komplexes Layout geeignet, wie es bei Lehr- und Fachbüchern verwendet wird (Bilder, Tabellen, Spalten, Fußnoten). Bei kleinen Displays von E-Readern oder Smartphones sind PDF leider eher nervig, weil zu viel Scrollen notwendig ist. Mit Wasserzeichen-DRM wird hier ein „weicher” Kopierschutz verwendet. Daher ist technisch zwar alles möglich – sogar eine unzulässige Weitergabe. Aber an sichtbaren und unsichtbaren Stellen wird der Käufer des E-Books als Wasserzeichen hinterlegt, sodass im Falle eines Missbrauchs die Spur zurückverfolgt werden kann.

Weitere Informationen finden Sie in unserer  E-Book Hilfe.