Erhalten Sie Zugang zu diesem und mehr als 300000 Büchern ab EUR 5,99 monatlich.
Dieses Buch beschreibt alle wichtigen praxistauglichen Methoden des Software-Tests für eingebettete Systeme und zeigt, wie sie sich in ein planungsgesteuertes bzw. agiles Projekt eingliedern lassen. Dabei werden die Teststufen in chronologischer Reihenfolge behandelt und die Erläuterungen mit zahlreichen Beispielen aus Projekten mit und ohne Sicherheitsrelevanz illustriert. Behandelt werden u. a. folgende Themen: • Statische Code-Analyse • Unit-Tests • Hardware/Software-Integrationstests • Software/Software-Integrationstests • Systemtests • Data Race Testing • Schedulability und Echtzeittests • Normen und Haftungsrisiko Persönliche Bewertungen von Testmethoden, Erfahrungsberichte und eine Diskussion von Testwerkzeugen am Ende jedes Kapitels geben dem Leser wichtige Orientierungshilfen bei der Umsetzung des Stoffs und beim Kauf von Werkzeugen. Verständnisfragen mit Antworten sowie Übungsbeispiele mit Lösungen erleichtern die Verwendung des Buches im Hochschulbereich und geben auch dem Leser aus dem industriellen Umfeld die Möglichkeit zur Selbstkontrolle. Die Buchkapitel sind weitgehend unabhängig voneinander aufgebaut. Sie erlauben das Lesen der Kapitel in einer beliebigen Reihenfolge und machen das Buch auch als Nachschlagewerk wertvoll. Neu in der 2. Auflage: • Aktualisierung auf die neuesten Tools und Normen – insbesondere ISO 29119 • Neues Kapitel zu Trace-Daten im Testumfeld • Zusätzliche Erfahrungsberichte
Sie lesen das E-Book in den Legimi-Apps auf:
Seitenzahl: 570
Das E-Book (TTS) können Sie hören im Abo „Legimi Premium” in Legimi-Apps auf:
Stephan Grünfelder war Programmierer und Tester für die unbemannte Raumfahrt und Medizintechnik, später Projektleiter für Steuergeräte-Entwicklung im Automobilbereich und arbeitet nun als selbständiger Trainer für Software-Testing und als Senior Software Tester für Broadcast-Ausrüstung. Er hat bzw. hatte Lehraufträge an der Hochschule Reykjavik, der Fachhochschule Technikum Wien und der Technischen Universität Wien.
Zu diesem Buch – sowie zu vielen weiteren dpunkt.büchern – können Sie auch das entsprechende E-Book im PDF-Format herunterladen. Werden Sie dazu einfach Mitglied bei dpunkt.plus+:
www.dpunkt.plus
Stephan Grünfelder
Ein Praxishandbuch für Entwickler,Tester und technische Projektleiter
2., aktualisierte Auflage
Stephan Grünfelder
Lektorat: Sandra Bollenbacher
Copy-Editing: Geesche Kieckbusch, Hamburg
Satz: Frank Heidt
Herstellung: Susanne Bröckelmann
Umschlaggestaltung: Helmut Kraus, www.exclam.de
Druck und Bindung: M.P. Media-Print Informationstechnologie GmbH, 33100 Paderborn
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:
Print978-3-86490-448-6
PDF978-3-96088-148-3
ePub978-3-96088-149-0
mobi978-3-96088-150-6
2., aktualisierte Auflage 2017
Copyright © 2017 dpunkt.verlag GmbH
Wieblinger Weg 17
69123 Heidelberg
Die vorliegende Publikation ist urheberrechtlich geschützt. Alle Rechte vorbehalten. Die Verwendung der Texte und Abbildungen, auch auszugsweise, ist ohne die schriftliche Zustimmung des Verlags urheberrechtswidrig und daher strafbar. Dies gilt insbesondere für die Vervielfältigung, Übersetzung oder die Verwendung in elektronischen Systemen.
Es wird darauf hingewiesen, dass die im Buch verwendeten Soft- und Hardware-Bezeichnungen sowie Markennamen und Produktbezeichnungen der jeweiligen Firmen im Allgemeinen warenzeichen-, marken- oder patentrechtlichem Schutz unterliegen.
Alle Angaben und Programme in diesem Buch wurden mit größter Sorgfalt kontrolliert. Weder Autor noch Verlag können jedoch für Schäden haftbar gemacht werden, die in Zusammenhang mit der Verwendung dieses Buches stehen.
5 4 3 2 1 0
Wie viele Artikel und Bücher habe ich schon gelesen, in denen im ersten Satz steht, dass Computersysteme immer komplexer werden oder Entwicklungszyklen immer kürzer und dass man deshalb von nun an Dinge besser/schneller machen muss als früher? Ich kann es nicht sagen. Diese Ausrede und Einleitung ist aber schon seit mehreren Jahrzehnten gültig, denn Techniken werden unentwegt weiterentwickelt, Technologien wandeln sich durch neue Einflüsse und die Zeit steht niemals still. Schon gar nicht rund um die Themen der Software-Entwicklung. Dieses Buch wurde nicht geschrieben, weil gerade jetzt alles komplexer wird und ich, als Autor, der Welt sagen will, wie man damit umgeht, sondern weil es im deutschsprachigen Raum noch kein brauchbares Buch zum Thema Test von Software eingebetteter Systeme gab und ich oft genug gesehen habe, wie schwer sich manche Leute damit tun.
Das Buch vermittelt praxisnahes Wissen zum Test von Software eingebetteter Systeme, so wie es jetzt und heute gemacht wird oder gemäß dem industriellen Stand der Technik gemacht werden sollte. Auch wenn der Stand der Wissenschaft und Forschung für das Schreiben des Buchs wichtig war, so nehmen forschungsnahe Themen nur wenig Platz ein, wenn deren industrielle Umsetzung Probleme bereitet. Das Buch präsentiert viele Beispiele, persönliche Erfahrungsberichte und enthält praxisnahe Fragen und Lösungen zum Selbsttest. Die Terminologie des Buchs orientiert sich weitgehend an der des ISTQB-Certified-Tester-Schemas und der Normenreihe ISO 29119. Das Buch ist dabei an vielen Stellen komplementär zum Curriculum des ISTQB, speziell dann, wenn es um Echtzeit, Concurrency und maschinennahe Themen geht, und es ist – unvermeidbar – zum Teil redundant dazu.
Software für eingebettete Systeme unterscheidet sich von anderer Software dadurch, dass die Software Teil des Produkts ist, das der Kunde kauft, und nicht das Produkt selbst. Meist wird das Produkt, in das ein Prozessor mit zugehöriger Software eingebettet ist, wertlos, wenn die Software nicht zuverlässig funktioniert. Im schlimmsten Fall muss es vom Markt genommen werden. Kein Wunder also, dass man sich in dieser Sparte der Software-Entwicklung besonders viele Gedanken zur Korrektheit von Software macht.
Aber durch Testen alleine erhält man kein fehlerfreies Produkt. Wie ein alter Freund von mir zu sagen pflegte: »Man kann Software nicht am Ende der Produktentwicklung ›gesund testen‹, wenn es in so manchen Entwicklungsschritten zuvor krankt.« Das vorliegende Buch beschäftigt sich daher auch mit Praktiken links und rechts vom Test, die die Entwicklung begleiten und dazu beitragen, mit höherer Wahrscheinlichkeit »gesunde« Software zu erhalten.
Das Spektrum eingebetteter Systeme reicht von batteriebetriebenen 16-Bit-Controllern ohne Betriebssystem und mit geringen Anforderungen an die Systemintegrität bis hin zu im Internet Of Things vernetzten Multiprozessor-Systemen mit Echtzeitbetriebssystem, Mensch-Maschine-Schnittstelle und Sicherheitsrelevanz. Entsprechend viele Zielgruppen hat dieses Buch. Daher gibt es vermutlich Kapitel im Buch, die für Ihre speziellen Aufgaben irrelevant sein könnten. Sie dürfen diese Kapitel gerne überspringen, denn ich habe mir größte Mühe gegeben, jedes Kapitel weitgehend unabhängig von den anderen zu schreiben, und das Letzte, was dieses Buch tun sollte, ist, Sie zu langweilen. So können Systemtester zum Beispiel getrost die Kapitel über Reviews und statische Analyse auslassen. Die Unabhängigkeit der Kapitel macht es nötig, dass Inhalte teilweise wiederholt werden müssen.
Fans moderner Programmiersprachen sollten sich nicht daran stoßen, dass fast alle Beispielprogramme im Buch in der Programmiersprache C geschrieben sind. C ist weder komfortabel noch modern, doch hat C noch immer seinen festen Platz in der Entwicklung von Produkten mit höchsten Qualitätsanforderungen, und die meisten Entwickler verstehen die Basissyntax dieser Sprache ohne Probleme.
Ich wünsche Ihnen viel Freude beim Lesen und viel Erfolg bei der Umsetzung der in diesem Buch präsentierten Ideen.
Herzlichst
Stephan Grünfelder, Oktober 2016
Ich persönlich fand es immer ärgerlich ein Buch zu lesen, in dem ein Autor über Themen schrieb, bei denen er – wie ich später herausfand – nicht wirklich sattelfest war oder die er nur aus einem einzigen Projekt kannte. Nun habe ich selbst ein Buch verfasst und noch dazu eines mit dem Anspruch, praxisnah zu sein. Ich kann nicht für alle in diesem Buch beschriebenen Methoden ein Experte mit jahrelanger Erfahrung sein. Um meinen eigenen Ansprüchen an ein Fachbuch gerecht zu werden, war es daher unumgänglich, Partner zur Unterstützung hinzuzuziehen. Diesen Unterstützern gilt mein besonderer Dank. Ich nenne zunächst Personen, die ganze Kapitel (mit)gestaltet haben:
Reinhard Wilhelm, wissenschaftlicher Direktor des Leibniz-Zentrums für Informatik und Professor an der Universität des Saarlandes, hat das Kapitel über Worst Case Execution Timing Analysis verfasst.
Michael González Harbour, Professor des Computer- und Echtzeitteams der Fakultät für Computer und Elektronik der Universität Kantabrien, Spanien, hat das Kapitel über Schedulability-Analyse geschrieben.
Oliver Alt, Autor des Buchs »Modell-basierter Systemtest von Car Multimedia Systemen mit SysML« steuerte den größten Teil von Kapitel 15 bei.
Stoff und Idee für das Kapitel »Trace-Daten im Testumfeld« kamen von Alexander Weiss, Accemic GmbH, und von Martin Leucker, Professor am Institut für Softwaretechnik und Programmiersprachen an der Universität zu Lübeck.
Johannes Bergsmann, gerichtlich vereidigter Sachverständiger und Ziviltechniker für Informatik sowie Geschäftsführer des Unternehmens Software Quality Lab, hat mich durch eine Review des Kapitels 17 unterstützt und den Großteil von Kapitel 18 geschrieben.
Die Inhalte aus Kapitel 19 zum Thema Haftung stammen aus einer Publikation, die ich im Jahr 2009 gemeinsam mit dem Heidelberger Fachrechtsanwalt Tobias Sedlmeier und zuvor genanntem Johannes Bergsmann veröffentlicht habe. Für die unabhängige Durchsicht des auf Basis dieser Publikation neu geschriebenen Kapitels danke ich dem Münchner Rechtsanwalt Christian R. Kast recht herzlich.
Eine ganze Reihe von Personen hat mich durch eine Review oder Ergänzungen des Manuskripts unterstützt. Ich freue mich, dass die folgenden von mir ausgewählten Spezialisten meiner Bitte, Teile des Buchs zu prüfen und zu ergänzen, Folge geleistet haben:
Helmut Pichler, Präsident des Austrian Testing Boards, hat die Buchpassagen mit Bezug zu ISTQB reviewt.
Markus Unterauer, Trainer und Berater für Requirements Engineering, hat das Kapitel »Anforderungen und Test« kritisch gelesen.
Gernot Salzer, Professor am Institut für Computersprachen der Technischen Universität Wien, hat meine Ausführungen zu formalen Methoden korrigiert und ergänzt. Ich gebe unumwunden zu, dass formale Methoden nicht zu meiner Kernkompetenz gehören. Dementsprechend viel Rotstift fand sich in meinem Manuskript und dementsprechend kurz ist der betreffende Abschnitt in meinem Buch. Sein Kollege Georg Weissenbacher hat diese undankbare Aufgabe bei der Überarbeitung für die zweite Auflage übernommen.
Robert Mittermayr, Promovend auf dem Gebiet der Deadlock-Analyse, unterstützte mich durch eine Review der Kapitel zu Deadlocks und Race Conditions.
Daniel Kästner, Mitbegründer der AbsInt Angewandte Informatik GmbH, ergänzte für die zweite Auflage meine Ausführungen zur statischen Data-Race-Analyse um die Technik der abstrakten Interpretation.
Renate Gutjahr, Product Managerin der PLATO AG in Lübeck, sah Kapitel 14 durch und lieferte wertvolle Ergänzungen für die Abschnitte mit Bezug zur FMEA.
Matthias Daigl von der imbus AG hat mich unterstützt, indem er die Teile der zweiten Auflage des Buchs korrigierte, die Bezug zur ISO 29119 nehmen.
Aus dem Kreis der Abonnenten meines Newsletters meldeten sich viele Testleser für einzelne Kapitel dieses Buchs; Einsteiger wie ausgewiesene Experten. Für Hinweise und Kommentare aus diesem Leserkreis danke ich Oliver Bee, Frank Büchner, Christian Fuchs, Ralf Geiger, Alfred Guszmann, Wolfgang Höllmüller, Martin Horauer, Stefan Larndorfer, Sebastian Koopmann, Reinhard Meyer, Anke Mündler, Harald Nistelberger, Rudolf Ramler, Thilo Richard, Gerald Schröder, Christian Siemers, Arnd Strube, Andreas Weigl-Pollack und Bodo Wenzel.
Meiner Frau und meinen Kindern danke ich für ihre Geduld. Viele Monate lang war ich fast jede freie Minute mit dem Schreiben des Buchs beschäftigt.
1Einleitung
1.1Motivation
1.2Abgrenzung des Buchs zu ISTQB-Lehrplänen
1.3Zur Gliederung dieses Buchs
1.4Die wichtigsten Begriffe kurz erklärt
1.4.1Definition von Fachbegriffen
1.4.2Zu Definitionen und TesterInnen
1.5Ein Überblick über das Umfeld des Software-Testing
1.5.1Ursachen von Software-Fehlern
1.5.2Warum Programmfehler nicht entdeckt werden
1.5.3Angebrachter Testaufwand
1.5.4Der Tester und der Testprozess
1.5.5Modellieren der Software-Umgebung
1.5.6Erstellen von Testfällen
1.5.7Ausführen und Evaluieren der Tests
1.5.8Messen des Testfortschritts
1.5.9Testdesign und Testdokumentation im Software-Entwicklungsprozess
1.5.10Verschiedene Teststufen und deren Zusammenspiel
1.5.11Andere Verifikationsmethoden als Ergänzung zum Test
1.5.12Agile Prozessmodelle
1.5.13Der Software-Test in agilen Vorgehensmodellen
1.5.14Wer testet die Tester?
2Anforderungen und Test
2.1Die Bedeutung textueller Anforderungen
2.2Requirements Engineering im Projekt
2.3Arten und Quellen von Anforderungen
2.4Warum Anforderungen dokumentiert werden sollen
2.5Die Review von Anforderungen
2.5.1Testbarkeit von Anforderungen
2.5.2Modifizierbarkeit und Erweiterbarkeit
2.5.3Relevanz von Anforderungen
2.6Der Umgang mit natürlicher Sprache
2.6.1Einfache Sprache gegen Missverständnisse
2.6.2Gelenkte Sprache
2.7Hinweise zur Dokumentenform
2.8Die Spezifikation an der Schnittstelle zum Testteam
2.8.1Konfiguration von Testdesigns
2.8.2Vollständigkeit von Spezifikationen
2.9Werkzeuge zur Review von Anforderungen
2.10Diskussion
2.10.1Verifikation beim Requirements Engineering mit Augenmaß
2.10.2Bewertung der Rolle des Requirements Engineering für den Testprozess
2.11Fragen und Übungsaufgaben
3Review des Designs
3.1Ziele der Review des Architekturdesigns
3.2Ziele der Review des Detaildesigns
3.3Eigenschaften von gutem Software-Design
3.4Hinweise zur Architektur-Design-Review
3.5Embedded Design
3.5.1Sicherheit, Verfügbarkeit & Co
3.5.2Wartbarkeit des Geräts
3.5.3Ressourcenverbrauch
3.5.4Design von Echtzeitsystemen
3.6Diskussion
3.7Fragen und Übungsaufgaben
4Automatische statische Code-Analyse
4.1Motivation zum Einsatz von Analysewerkzeugen
4.2Techniken von Analysewerkzeugen im unteren Preissegment
4.2.1Sprachspezifische Fallstricke
4.2.2Kontrollflussanalyse
4.2.3Datenflussanalyse, Initialisation Tracking
4.2.4Datenflussanalyse, Value Tracking
4.2.5Semantische Analyse
4.2.6Starke Typenprüfung
4.3Techniken von Analysewerkzeugen im oberen Preissegment
4.3.1Größerer Komfort für den Benutzer
4.3.2Concurrency Checks
4.3.3Stack-Analyse und erweiterte Kontrollflussanalyse
4.3.4Erschöpfende Analyse des Zustandsbaums
4.4Statische Security-Analyse (SSA)
4.5Code-Metriken
4.6Werkzeuge für die Automatische Code-Analyse
4.7Diskussion
4.8Fragen und Übungsaufgaben
5Code-Reviews
5.1Review-Arten
5.1.1Code-Inspektionen
5.1.2Walkthrough
5.1.3Peer-Review
5.2Pair Programming
5.3Werkzeuge zur Code-Review
5.4Diskussion
5.5Fragen und Übungsaufgaben
6Unit-Tests
6.1Der Unit-Test im Entwicklungsprozess
6.2Zur Definition von Unit-Test und Modultest
6.3Black-Box-Testfälle beim White-Box-Test
6.3.1Äquivalenzklassenbildung
6.3.2Grenzwertanalyse
6.3.3Andere Methoden
6.4Stubs und Treiber
6.5Verschiedene Typen von Werkzeugen beim White-Box-Test
6.5.1Unit-Test-Frameworks
6.5.2Werkzeuge zur Testerstellung
6.5.3Werkzeuge zur Messung der Testabdeckung
6.6Testabdeckung
6.6.1Statement Coverage
6.6.2Branch Coverage und Decision Coverage
6.6.3Decision/Condition Coverage
6.6.4Modified Condition/Decision Coverage
6.6.5Andere Testabdeckungen
6.6.6Testabdeckung bei modellbasierter Entwicklung
6.6.7Messung der Testabdeckung
6.7Basis Path Testing
6.8Host oder Target Testing?
6.9Den Code immer unverändert testen?
6.10Unit-Tests bei objektorientierten Sprachen
6.11Grenzen des Unit-Tests
6.12Werkzeuge für den Unit-Test
6.12.1Unit-Test-Frameworks
6.12.2Werkzeuge zur Testerstellung
6.12.3Coverage-Analyse
6.13Diskussion
6.13.1Testabdeckung
6.13.2Organisation von Unit-Tests
6.14Fragen und Übungsaufgaben
7Integrationstests
7.1Software/Software-Integrationstest
7.1.1Bottom-up-Unit-Tests als Integrationstest
7.1.2Strukturierter Integrationstest
7.1.3Testabdeckung der Aufrufe von Unterprogrammen
7.1.4Vergleich der Teststrategien
7.1.5Grenzen des Software/Software-Integrationstests
7.1.6Diskussion des Software/Software-Integrationstests
7.2Ressourcentests
7.2.1Statischer Ressourcentest
7.2.2Dynamischer Ressourcentest
7.3Hardware/Software-Integrationstest
7.3.1Bottom-up-Verfahren
7.3.2Regressionsverfahren
7.3.3Black-Box-Verfahren
7.3.4Test und Analysen bei Sicherheitsrelevanz
7.3.5Diskussion des Hardware/Software-Integrationstests
7.4Systemintegrationstest
7.5Werkzeuge für den Integrationstest
7.6Fragen und Übungsaufgaben
8Systemtests
8.1Funktionale Systemtests
8.1.1Zuordnung funktionaler Systemtests zu Anforderungen
8.1.2Äquivalenzklassen und Grenzwerte im Black-Box-Test
8.1.3Zustandsbasierter Test
8.1.4Ursache-Wirkungs-Analyse
8.1.5CECIL-Methode
8.1.6Entscheidungstabellentechnik
8.1.7Paarweises Testen und Klassifikationsbaum-Methode
8.1.8Back To Back Testing
8.1.9Erfahrungsbasierter Test
8.1.10Diskussion des Black-Box-Tests
8.1.11Auswahl eines Black-Box-Testverfahrens für eine Aufgabe
8.1.12Werkzeuge für Funktionstests
8.2Test der Benutzerschnittstelle
8.2.1Grafische Benutzerschnittstelle
8.2.2Werkzeuge für GUI-Tests
8.2.3Eingebettete Benutzerschnittstellen
8.2.4Werkzeuge für den Test von eingebetteten Benutzerschnittstellen
8.3Performanztest und Lasttest
8.4Stresstest
8.5Volumentest
8.6Failover und Recovery Testing
8.7Ressourcentests
8.8Installationstests
8.9Konfigurationstests
8.10Security-Tests
8.11Dokumententests
8.12Testumgebung und Testdaten
8.13Formale Methoden
8.13.1Symbolischer Test
8.13.2Deduktive Verifikation von funktionalen Anforderungen
8.13.3Model Checking
8.14Automation von Systemtests
8.14.1Vor- und Nachteile der Testautomation
8.14.2Tipps zur Automation von Systemtests
8.15Dokumentation des Testdesigns und der Testergebnisse
8.16Grenzen des Systemtests
8.17Fragen und Übungsaufgaben
9Testen von RTOS und Middleware
9.1Definition und Motivation
9.2White-Box-Requirements-Test
9.3Test eines Interrupt-Managers
9.4Test eines Schedulers
9.5Fragen und Übungsaufgaben
10Race Conditions
10.1Definition von Data Races
10.2Dynamische Data-Race-Analyse
10.2.1Eraser
10.2.2Lamports Happens-Before-Relation
10.3Statische Data-Race-Analyse
10.3.1Ansätze zur statischen Data-Race-Analyse
10.3.2Vergleich zur dynamischen Data-Race-Analyse
10.4Werkzeuge für die Data-Race-Analyse
10.5Diskussion
10.6Fragen und Übungsaufgaben
11Deadlocks
11.1Über die Entstehung von Deadlocks
11.2Verschiedene Arten der Deadlock-Analyse
11.3Dynamische Deadlock-Analyse
11.4Statische Deadlock-Analyse
11.5Werkzeuge zur Deadlock-Detektion
11.6Diskussion
11.7Fragen und Übungsaufgaben
12Echtzeit-Verifikation
12.1Antwortzeiten bei funktionalen Tests
12.2WCET-Analyse
12.2.1Problemstellung
12.2.2Laufzeitanalyse
12.3Werkzeuge für die WCET-Analyse
12.4Diskussion
12.5Fragen und Übungsaufgaben
13Schedulability-Analyse
13.1Aufgaben der Schedulability-Analyse
13.2Definitionen
13.3Diskussion der Scheduling-Strategien
13.3.1Statisches Scheduling
13.3.2Dynamisches Scheduling
13.4Analyse bei Fixed-Priority-Single-CPU-Systemen
13.4.1Optimale Prioritätsvergabe
13.4.2Rate Monotonic Analysis
13.4.3Exakte Antwortzeitenanalyse
13.4.4Gegenseitiger Ausschluss
13.4.5Aperiodische Aufgaben
13.4.6Kontextwechsel
13.4.7Cache und Out Of Order Execution
13.4.8Input-Jitter
13.4.9Interrupts
13.5Multi-CPU-Systeme
13.5.1Multicore- und Multiprozessor-Systeme
13.5.2Verteilte Systeme
13.6Scheduling-Analyse für CAN
13.7Werkzeuge
13.8Diskussion
13.9Fragen und Übungsaufgaben
14Hardware/Software-Interaktionsanalyse
14.1Die FMEA als Grundlage der HSIA
14.2Die HSIA als Quelle für Software-Anforderungen
14.3Software-Kritikalitätsanalyse
14.4Software-FMEA
14.5Werkzeuge
14.6Diskussion
14.7Fragen und Übungsaufgaben
15Modellbasierter Test
15.1Begriffsdefinition
15.2MBT und Testautomation
15.3Modelle
15.3.1Statecharts
15.3.2SDL
15.3.3Message Sequence Charts
15.3.4UML Version 2
15.3.5SysML
15.3.6Funktionsmodellierung
15.4Testmodell vs. Implementierungsmodell
15.5Werkzeuge
15.6Diskussion
15.7Fragen und Übungsaufgaben
16Trace-Daten im Testumfeld
16.1Das Dilemma mit instrumentiertem Code
16.2Embedded-Trace-Schnittstellen
16.3Werkzeuge
16.4Diskussion
17Testmanagement
17.1Testplanung
17.2Teststeuerung
17.3Abweichungsmanagement
17.4Bewertung und Anpassung des Testprozesses
17.4.1Formale Reifegradmodelle für den Software-Test
17.4.2Prozessbewertung in agilen Projekten
17.4.3Mit Augenmaß ins Kostenoptimum
17.5Risikobasierter Test
17.6Werkzeuge
17.7Diskussion
17.8Fragen und Übungsaufgaben
18Qualitätsmanagement
18.1Definition
18.2Qualitätsmanagement-Standards
18.3Kosten und Haftungsrelevanz des QM
18.4Umsetzung des Qualitätsmanagements
18.5Die Rolle des Qualitätsmanagers
18.6Mit Metriken die Qualität steuern
18.7Die Wirtschaftlichkeit von QM
18.8Werkzeuge
18.9Diskussion
18.10Fragen und Übungsaufgaben
19Software-Test und Haftungsrisiko
19.1Ein Software-Fehler im Sinne des Gesetzes
19.2Vertragliche Gewährleistung und Haftung
19.3Vertragliche Beschränkung der Haftung
19.4Produzentenhaftung bei Software
19.5Produkthaftung
19.6Sorgfaltspflicht des Software-Herstellers
19.7Technische Normen mit Bezug zum Software-Test
19.7.1DIN IEC 56/575/CD
19.7.2IEEE Std 1012
19.7.3IEEE Std 829
19.7.4IEEE Std 1008-1987
19.7.5ISO/IEC 29119
19.7.6IEC/EN 61508
19.7.7ISO 26262
19.7.8Normenreihe 250XX
19.8Tipps vom Rechtsanwalt und vom Techniker
19.9Fragen und Übungsaufgaben
Nachwort
Anhang
Anhang A – Lösungen zu den Übungsaufgaben
Anhang B – Dokumentation des Testdesigns
Anhang C – Software-Verifikationsplan
Anhang D –Software-Verifikationsreport
Quellenverzeichnis
Index
Fast jeder fortgeschrittene Programmierer hat ein oder mehrere Bücher über Programmiersprachen und Software-Entwicklung gelesen. Bücher über das Testen von Software stehen aber weit weniger oft in den Regalen. Das liegt vermutlich unter anderem am hartnäckigen Gerücht, dass Testen von Software langweilig sei. Um diesem Gerücht entschieden entgegenzutreten, ist dieses Kapitel geschrieben worden. Es soll ein Appetitanreger auf die im Buch behandelten Testthemen sein, beschreibt die Eingliederung des Tests in den Software-Entwicklungsprozess und analysiert zunächst einmal den Feind: den Software-Fehler. Doch zuvor noch ein paar Worte zur Motivation des Software-Tests, zur Eingliederung dieses Buchs in andere Literatur und ein paar Definitionen.
Fehler in der Software eingebetteter Systeme können teure Rückholaktionen zur Folge haben. Selten ist es den Anbietern von eingebetteten Systemen möglich, einfach einen Bugfix per E-Mail zu verschicken und wieder dem Tagesgeschäft nachzugehen. Daher sollte man in Branchen mit hoher Anforderung an die Software-Integrität erstens besonders bedacht sein, Software-Fehler zu vermeiden, und zweitens, gemachte Fehler zu erkennen. Punkt eins zielt auf die Prozesslandschaft, die Qualifikation der Mitarbeiter und die Unternehmensstruktur ab. Er betrachtet also, wie sehr das Talent oder – viel wichtiger – das fehlende Talent eines Mitarbeiters die Qualität des Produkts beeinflussen kann. Punkt zwei heißt, die Software und begleitende Dokumente sorgfältig zu verifizieren. Solche Dokumente können zum Beispiel die Anforderungsdefinition, Analysen der zu erwartenden CPU-Last oder das Design festhalten.
Leider wurde lange Zeit nicht nur im deutschsprachigen Raum das Thema Verifikation von Software, wozu auch Testen gehört, wenig an Hochschulen gelehrt. Eine Konsequenz daraus ist, dass Vertreter der Industrie das International Software Testing Qualifications Board (ISTQB) ins Leben gerufen haben, das eine »Certified Tester«-Ausbildung definiert. Der Inhalt des vorliegenden Buchs deckt sich nicht mit den Lehrplänen des ISTQB. In diesem Buch werden Themen genauer als durch das ISTQB behandelt, wenn sie für Embedded-Software besonders wichtig sind, und es werden Methoden präsentiert, die für eingebettete Software wichtig sein können, sich aber zurzeit nicht in den ISTQB-Lehrplänen befinden. Ebenso werden Themen der ISTQB-Lehrpläne hier nicht behandelt, wenn sie nicht technischer Natur sind oder nur Multisysteme oder reine Business-Anwendungen betreffen.
Das Buch ist für Personen ohne Vorwissen aus dem Bereich Software-Testing geschrieben. Absolventen der ISTQB-Certified-Tester-Lehrgänge werden im vorliegenden Buch daher viel Bekanntes wiederfinden und aus oben beschriebenen Gründen trotzdem ebenso viel Neues erfahren.
Die technischen Grundlagenkapitel dieses Buchs orientieren sich dabei am zeitlichen Verlauf eines Projekts. Das heißt, auch wenn das wichtigste Thema dieses Buchs der Test ist, handeln die ersten der folgenden Kapitel noch nicht vom Test, denn am Anfang eines Projekts gibt es zunächst noch keine Software, die man testen könnte. Wohl aber gibt es schon Dokumente (bei phasenorientierten Projekten) oder Vorgänge (bei agilen Vorgehensweisen), für die ein Tester einen Beitrag zur Software-Qualität leisten kann.
Kapitel 2 beschreibt, wie dieser Beitrag bei der Review von Anforderungstexten aussehen kann. Kapitel 3 beschreibt kurz die möglichen Verifikationsschritte beim Design. In den Kapiteln 4 und 5 wird beschrieben, wie Code-Reviews durchgeführt werden können und wie Werkzeuge funktionieren, die teilweise oder gänzlich automatisch Review-Aufgaben übernehmen können.
Dann erst geht es mit dem Testen los. In Kapitel 6 werden Unit-Tests, in Kapitel 7 Integrationstests und in Kapitel 8 Systemtests beschrieben. Bei Tests von Middleware können diese Teststufen alle stark verschwimmen, wie Kapitel 9 zeigt. Im Anschluss daran beschäftigt sich Kapitel 10 mit einer Art von Fehler, die nur durch Zufall in den zuvor beschriebenen Tests gefunden werden kann: Race Conditions. Das Kapitel zeigt, wie sich Data Races zuverlässig auffinden lassen, gefolgt von einem verwandten Thema: Kapitel 11 zeigt, wie sich Deadlocks automatisch auffinden lassen.
Das darauf folgende Kapitel 12 beschreibt Verfahren zur Bestimmung der maximalen Ausführungszeit von Code. Das Ergebnis kann ein wichtiger Beitrag für die Schedulability-Analyse sein, die in Kapitel 13 behandelt wird.
Spätestens nach diesem Kapitel hält sich die Reihung der weiteren Kapitel nicht mehr an den zeitlichen Verlauf eines Projekts. Die nun folgenden Kapitel sind auch weit weniger umfangreich. In Kapitel 14 wird die Hardware/Software-Interaktionsanalyse vorgestellt, die auf Produkt/System-Ebene stattfindet. Mit einem kurzen Kapitel 15 über modellbasierten Test und einem technischen Ausblick in Kapitel 16 verlässt das Buch das technische Terrain.
In Kapitel 17 werden Hinweise für das Testmanagement gegeben und Kapitel 18 beschreibt die Aufgaben und möglichen Vorgehensweisen des Qualitätsbeauftragten. Auch diese beiden Kapitel sind bewusst kurz gehalten und geben eher nützliche Tipps, als dass man lange Abhandlungen darin findet, denn zu diesen Themen gibt es jede Menge Spezialliteratur. Das Kapitel 19 widmet sich dem Thema Haftung: In welchem Maß ist ein Programmierer oder ein Tester für Fehler haftbar? Dort erfahren Sie es.
Die meisten Kapitel schließen mit einem Fragenkatalog und Übungsaufgaben zur Kontrolle des Lernziels. Am Ende des Buchs finden Sie Lösungen dazu und Quellenverzeichnisse für referenzierte Literatur.
Die ISO 29119-1 und das ISTQB-Glossary of Terms definieren eine ganze Reihe von Fachwörtern rund ums Testen. In Einzelfällen sind sie allerdings nicht übereinstimmend. Dabei ist zu erwarten, dass das ISTQB-Glossar früher oder später an die ISO 29119-1 angepasst wird. Wenn man in einem Unternehmen Dinge rund um das Thema Software-Qualität benennen möchte, ist man gut beraten, sich an diesen Definitionen zu orientieren. Das ISTQB-Glossar kann man im WWW nachschlagen, siehe [URL: ISTQB] für die englische Fassung und [URL: ISTBQ/D] für die deutschsprachige, die ISO-Norm ist kostenpflichtig.
Es ergibt nicht viel Sinn, diese Definitionen hier zu kopieren. Stattdessen enthält die folgende Aufstellung die wichtigsten Begriffe, die im vorliegenden Buch Verwendung finden, unmittelbar gefolgt von der Definition aus dem ISTQB-Glossar und einer kurzen Ergänzung:
Agile Software-Entwicklung ist eine auf iterativer und inkrementeller Entwicklung basierende Gruppe von Software-Entwicklungsmethoden, wobei sich Anforderungen und Lösungen durch die Zusammenarbeit von selbstorganisierenden funktionsübergreifenden Teams entwickeln.
Der mit großem Abstand bedeutendste Vertreter agiler Entwicklungsmodelle ist Scrum, gefolgt von Extreme Programming. Speziell in Projekten mit begrenzter Größe und nur vage definierten Anforderungen haben diese Entwicklungsmodelle ihre Berechtigung. Diese »agilen Methoden« kommen in Reinform ohne Projektleiter aus. Die Teams sind selbstorganisierend.
Audit: Ein unabhängiges Prüfen von Software-Produkten und -prozessen, um die Konformität mit Standards, Richtlinien, Spezifikationen und/oder Prozeduren basierend auf objektiven Kriterien zu bestimmen, einschließlich der Dokumente, die (1) die Gestaltung oder den Inhalt der zu erstellenden Produkte festlegen, (2) den Prozess der Erstellung der Produkte beschreiben (3) und spezifizieren, wie die Übereinstimmung mit den Standards und Richtlinien nachgewiesen beziehungsweise gemessen werden kann.
Ein Audit führt also ein externer Fachmann durch, der sich nicht nur das Produkt ansieht, sondern auch und vor allem den Entstehungsprozess des Produkts. Ein Auditor prüft, ob ein Unternehmen ein Prozessumfeld schafft, das die Wahrscheinlichkeit von guter (beziehungsweise angepasster) Software-Qualität maximiert.
Validierung ist die Bestätigung durch Bereitstellung eines objektiven Nachweises, dass die Anforderungen für einen spezifischen beabsichtigten Gebrauch oder eine spezifische beabsichtigte Anwendung erfüllt worden sind.
Wer diese Definition aus der deutschen Version des ISTQB-Software-Testing-Glossars beim ersten Durchlesen versteht, gewinnt einen Preis. Weiter auf Deutsch übersetzt könnte man sagen: Validierung bestätigt, dass das Produkt, so wie es vorliegt, seinen beabsichtigten Verwendungszweck erfüllen kann. Validierung stellt also sicher, dass »das richtige Ding erzeugt wird«. Etwas weniger streng definierte die nun abgelöste IEEE 829-2008 diesen Begriff und verstand Validierung einfach als Nachweis der Erfüllung der Anforderungen.
Verifikation ist die Bestätigung durch Bereitstellung eines objektiven Nachweises, dass festgelegte Anforderungen erfüllt worden sind.
Das IEEE Glossary of Software Engineering Terminology [IEEE 610.12] beschränkt den Begriff nicht auf Anforderungen, sondern bezieht ihn auf Entwicklungsphasen: »Verifikation ist die Prüfung eines Systems oder einer Komponente, mit dem Ziel zu bestimmen, ob die Produkte einer Entwicklungsphase die Vorgaben erfüllen, die zum Start der Phase auferlegt wurden.« Verifikation subsumiert gemäß IEEE also alle Techniken, die sicherstellen, dass man »das Ding richtig erzeugt«. Zu diesen Techniken gehören der Test des Produkts, Reviews, die Sicherstellung eines Zusammenhangs von Design, Anforderungen und Tests (Traceability) sowie Audits [PSS-05-0].
Im allgemeinen Sprachgebrauch kann man ein Ding nicht testen, das es noch nicht gibt. Das ISTQB-Glossar hat eine Definition des Begriffs Testen, der dem allgemeinen Sprachgebrauch widerspricht:
Test: Der Prozess, der aus allen Aktivitäten des Lebenszyklus besteht (sowohl statisch als auch dynamisch), die sich mit der Planung, Vorbereitung und Bewertung eines Software-Produkts und dazugehöriger Arbeitsergebnisse befassen. Ziel des Prozesses ist sicherzustellen, dass diese allen festgelegten Anforderungen genügen, dass sie ihren Zweck erfüllen, und etwaige Fehlerzustände zu finden.
Bei dieser Definition subsumiert der Begriff Test Aktivitäten, die in der älteren Definition von IEEE der Verifikation zugeordnet werden, und enthält auch Planungsschritte für das Software-Produkt. So weit gefasst ist dann fast alle Projektarbeit, außer der Produktentwicklung selbst, ein Test.
In diesem Buch wird, so wie bei der Definition von IEEE, dann vom Testgesprochen, wenn das Produkt Software, zumindest in Teilen, Gegenstand des Tests ist. Alle Schritte zur »Bewertung eines Software-Produkts und dazugehöriger Arbeitsergebnisse« davor werden aber nicht »Test« genannt, damit dem allgemeinen Sprachgebrauch und den IEEE-Standards nicht widersprochen wird.
Ansonsten entspricht die Verwendung von Fachwörtern in diesem Buch den Definitionen des ISTQB-Glossars und der ISO 29119-1. Und Hand aufs Herz: Ob man die Review dem Test (wie ISTQB) oder der Verifikation (wie IEEE) zuordnet, ist wohl weniger wichtig, als dass man sie ordentlich macht.
Mit der Niederschrift der Definition der verwendeten Fachbegriffe zu Beginneines Dokuments sehen Sie eine Praxis, die auch im Umfeld der Software-Entwicklung gut aufgehoben ist und in einschlägigen Standards so empfohlen wird, zum Beispiel [IEEE 829]. Welche Zeitverschwendung, wenn Sie als Leser einen Begriff anders verstehen als der Autor, aber erst im Laufe des Lesens dahinter kommen und deshalb zum besseren Verständnis die ersten Passagen des Buchs noch einmal lesen müssen!
Apropos Missverständnis: Wenn in diesem Buch vom Beruf des Testers oder von anderen Rollen in der Software-Entwicklung gesprochen wird, so wird immer die männliche Form verwendet. Dies soll nur der Leserlichkeit dienen, aber in keiner Weise die Frauen diskriminieren. Ein Trost für alle Leserinnen: Wahre Top-Experten nennt man Koryphäen, auch wenn es Männer sind. Und zum Wort »Koryphäe« gibt es keine männliche Form.
In diesem Teil der Einleitung wird das Umfeld des Software-Tests erörtert und ein Überblick über Möglichkeiten und Grenzen des Testens gegeben. Für das Verstehen der späteren Kapitel ist das Lesen nicht notwendig, weil große Teile von Abschnitt 1.5 redundant zum Inhalt der vertiefenden Kapitel sind. Lesern, die sich schon mit dem Thema Test auseinandergesetzt haben und die wissen, wie sie eine Brücke vom V-Modell zu agilen Methoden schlagen können, wird daher empfohlen, bei Kapitel 2 weiterzulesen.
Ohne Zweifel helfen die folgenden Seiten aber Neueinsteigern, die später vorgestellten Methoden im Software-Entwicklungsprozess besser einzuordnen. Und – wie gesagt – diese Seiten sind ein Appetitanreger auf das, was später noch im Buch behandelt wird.
Der Protagonist schlechthin im Umfeld des Software-Tests ist der Software-Fehler. Als Einstieg in das Thema Testen werden wir daher zunächst seine möglichen Ursachen untersuchen.
Warum hat Software überhaupt Fehler? Die einfachste Antwort auf diese Frage ist, dass Software von Menschen geschrieben wird, und Menschen machen nun einmal Fehler. Wenn die Antwort auf eine komplexe Frage sehr einfach ist, dann übersieht sie meistens viele Facetten des zugrunde liegenden Problems. So auch in diesem Fall. Viele Software-Fehler, die sehr viel Geld kosteten, waren alles andere als einfache Programmierfehler. Die folgende Aufzählung skizziert einige typische, aber sehr unterschiedliche Ursachen für Fehler in Software.
Fehlerhafte Kommunikation oder keine Kommunikation bei der Anforderungsspezifikation
. In einem Projekt würde das bedeuten, dass nie ganz genau klar war, was die Software tun soll und was nicht. Oder, noch tückischer: Auftraggeber und Entwickler verstehen die Niederschrift der Anforderung unterschiedlich und sind sich der Möglichkeit einer anderen Interpretation gar nicht bewusst.
Psychologische oder kulturelle Gründe
können Auslöser für Kommunikationsprobleme sein: Manchen Personen fällt es schwer zuzugeben, wenn sie die Aufgabenstellung nicht verstehen. In manchen Kulturkreisen ist es üblich, aus Höflichkeit so zu tun, als verstünde man alles. Nicht selten hört man von euphorischen Verkäufern, die dem Kunden Produkteigenschaften zusichern, deren Realisierung nicht oder nur teilweise möglich ist. Mit Recht reklamiert der Kunde dann die entstehende Abweichung als Fehler.
Sich ändernde Anforderungen
. In welcher Softwareversion ist welche Version welcher Anforderung realisiert? Welche Tests müssen aufgrund einer Änderung modifiziert, welche Tests neu durchlaufen werden?
Softwarekomplexität
. Applikationen benutzen Module von Zulieferern oder anderen Projekten, bedienen sich komplizierter Algorithmen, unterstützen eine Vielzahl von Plattformen und so weiter. In großen Projekten können wenige Entwickler behaupten, die von ihnen erzeugte Software in allen Details zu verstehen.
Zeitdruck
. Entwicklungszeitpläne beruhen alle auf Aufwandsschätzungen. Wenn man hier sehr daneben lag und der Abgabetermin näher rückt, dann ist Eile angesagt. Zeitdruck ist ein perfekter Nährboden für Fehler.
Schlecht dokumentierter Code
. Der Programmierer, dessen Code im neuen Projekt wiederverwendet werden muss, war kein Freund der Dokumentation. Das Programm war für ihn schwer zu schreiben. Aus seiner Sicht ist es daher zumutbar, wenn auch die Dokumentation schwer zu lesen ist.
Programmierfehler
. Programmierer sind auch nur Menschen und machen Fehler im Software-Design oder bei der Umsetzung des Designs.
Ein Software-Fehler hat also viele verschiedene Ursachen. Tests sind nur geeignet, klassische Programmier- und Designfehler zu finden und sind bei allen, bis auf die letztgenannte Fehlerursache ein vergleichsweise wirkungsloses Instrument. Wenn zum Beispiel ein Kommunikationsproblem vorliegt und daher gegen eine falsche Anforderungsspezifikation getestet wird, dann nützt der gewissenhafteste Test nichts. Bis auf den Programmierfehler kann man aber allen anderen genannten Fehlerursachen durch Methoden des Managements begegnen.
Mit dem Wissen, dass Testen nur eine von vielen Maßnahmen im Kampf gegen Software-Fehler ist, nehmen wir nun den Programmierfehler, den Software-»Bug«, genauer ins Visier und erörtern, warum es so schwierig ist, alle Bugs zu finden. Die Bezeichnung Bug stammt übrigens laut Gerüchteküche von einer Motte, die auf einer Speicherplatine des Computers eines Zerstörers der US-Navy landete. Der resultierende Kurzschluss grillte nicht nur das unglückliche Insekt, sondern führte auch zu einer Fehlfunktion des Computers. Seitdem werden Software-Fehler nach dem Insekt benannt.
Vielen Software-Entwicklern ist Folgendes nicht unbekannt: Der Kunde meldet einen Programmierfehler, obwohl unzählige Stunden mit gewissenhafter Code-Review verbracht wurden, obwohl tagelang getestet wurde. Wie konnte dieser Fehler unbemerkt das Haus verlassen?
Unter der Annahme, dass sich der Kunde nicht irrt, kann einer der folgenden Punkte diese Frage beantworten:
Der Kunde führte Programmteile aus, die noch nie getestet wurden
. Entweder absichtlich (bei Zeitdruck oder Kostendruck) oder durch Unachtsamkeit wurden Programmteile nicht oder unzureichend getestet.
Die Reihenfolge, in der der Kunde Programmanweisungen ausführte, ist anders als die Reihenfolge, in der die Anweisungen getestet wurden
. Die Reihenfolge kann aber über Funktion und Fehler entscheiden.
Der Kunde verwendete eine Kombination von Eingangsgrößen, die nie getestet wurden
. Software wird in den seltensten Fällen mit allen möglichen Eingangsgrößen getestet. Der Tester muss daher eine geringe Zahl von Kombinationen selektieren und daraus schließen, dass die anderen Kombinationen auch funktionieren. Wenn dieser Schluss falsch ist, rutscht der Fehler durch.
Die operative Umgebung der Software ist beim Kunden eine andere
. Der Kunde verwendet eine andere Betriebssystemversion oder eine andere Hardware. Vielleicht stand dem Testteam die Anwendungsumgebung überhaupt nicht zur Verfügung und man musste diese simulieren oder von Annahmen ausgehen.
Software wird fast nie zu 100 % getestet. Das gilt auch für sicherheitskritische Anwendungen. [Hayhurst 01] beschreibt zum Beispiel, dass Flugkontrollsoftware bis zu 36 verschiedene Eingangsgrößen verarbeitet. Wollten wir alle möglichen Eingangskombinationen durchtesten und damit beweisen, dass keine ungewollten Wechselbeziehungen zwischen den Eingängen bestehen, so müssten wir 21 Jahre lang testen, selbst wenn wir pro Sekunde 100 Testfälle erstellen und durchführen könnten. In Kapitel 6 werden Techniken vorgestellt, die durch Analyse des Quellcodes den Testaufwand dramatisch reduzieren und trotzdem die Testschärfe nur gering beschneiden.
Die Aufgabe des Testers ist es nun, mit den vorhandenen Ressourcen so zu testen, dass er mit größter Wahrscheinlichkeit alle Fehler findet, die in der Software stecken. Kapitel 8 wird dazu viele Techniken vorstellen. Die Aufgabe des Managements ist, dem Tester Ressourcen so zu genehmigen, dass der maximale Projektgewinn resultiert. Abbildung 1–1 zeigt dazu die anzustellende, wirtschaftliche Überlegung. Wird zu wenig gestestet und drohen dem Unternehmen daher Schadenersatzzahlungen oder Imageverlust, dann ist der Testaufwand zu erhöhen. Wird andererseits zu viel getestet, dann ist das Software-Produkt zwar vielleicht von guter Qualität, aber nicht mehr wirtschaftlich zu erzeugen.
Die Entscheidung, wie viel Aufwand in den Test zu stecken ist, ist eine rein wirtschaftliche und stützt sich im Idealfall auf sogenannte Prozessmetriken. Derartige Metriken erfassen beispielsweise wie viel Zeit (und damit Geld) es kostet, einen Fehler zu finden, und wie viel es kostet, einen Fehler nicht zu finden. Prozessmetriken sind ein wichtiges Werkzeug der Wirtschaftlichkeitsanalyse und des Software-Qualitätsmanagements.
Abb. 1–1Der Testaufwand sollte sich am Betriebsgewinn orientieren.
Bei der Erstellung von Testfällen muss der Tester die Software, ihre Funktionalität, die Eingangsgrößen, die möglichen Kombinationen der Eingangsgrößen und die Testumgebung berücksichtigen. Dieser Prozess ist kein Kinderspiel, benötigt Zeit, Erfahrung und Planung. In der Zeitskala dieser Planung muss auch Zeit vorgesehen werden, die Testfälle zu revidieren, gefundene Bugs zu entfernen und die Software von Neuem zu testen. Im Zeitplan nur den Wonnefall vorzusehen – alles funktioniert klaglos, das Testfalldesign ist fehlerfrei –, ist ein Fehler, der Anfängern vorbehalten bleiben soll.
Vom Tester wird destruktive Kreativität verlangt, wenn seine Tests auch trickreiche Bugs finden sollen. Je mehr Freude der Tester am Finden von Fehlern hat, desto mehr wird er sich anstrengen, auch tatsächlich welche zu finden. Wenig Freude bereitet es, seine eigenen Fehler zu finden, und so ist eine der Grundregeln des Testens, dass Programmautor und -tester verschiedene Personen sein müssen. Glenford Myers, der erste nennenswerte Autor von Literatur über Software-Tests, schreibt dazu folgenden Absatz [Myers 78]:
»Testen ist ein destruktiver Prozess. Man versucht die Software zu brechen, ihre Schwachpunkte zu finden, Fehler aufzudecken. Es ist sehr schwierig für einen Programmierer, nachdem er während des Designs und des Programmierens konstruktiv war, plötzlich seine Perspektive zu ändern und eine destruktive Haltung gegenüber dem Programm einzunehmen. Aus diesem Grund können die meisten Programmierer ihre eigene Software nicht effektiv testen, weil sie es nicht schaffen, diese destruktive Haltung einzunehmen.«
Um den Testprozess genauer zu beschreiben, unterteilt ihn James Whittaker in einem sehr gelungenen Überblicksartikel in vier Phasen [Whittaker 00]:
Modellieren der Software-Umgebung
Erstellen von Testfällen
Ausführen und Evaluieren der Tests
Messen des Testfortschritts
Diese Phasen und die damit verbundenen Probleme und Lösungsansätze wollen wir uns nun genauer ansehen.
Eine der Aufgaben des Testers ist es, die Interaktion der Software mit ihrer Umgebung zu prüfen und dabei diese Umgebung zu simulieren. Das kann eine enorme Aufgabe sein, wenn man die Vielfalt von Schnittstellen bedenkt:
Die
klassische Mensch/Maschine-Schnittstelle
: Tastatur, Bildschirm, Maus. Der Tester muss sich überlegen, wie er alle erwarteten und unerwarteten Mausklicks, Tastatureingaben und Bildschirminhalte in den Tests organisiert. Dabei können ihn Capture/Replay-Tools unterstützen, die diese Eingaben simulieren und die resultierende Bildschirmdarstellung mit einer gespeicherten Soll-Darstellung vergleichen. Der Einsatz solcher Tools ist mit einer nicht zu unterschätzenden Lernkurve verbunden. Billige Tools haben obendrein das Problem, dass man bei einem Wechsel der GUI-Version oder des Betriebssystems oft auch gleich viele Tool-Aufzeichnungen wiederholen muss.
Das Testen der
Schnittstellen zur Hardware
kann eine Herausforderung für sich sein. Beim Test von eingebetteten Systemen muss oft erst ein Testgerät entwickelt beziehungsweise gekauft werden, damit die zu testende Software in ihrer Zielhardware auch getestet werden kann (
Hardware in the Loop
). Für die auf diesen Schnittstellen basierenden Kommunikationsprotokolle muss der Tester erwartete und unerwartete, gültige und ungültige Daten oder Kommandos versenden.
Kapitel 8
zeigt Testtechniken dazu und
Kapitel 14
stellt eine ergänzende Analysetechnik vor.
Die
Schnittstelle zum Betriebssystem
sollte ebenfalls Gegenstand von Tests sein. Wenn die zu testende Software einige Dienste des Betriebssystems in Anspruch nimmt, dann muss auch geprüft werden, was passiert, wenn das Betriebssystem diese Dienste verweigert: Was ist, wenn das Speichermedium voll ist oder der Zugriff darauf misslingt? Um das ohne Kenntnis des Codes zu testen, könnte man beispielsweise Werkzeuge des Security-Testings verwenden, die die zu testende Software in einer Betriebssystem-Simulation laufen lassen [
Whittaker 03
]. In dieser Simulationsumgebung kann man dann zum Beispiel per Knopfdruck eine volle Festplatte simulieren. Manche sprechen in diesem Zusammenhang auch von
Sandbox Testing
.
Auch
Dateisystem-Schnittstellen
findet man bei einigen eingebetteten Systemen. Der Tester muss Dateien mit erlaubtem und unerlaubtem Inhalt und Format bereitstellen.
Es ist unschwer zu erkennen, dass die Modellierung der Systemschnittstellen ein sehr aufwändiges Projekt werden kann. Stellen wir uns zum Beispiel Software für ein Motorsteuergerät in einem Kraftfahrzeug vor: Manche Prozesse im Motor und Interaktionen mit anderen Steuergeräten (wie ABS, ESP, …) sind so komplex, dass sie nur unter großem Aufwand modelliert werden können. Es ist in der Testplanung abzuwägen, wie exakt das Modell der Umgebung sein soll. So muss etwa bei einem Steuergeräte-Test für Fahrzeuge geplant werden, was in einer Umgebungssimulation geprüft wird (siehe Abb. 1–2) und was etwa an einem Motorprüfstand oder in einem Testfahrzeug getestet wird (siehe Abb. 1–3).
Das Modell der Umgebung, beziehungsweise die Testausrüstung für Tests am Zielsystem, muss auch außergewöhnliche Situationen vorsehen. Etwa den Neustart der Hardware während der Kommunikation mit einem externen Gerät, die Parallelnutzung eines Betriebssystemservices durch andere Applikationen, einen Fehler im Speichermedium und so weiter.
Abb. 1–2Beispiel einer Testumgebung. Diese Ausrüstung wird verwendet, um Software für Steuergeräte automatisiert zu testen. Produziert die Testumgebung, wie hier, auch alle Stimuli für Sensoren und prüft sie die Funktion von Aktoren, so spricht man vom Hardware-In-The-Loop-Test. Foto © dSPACE GmbH.
Abb. 1–3Eine Testschnittstelle ermöglicht während der Fahrt, Interna der Steuergeräte-Software per Laptop zu überwachen. Die Testfälle sind in diesem Testfahrzeug per Definition real. Ihr Design ist aber im Vergleich zur Simulation eingeschränkter, zum Beispiel weil Unfallszenarien nicht einfach zu durchlaufen sind.
Software kann mitunter eine unendlich große Anzahl von verschiedenen Eingangsdaten verarbeiten. Denken wir nur an ein Textverarbeitungsprogramm oder an eine Signalverarbeitungssoftware, wo die Reihenfolge der Eingabe von Daten relevant ist. Die schwierige Aufgabe des Testers ist es nun, einige wenige Testszenarien zu entwerfen, die ein Programm prüfen sollen, das eigentlich unendlich viele Szenarien verarbeiten kann.
Bei der Durchführung der Tests wird man nach der strukturellen Testabdeckung (Structural Test Coverage) fragen: Welche Teile des Codes sind noch ungetestet? Um diese Frage zu beantworten, bedient man sich in den meisten Fällen eines Werkzeugs. Kapitel 6 wird die Funktionsweise solcher Werkzeuge erklären.
Abbildung 1–4 zeigt, wie so ein Werkzeug verschiedene Arten von Testabdeckungen nach Messung anzeigt und so den Testfortschritt visualisiert.
Mit dem Ziel, die gewünschte Testabdeckung am Quellcode zu erreichen wird der Tester daher Szenarien auswählen, die
typisch auch in der Feldanwendung auftreten,
möglichst »bösartig« sind und damit eher Fehler provozieren als »Schönwettertests«,
Grenzfälle ausprobieren.
Für die Testabdeckung gibt es eine Reihe von Kriterien unterschiedlicher Schärfe. Im einfachsten Fall könnte man sich etwa zufriedengeben, wenn jedes Statement der Programmiersprache C einmal ausgeführt wurde. In sicherheitskritischen Anwendungen könnte man fordern, dass jedes Assembler-Statement mindestens einmal ausgeführt wird und dass zusätzlich bewiesen werden muss, dass jeder Einfluss auf eine Programmverzweigung auch unabhängig von anderen Einflüssen wirken kann. Abschnitt 6.6 wird einige Testabdeckungsmetriken für Modultests vorstellen.
Abb. 1–4Anzeige der erreichten Testabdeckung in einem Werkzeug für Unit-Tests
Die Testabdeckung aber nur am Quellcode zu messen, wäre keine gute Idee. Der Code zeigt nicht, was vergessen wurde zu implementieren, und er zeigt auch nicht, ob die Anforderungen richtig umgesetzt wurden. Dazu ist zumindest ein Blick in die Anforderungsspezifikation nötig. Je formaler diese verfasst ist, desto besser für den Zweck des Testens.
Auf Basis der Spezifikation lassen sich auch für viele Black-Box-Testtechniken Maße definieren, die die Schärfe/Überdeckung eines Tests völlig unabhängig vom Code bewerten. Die anzustrebende Überdeckung für einen Black-Box-Test nennt die Normenreihe ISO 29119 Testüberdeckungselemente (test coverage items). Kapitel 8 wird solche Testüberdeckungselemente vorstellen.
Nachdem geeignete Testfälle ausgewählt/entworfen worden sind, kann zur Ausführung derselben geschritten werden. Die kann manuell erfolgen, halb automatisch sein oder voll automatisch ablaufen. Die Wahl des Automatisierungsgrads ist vor allem von zwei Faktoren abhängig: der Haftung bei Software-Fehlern und der Wiederholungsrate der Tests. Bei Anwendungen mit Sicherheitsrelevanz wird die Wahl eher auf automatische Tests fallen. Die Testskripts erlauben im Idealfall eine exakte Wiederholbarkeit der Tests.
Bei manuell durchgeführten Tests ist exakte Wiederholbarkeit schlecht möglich. Ganz speziell bei Echtzeitsystemen. Dafür ist man mit manuellem Testen schneller am Ziel: Bis automatische Tests fehlerfrei laufen, ist im Schnitt der zehnfache Aufwand wie für einen manuellen Test notwendig. Also rentiert sich Testautomation vor allem dann, wenn Tests oft wiederholt werden. Solche Wiederholungen können zum Beispiel notwendig sein, wenn man zu bestehender Software neue Funktionalität hinzufügt oder einen Fehler behebt. Bringt die Fehlerbehebung an anderer Stelle einen neuen Fehler? Um sicherzugehen, kann man dann alle existierenden Tests automatisch nochmals durchführen. Diese Testwiederholungen, »nur um sicherzugehen«, werden Regressionstests genannt. Automation ist besonders für Regressionstests geeignet.
Mit der Ausführung der Tests alleine ist es aber noch nicht getan. Es muss auch noch beurteilt werden, ob sie einen Fehler gefunden haben oder nicht. Das ist nicht immer einfach und gelegentlich eine Hürde für die volle Automation von Tests. Jedenfalls müssen die Kriterien für den Testerfolg genau spezifiziert sein. Ohne diese Festlegung würde der Software-Test allenfalls ein Herumprobieren sein, aber den Namen »Test« nicht verdienen.
Trotz des Determinismus und der Wiederholbarkeit ersparen vollautomatische Tests nicht die sorgfältige Dokumentation und Abstimmung des Testdesigns mit sich ändernden Versionen der Anforderungsspezifikation. Sonst würde die Testkollektion, wie es in Kritiken der Testautomation heißt, ein gewisses Eigenleben entwickeln: »Niemand getraut sich einen Test zu löschen, weil die Bedeutung nicht genau bekannt ist; kein Mitarbeiter weiß, was die Tests eigentlich tun, aber sie zu bestehen ist essenziell; mit neuen Anforderungen kommen aber neue Tests hinzu, und so wird die Testkollektion ein zunehmend mysteriöseres Orakel, ähnlich einer sprechenden Eiche aus einem Disney-Film« [Bach 96].
Bleibt trotz allem noch die Frage des Vertrauens in die automatischen oder manuellen Tests. Wenn das Testsystem immer »alles okay« meldet, sollten wir uns dann nicht irgendwann mal Sorgen machen? Um diese Sorgen in Grenzen zu halten, ist es empfehlenswert, bei der Entwicklung von Testskripts zum Debugging absichtlich Fehler im Testobjekt einzubauen oder das Testobjekt so zu konfigurieren, dass das Testskript einen Fehler erkennen sollte. Beispiel: beim Test eines Video-Übertragungssystems auf einem eingebetteten Audio-Kanal kurz den Ton abdrehen. Wird dieser eingebrachte »Fehler« nicht in den automatischen Tests entdeckt, dann stimmt etwas mit der Testumgebung nicht.
Wie jedes andere Projekt sollte auch ein Testprojekt genau geplant werden. Teil dieses Plans ist die Festlegung des Projektziels, zum Beispiel wie viele unentdeckte Fehler welcher Kategorie die zu testende Software nach dem Test noch haben darf. Die Art und der Umfang der Tests werden sich nach dieser Größe richten, siehe Diskussion zu Abbildung 1–1.
Bei der Erstellung eines Zeitplans für den Software-Test können Code-Metriken helfen. Code-Metriken sind Maßzahlen, die aus dem Quellcode automatisch erhoben werden, siehe Abschnitt 4.5. Zum Beispiel die Anzahl der linear unabhängigen Pfade, die in Abschnitt 6.7 behandelt werden. Ist aus Aufzeichnungen bekannt, wie lange man im Schnitt pro Pfad testet, dann ist die Aufwandsschätzung schnell gemacht, wenn man sich vornimmt, alle linear unabhängigen Pfade zu testen.
Für die Aufwandsschätzung beim Test gegen die Anforderungsspezifikation, dem Systemtest, können die gleichen Verfahren herangezogen werden, die zur Schätzung der Programmerstellung dienen. Auch hier kann man eine Testabdeckung definieren. Etwa: Alle Software-Anforderungen einer gewissen Mindestpriorität sollen getestet werden.
Um den Zeitplan regelmäßig zu aktualisieren, kann man Messungen einer zuvor ausgewählten Testabdeckung verwenden. Die Erfassung des bisher in den Test gesteckten Aufwands und der bisher erreichten Testabdeckung erlaubt eine einfache Extrapolation und damit die Vorhersage des Erreichens von 100 % der gewünschten Testabdeckung. Dabei ist allerdings eine Warnung angebracht: Der Aufwand pro Prozent Abdeckung steigt typischerweise gegen Ende des Projekts stark an.
Der Software-Entwicklungsprozess beginnt meist mit der Analyse des Problems und dem Schreiben der Anforderungsspezifikation. Die Spezifikation bildet die Grundlage für funktionale Software-Systemtests, die die Einhaltung der Spezifikation testen und somit Designfehler und Programmierfehler aufdecken.
Mit dem Design der Systemtests kann begonnen werden, sobald die Anforderungen feststehen, also oft schon lange, bevor die Software überhaupt existiert. Ein früher Beginn des Testdesigns, parallel zum Software-Design, zahlt sich aus mehreren Gründen aus:
Die Testphase verkürzt sich, denn wenn die zu testende Software fertig für den Test ist, muss man nicht erst beginnen, sich gute Tests auszudenken.
Untestbare Anforderungen werden identifiziert. Es gibt kaum eine kritischere Review von Anforderungen, als wenn man sich Tests dafür ausdenkt.
Gegebenenfalls wird die Notwendigkeit von spezieller Testhardware erkannt und diese kann rechtzeitig geschaffen oder beschafft werden. Solche Testhardware kann ein Testzugang am zu testenden Gerät sein, etwa ein Messpunkt auf einer Platine oder ein Messmittel, etwa ein Oszilloskop.
Mit dem Testen selbst kann man aber natürlich erst beginnen, wenn die Software fertig ist. Wenn die Anforderungen dem Entwickler-Team gewisse Freiheiten lassen, dann kann es sein, dass es beim Testdesign nicht möglich ist, den einen oder anderen Test ins letzte Detail auszuformulieren. Das ändert nichts an der Tatsache, dass es sinnvoll ist, mit dem Testdesign möglichst früh zu beginnen. Es bleiben aber durch offene Fragen Lücken im Testdesign. Der Testplan, in dem das Systemtestdesign meist dokumentiert ist, muss also ein »lebendes Dokument« sein. Es erfährt regelmäßige Aktualisierungen und muss daher unter Versionskontrolle stehen. Nicht nur das Füllen der genannten Lücken sind Gründe für Aktualisierungen. Natürlich kommt es vor, dass ein im frühen Projektstadium ausgedachter Testfall später nicht so umzusetzen ist, wie gedacht. Wird die Dokumentation nicht angepasst, so laufen reale Tests und Dokumentation auseinander und man entwertet das Test-Set. Im schlimmsten Fall manövriert man die Tests in einen unwartbaren Zustand und landet bei der in Abschnitt 1.5.7 erwähnten sprechenden Eiche aus einem Disney-Film.
In vielen Projekten ist aber der häufigste Grund für Updates von Tests eine Revision der Anforderungsspezifikation. Um bei einer solchen Revision der Anforderungen zu wissen, welche der schon bestehenden Systemtests überarbeitet werden müssen, wird eine Traceability-Tabelle erzeugt und stets auf dem aktuellsten Stand gehalten. Diese Tabelle verfolgt, welche Anforderung in welchem Testfall getestet wird. Ein Beispiel ist in Abbildung 1–5 zu sehen. Diese Tabellen können entweder manuell erstellt und gewartet werden oder sind ein Produkt von Requirements Engineering/Management Tools.
Normalerweise werden im Software-Designprozess die Aufgaben der Software auf verschiedene Module (beziehungsweise Klassen) aufgeteilt. Es ist daher naheliegend, nach dem Programmieren zuerst jedes dieser Module einzeln zu testen, bevor sie zu einem Ganzen zusammengefügt werden. Diese in Kapitel 6 behandelten Tests werden Modultests genannt. Mit dem Design der Modultests kann begonnen werden, sobald das Software-Design genau die Aufgaben jedes Software-Moduls spezifiziert. Der Modultest testet das Software-Modul gegen diese Modulspezifikation. Beim Modultest leistet man sich den Luxus, genau zu prüfen, welche Teile des Quellcodes tatsächlich durchlaufen wurden. Je nach Anspruch an die Schärfe dieser White-Box-Tests existieren verschiedene Maße für das Messen der Testabdeckung, wie Abschnitt 6.6 zeigen wird.
Ob beim Zusammenfügen der Module Fehler auftreten, prüft ein Integrationstest. So wie dem Thema Modultest widmet sich ein eigenes Kapitel dieses Buchs dieser in der Literatur wenig beschriebenen Teststufe. Integrationstests können geplant werden, sobald feststeht, welche Daten- und Kontrollflüsse zwischen den Modulen stattfinden. Integrationstests prüfen genau dieses Zusammenspiel und decken also Schnittstellenprobleme auf. Sie sind also ein Test der Software gegen das Design der Software-Architektur.
Nach bestandenem Integrationstest beginnt man mit der Durchführung der Systemtests. Systemtests prüfen die Einhaltung der Anforderungsspezifikation und testen die Software möglichst in der Zielumgebung. Auch bei gewissenhaftesten Unit-Tests und Integrationstests werden hier typischerweise Fehler gefunden: Design-Fehler. Die vorhergehenden Testschritte testen immer gegen das Design der Software. Ist das Design aber fehlerhaft oder lückenhaft und wird dadurch die Spezifikation nicht erfüllt, so ist die Software dennoch fehlerhaft und diese Fehler werden am ehesten im Systemtest in der Zielumgebung gefunden.
Ist die Zielumgebung nicht verfügbar und das Risiko vertretbar, so kann man sich mit der Simulation der Zielumgebung zufriedengeben. Bei sicherheitsrelevanter Software und Software mit hohen Ansprüchen an die Integrität ist ein Test in der Zielumgebung jedoch unverzichtbar. Abschnitt 8.12 auf Seite 183 gibt ein eindrucksvolles Beispiel aus der Praxis zu diesem Thema.
Systemtests werden, wie erwähnt, am besten schon lange vor den Integrationstests entworfen. Da zum Zeitpunkt des Entwurfs der Code noch nicht existiert, sind die Tests idealerweise unabhängig vom Design. Man spricht von Black-Box-Tests. Techniken dazu werden in Kapitel 8 vorgestellt.
Requirement No
Requirement Short Text
Tested in
R/SRD/INIT/10
Self Test
ST-IOPS-FT01
R/SRD/INIT/20
Self Test Fail Silence
ST-IOPS-FT01
R/SRD/PP/05
Ready Message
ST-IOPS-FT01
R/SRD/PP/20
PP-bus Performance
ST-IOPS-FT02
R/SRD/PP/30
Reply Message Format
ST-IOPS-FT02
R/SRD/PP/40
SetPosDebTime Cmd
ST-IOPS-FT03
R/SRD/PP/50
SetNegDebTime Cmd
ST-IOPS-FT03
R/SRD/PP/60
SetRepIntv Cmd
ST-IOPS-FT02
R/SRD/PP/70
Start Command
ST-IOPS-FT02
R/SRD/PP/80
Report Message Format
ST-IOPS-FT02
R/SRD/SI/10
Position Sampling Rate
ST-IOPS-FT03
R/SRD/SI/30
Debouncing
ST-IOPS-FT04,ST-IOPS-FT03
R/SRD/RA/10
Missing Parameters
ST-IOPS-FT05
R/SRD/RA/20
PP-bus Error
ST-IOPS-FT05
R/SRD/RA/30
Watchdog Kicking
ST-IOPS-FT05
R/SRD/SB/10
Maximum CPU Load
ST-IOPS-FT06
R/SRD/SB/20
CPU Idle Time
ST-IOPS-FT07
R/SRD/SB/30
Memory Footprint
ST-IOPS-FT08
R/SRD/SD/10
Software Coding Standard
verified in code reviews
Abb. 1–5Die Traceability-Tabelle für Systemtests eines fiktiven Projekts
Mit hohen Ansprüchen an die Integrität der Software sollte auch die weitgehende Automation der Tests einhergehen. Bei Updates kann somit schnell der gesamte Funktionsumfang der Software getestet werden und die Wiederholbarkeit der Tests ist im Idealfall zu 100 % gesichert. Bei eingebetteten Systemen kann so ein automatischer Test in der Zielumgebung großen Aufwand bedeuten. Ein Beispiel ist in Abbildung 1–6 zu sehen. Die zu testende Software steuert eine Anzeige am Aktor Armaturenbrett. Dem Aktor muss im Testsystem ein entsprechender Sensor gegenüberstehen, der die Anzeige erfasst.
Abb. 1–6Automatische Systemtests können aufwändig werden. Ist der von der Software bediente Aktor die Tacho-Nadel, so sollte der Sensor des Testaufbaus die Position der Tacho-Nadel erfassen können. Foto © dSPACE GmbH.
Die Durchführung der Testschritte erfolgt also in einem Bilderbuchprojekt in umgekehrter Reihenfolge wie die Planung und das Design der Tests. Dieses traditionelle Software-Entwicklungsmodell (Software Life Cycle Model) wird oft mit einem »V« visualisiert. Abbildung 1–7 zeigt solch ein Modell: das inzwischen abgelöste Entwicklungsmodell PSS-05 der europäischen Raumfahrtorganisation [PSS-05-0]. Der zeitliche Verlauf in diesem »V« ist von links oben nach unten und dann nach rechts oben. Und das Modell definiert für jeden Prozessschritt bestimmte Artefakte als zu erwartendes Ergebnis. Am linken Ast im »V« des PSS-05 sind dies nur Dokumente. Und zwar URD für das User Requirements Document, SRD für das Software Requirements Document, ADD für das Architectural Design Document und DDD für das Detailed Design Document.
Ob alle beschriebenen Testschritte in einem Projekt auch tatsächlich zum Einsatz kommen und alle Dokumente wirklich geschrieben werden, ist eine Frage der Wirtschaftlichkeit.
Abbildung 1–7 zeigt am linken Ast des Modells Pfeile in Aufwärtsrichtung, also »gegen die Zeit«. Diese mit SVVP/SR, SVVP/AD und SVVP/DD beschrifteten Pfeile stehen für kleine Iterationen. Solche kurzen Zyklen sind Ergebnisse von Reviews. Welche Reviews durchgeführt werden, ist gemäß PSS-05 beim Projektstart zu definieren und in einem Software Verification and Validation Plan (SVVP) zu dokumentieren. Dieses zentrale Planungsdokument hat leider viele verschiedene Namen. In älteren IEEE-Normen und bei ISTQB spricht man vom Master Test Plan. Die Normenreihe 29119 spricht vom Test Plan und lässt offen, ob es mehrere Bände dieses Dokuments gibt. »Test Plan« übersetzen Normenspezialisten auf Deutsch gerne als Testkonzept [Daigl 16].
Alle vorgestellten Artefakte – User Requirements Document, Software Requirements Document, Architectural Design Document und das Detailed Design Document – werden im Idealfall einer Review unterzogen. Kommt der Reviewer zur Auffassung, dass zum Beispiel ein Anforderungsdokument Widersprüche enthält oder ein Design verbesserungswürdig ist, so wird der Widerspruch aufgelöst und das Design verbessert, ehe man die nächste Prozessphase betritt. Typischerweise finden solche Reviews innerhalb eines Teams statt. Dokumente, die Vertragsbestandteil sind oder die Kundenkommunikation unterstützen, wie Anforderungsdokumente, werden oft auch durch den Geschäftspartner inspiziert.
In Projekten mit höchster Integritätsanforderung ist der Abschluss einer Phase oft mit einer Technical Review verbunden. Ein Review Board, bestehend aus Kunden, Lieferanten und gegebenenfalls einer externen Firma, die ausschließlich zum Zweck der Review bestellt wurde, entscheidet, ob ein Zahlungsmeilenstein erreicht ist und es dem Lieferanten gestattet wird, in die nächste Projektphase einzutreten.
Abb. 1–7Das Software-Entwicklungsmodell nach PSS-05. Die horizontalen Pfeile zeigen, welche Testschritte welche Teile der Entwicklungsschritte abtesten. Sobald der Entwicklungsschritt an der Pfeilspitze fertig ist, kann mit dem Design der entsprechenden Tests begonnen werden.
Auch der Quellcode wird einer Review unterzogen – am besten, bevor man Unit-Tests macht. Code-Reviews können zum Teil automatisiert werden. Man spricht von der Automatischen Statischen Analyse, Kapitel 4 beschäftigt sich damit.
Alle angesprochenen Reviews dienen dazu, die Fehlerkosten niedrig zu halten. Je früher im Entwicklungsprozess sich ein Fehler einschleicht, desto größer seine Tragweite. Denken wir zum Beispiel an eine ungeschickte Software-Architektur. Wenn der Code bereits implementiert ist und erst im Integrationstest erkannt wird, wie unpassend das Design ist, dann müssen die Architekturdokumentation geändert, der Code angepasst und die Unit-Tests aktualisiert werden. Wäre der Fehler gleich bei einer Review des Architectural-Design-Dokuments aufgefallen (in kleinen Projekten kann das auch eine Bleistiftskizze sein), wäre der Änderungsaufwand auf die Aktualisierung des Dokuments beschränkt gewesen.
Reviews und Tests reichen nicht aus, um Echtzeitsysteme mit höchsten Ansprüchen ausreichend abzusichern. Als weitere Verifikationsmethode kommt die Analyse hinzu. Im Speziellen ist dies die Analyse der Rechtzeitigkeit der Systemantwort, der sich die Kapitel 12 und 13 widmen. Bei Systemen mit Sicherheitsrelevanz kommt noch die Analyse des Systemverhaltens bei Teilausfällen hinzu, die in Kapitel 14 beschrieben wird, und man wird im Projektverlauf auch regelmäßig den Speicherverbrauch des Systems ermitteln, damit es nicht unerwartet zu bösen Überraschungen kommt.
Im realen Leben wird der in Abbildung 1–7 gezeigte Entwicklungszyklus mehrfach durchlaufen. Neue Iterationen können notwendig werden, wenn zum Beispiel neue Anforderungen hinzukommen. Zumindest teilweise sind Iterationen bei Re-Designs und bei Bugfixes notwendig. Entsprechend erfahren die begleitenden Projektdokumente mehrere Updates. Ohne solche Updates werden die Dokumente zunehmend wertloser!
Agile Methoden (Scrum, Extreme Programming …) machen diese Not zur Tugend und versuchen durch eine absichtlich hohe Anzahl von Iterationen und Lieferung von Teilen des Produkts, Dokumentation zu sparen und den Kunden verstärkt in den Entwicklungsprozess einzubinden. Anstelle von Dokumentation tritt verstärkte Kommunikation und hohe Bereitschaft zu enger Zusammenarbeit [Beck 01].
Bei vielen eingebetteten Systemen sind Teillieferungen von Software nur eingeschränkt oder gar nicht möglich. Eine frühe Kundeneinbindung ist ebenfalls nicht immer sinnvoll. Agile Projektmodelle werden daher oft adaptiert. Die Rolle des die Teillieferung abnehmenden Kunden wird zum Beispiel von einer anderen Abteilung übernommen, die die neu entwickelte Software und Hardware integriert.
Eine Spielart bei agilen Methoden ist die Test-First-Strategie (oder Test Driven Development, TDD). Das heißt, der Programmierer beginnt einen Unit-Test für den eigenen Code zu schreiben, bevor er mit dem Codieren beginnt. Zug um Zug werden in kleinen Iterationen zuerst der Test und dann das Testobjekt implementiert beziehungsweise erweitert. Sobald der Test keine Fehler mehr meldet, beginnt eine neue Iteration.
Bei maschinennaher Programmierung kann diese Strategie sehr ineffizient werden, wenn man beim Programmieren erst die neue Hardware »kennenlernt« und das detaillierte Design sich daher hochdynamisch ändern kann. Ebenso ist es bei der Entwicklung von eingebetteten Systemen oft der Fall, dass Hardware erst während der Software-Entwicklung entsteht. Das erschwert natürlich Test Driven Development mit Tests in der Zielumgebung und zwingt gegebenenfalls zur Nutzung von Simulatoren, aber es zwingt auch – als positiver Effekt – zu einem Design, bei dem Hardware-Abhängigkeiten sauber gekapselt sind. Es gibt ohne Zweifel Embedded-Projekte, die von TDD profitieren: Die kurzen Iterationen vom fertiggestellten Code zum unerwartet fehlgeschlagenen Testfall ersparen langwierige Debug-Sitzungen, wie man sie oft vorfindet, wenn ein Test erst lange nach dem Programmieren stattfindet; nur der gerade hinzugefügte Code kann für das Fehlschlagen des Tests verantwortlich sein [Grenning 11]. Von dieser Eigenschaft profitiert man aber auch, wenn man den Unit-Test (siehe Kapitel 6) unmittelbar nach der Implementierung eines Moduls macht und dabei strikt Black Box gegen die Spezifikation (das Design) des Moduls testet. Der Test muss dazu nicht vor oder während der Implementierung des Codes entstehen.
Beim Erstellen eines Unit-Tests für fertig implementierte Komponenten unterstützen aber leistungsfähige Unit-Test-Werkzeuge extrem und können die Arbeit deutlich beschleunigen. Abschnitt 6.5.2 wird die Funktionsweise dieser Werkzeuge vorstellen.
TDD ist keine Testmethode, sondern eine Entwicklungsmethode, die sicherstellt, dass der Code testbar und getestet ist. Das ist aber noch kein Garant für Qualität, wenn man an unvollständige, unstrukturierte und qualitativ schlechte Tests denkt. Allerdings zwingt TDD den Tester, sich intensiv mit der Spezifikation der zu testenden Komponente auseinanderzusetzen, anstatt sich fälschlicherweise nur am Code zu orientieren, wie der Erfahrungsbericht am Ende von Abschnitt 6.13.1 zeigen wird.
Ein Absatz des agilen Manifests schlägt folgende Wertschätzung vor: »Working software over comprehensive documentation«. Das bedeutet aber keinesfalls den Verzicht auf die Dokumentation von Anforderungen, die die Basis für Systemtests darstellen. Wenn der Dokumentation der Anforderungen keine Wertschätzung zukommt, dann kann das schon sehr zermürbend werden für einen Tester: Das, was gestern noch für Team-Mitglied 1 ein Bug war, kann heute für Mitglied 2 ein Feature sein. Daher ist für einen Tester eine gewissenhafte Dokumentation der Anforderungen Bedingung für saubere Arbeit. Ohne diese Dokumentation wird von Testteam-Ineffizienzen von 25 bis 30 % berichtet [Black 10]. Wie auch immer der Autor zu diesen Zahlen kommt.
Auch Test Driven Development macht die Dokumentation von Anforderungen nicht überflüssig. [Heusser 07] zitiert folgende frei übersetzte, verlockende Aussage zum Thema Anforderungsspezifikation und Test in agilen Projekten:
»Wir implementieren Projekte iterativ. Da ist ja ein großes Software-Projekt nur eine Aneinanderreihung von kleinen. Wenn wir keine klar testbaren Akzeptanzkriterien für das Arbeitspaket unserer nächsten zwei Wochen haben, dann haben wir ein großes Problem. Wenn wir es können, warum repräsentieren wir diese Kriterien nicht gleich direkt in Form von Testfällen, anstatt später aus den Anforderungen Testfälle abzuleiten?«
Die Verlockung ist wahrlich groß: sich Anforderungsdokumentation zu ersparen und trotzdem Testfälle parat zu haben! Es gibt viele Gründe, dies nicht so zu tun. Abschnitt 2.4 wird die meisten davon nennen. Ein Beispiel ist die Wichtigkeit der Dokumentation von Hintergrundwissen rund um die Anforderungen. Also das Verstehen, wieso der Kunde etwas so wünscht und nicht anders. Ein Tester, der sich durch Lesen der Anforderungsdokumentation in die Kundensicht versetzen kann, macht die besten Akzeptanz-Testfälle. Ein Tester, der die folgenden Testfälle anstelle einer Anforderung von einem Kollegen zu übernehmen hat, versteht sicherlich nicht ohne nachzufragen, was der Kunde eigentlich benötigt:
Input
Erwarteter Output
32
0
100
38
212
100
Und was ist, wenn niemand da ist, den man fragen könnte? Dokumentation ist eine Art Sicherheitsgurt gegen Mitarbeiterfluktuation und Erinnerungslücken. Das gilt für den Test genauso wie für die Entwicklung. Wenn – im idealen agilen Projekt – immer jemand da ist, der Bescheid weiß, Zeit hat und kooperationswillig ist, dann darf man auch beim Test die Dokumentation einsparen. Solche Projekte gibt es aber nur im Märchen. Je komplexer und größer ein Projekt ist und je eher man Personen im Team hat, die nicht immer verfügbar sein werden, desto wichtiger wird die Dokumentation von Anforderungen und den daraus abgeleiteten Testfällen. Wenn man für das Produkt haftet, dann gilt ein nicht sauber dokumentierter Test als nicht gemacht, wie Kapitel 19 zeigen wird.
Manche Leute stellen sich die Frage, ob man auch unabhängige Tests von projektspezifischer Testsoftware macht. Also unabhängige Tests der Tests. Diese Frage kann man generell mit »Nein« beantworten. Die zu testende Software ist der Prüfstein für den Test. Geht der Test nicht durch, so gibt es zwei Möglichkeiten (wenn wir davon ausgehen, dass die Prüfmittel fehlerfrei sind): Entweder der Test ist fehlerhaft oder die zu testende Software ist es.
Das heißt aber nicht, dass man sich nicht anderer Verifikationsmethoden bedient, bei denen ein weiteres Augenpaar mitwirkt. Bei hohen Integritätsanforderungen an die Software ist es durchaus üblich, Folgendes durchzuführen:
Review der Unit-Tests, wenn diese vom Entwickler selbst gemacht wurden
Review der Integrationstests, wenn diese von einem einzigen Entwickler entworfen/durchgeführt wurden
Review des Systemtestdesigns gegen die Anforderungsspezifikation
Review der Systemtestskripts gegen das Systemtestdesign (bei automatischen Tests)
In Abschnitt 1.5.7 wurde schon eine andere Methode erwähnt, um die Testqualität zu verifizieren: das absichtliche Einbauen von Fehlern in das Testobjekt und das anschließende Prüfen, ob der Test diese auch findet. Wenn man den Quellcode ändert, um Fehler einzubauen, spricht man von Fault Seeding. Wird das zu testende System im Betrieb manipuliert, um fehlerhaft zu sein, spricht man von Fault Injection. Die systematische Anwendung dieser Methoden ist in nur wenigen Projekten finanziell zu rechtfertigen und hat sich daher nicht wirklich durchgesetzt. Trotzdem ist es eine gute Idee, wenn man als Entwickler von Testskripts gelegentlich prüft, ob das entwickelte Testskript auch mit Fehlern des Testobjekts wie erwartet umgeht.