Statische Analyse und Dynamischer Test: Wo liegen die Stärken und Schwächen?
Statische Analyse und Dynamischer Test: Von garantiert fehlerfreier Software sind wir auch nach mehreren Jahrzehnten an Software Engineering gefühlt immer noch unendlich weit entfernt. Auch für die nach den höchsten Sicherheitsstandards entwickelte Software kann niemand absolute Fehlerfreiheit garantieren. Alle Funktionalen Sicherheitsstandards erkennen an, dass eine garantiert fehlerfreie Software (mit dem heutigen Stand der Technik) nicht erreichbar ist. Die Maßnahmen in den Standards haben das Ziel die Anzahl der Fehler zu minimieren und auftretende Fehler so rechtzeitig zu erkennen, dass eine schlimmere Fehlerwirkung verhindert wird.
Statische Analyse und Dynamischer Test stellen zwei solche Maßnahmen dar. Insbesondere in sicherheitsrelevanten Systemen wird der Einsatz beider Maßnahmen gefordert, obwohl zum Teil die gleichen Fehler gefunden werden.
Umfängliches Validieren, Verifizieren und Testen ist mit hohen Kosten verbunden. Dies führt in den Meisten Projekten zu einem hohen Druck eine optimierte Teststrategie zu entwickeln.
Eine Voraussetzung für erfolgreiche Testoptimierungsstrategien ist das umfängliche Verständnis von Stärken und Schwächen der statischen und dynamischen Tests und Analysen. Der nachfolgende Beitrag gib einen ersten Überblick über das Thema.
Statischer Test bzw. Statische Analyse
Häufig wird für den statischer Test auch der Begriff statische Analyse verwendet. Der ISTQB definiert in seinem Glossar die statische Analyse wie folgt:
Der Prozess der Bewertung eines Testobjekts (Komponente oder System) basierend auf seiner Form, seiner Struktur, seines Inhalts oder seiner Dokumentation, ohne es auszuführen. [Nach ISO 24765].
Der statische Test wird dagegen wie folgt definiert:
Testen eines Arbeitsergebnisses, ohne dieses auszuführen.
Wie sich allerdings in der Praxis eine nachvollziehbare Abgrenzung zwischen beiden Definitionen machen lässt ist mir unklar. Mir ist keine praxistaugliche Unterscheidung bekannt. Konsequenterweise verwende ich im Nachfolgenden beide Begriffe so dass sie jederzeitig gegeneinander ausgetauscht werden können.
Dynamischer Test
Der ISTQB Glossar definiert den dynamischen Test wie folgt:
Prüfung des Testobjekts durch Ausführung auf einem Rechner.
Dynamische Analyse
Die dynamische Analyse unterscheidet gemäß ISTQB etwas vom dynamischen Test. Der ISTQB Glossar legt folgende Definition dafür fest:
Prozess der Bewertung des Verhaltens (z.B. Speichereffizienz, CPU-Nutzung) eines Systems oder einer Komponente während der Nutzung. [Nach IEEE 610]
Die Unterscheidung zwischen dynamischer Analyse bzw. dem dynamischen Test macht durchaus auch in der Praxis Sinn. Der Nachweis von Speichereffizienz und CPU Nutzung sind nur sinnvoll zu erbringen, wenn man dynamische Tests kombiniert mit einem Mix aus verschiedenen Analysen.
Übersicht über statische Analysen bzw. statische Tests
Welche Aktivitäten in einem Entwicklungsprojekt fallen nun in der Praxis unter den Begriff statische Analyse bzw. Test? Das folgende Diagramm gibt dazu einen Überblick.
Reviews von Requirements, Architektur, Design, Source Code und Traceability
Diese Reviews haben gemeinsam, dass Sie weitestgehend manuell, händisch durchgeführt werden müssen. Es gibt nach wie vor keine automatisierbaren Antworten, zu der Frage ob ein Requirement korrekt in einer Architektur/Design oder auch Source Code umgesetzt ist. Nur bei der Traceability gibt es eine gewisse Tool Unterstützung. Allerdings kann kein Tool bis heute eine Inhaltliche Prüfung von Verknüpfungen vornehmen, d.h. ob der verknüpfte Source inhaltlich wirklich zum Requirement passt, kann nur der Mensch entscheiden. Tools können nur unterstützen, bei Regeln, wie jedes Requirement muss mindestens einem Architektur Element zugeordnet sein etc.
Überprüfung von Codierrichtlinien
Codierrichtlinien sollen im Wesentlichen zwei Aspekte abdecken. Zum einen werden durch Codierrichtlinien Programmiersprachen-Elemente von der Verwendung ausgeschlossen, deren Verwendung sich als besonders Fehleranfällig in der Vergangenheit bewiesen haben. Zum anderen werden Codierrichtlinien auch angewandt, um den Source Code lesbarer und verständlicher zu machen.
Im Gegensatz zu den obigen Reviews, lässt sich die Überprüfung der Codierrichtlinien heutzutage weitestgehend automatisieren. Zum einen gibt es neben MISRA inzwischen auch andere Codierstandards, sodass jedes Projekt das für sich richtige Sub-Set finden können sollte und für die überwiegende Mehrzahl dieser Regeln gibt es inzwischen Tools welche die Umsetzung der Regeln im Code automatisiert prüfen können.
Bezogen auf den Source Code bleiben erfahrungsgemäß meist nur ein paar Lesbarkeitsregeln die so spezifisch sein können, dass Sie kein Tool prüfen kann. Bevor man solche Regen für sein Projekt festlegt, sollte man sich aber im Klaren sein, dass es wirklich eine wichtige Regel ist. Ansonsten steht Aufwand und Nutzen für die Überprüfung der Einhaltung der Regel in keinem Vergleich.
Überprüfung von Source Code Metriken
Ebenso wie die Codierrichtlinien lassen sich auch viele Source Code Metriken automatisch überprüfen. Die bekannteste Metrik für Software ist sicher die Zyklomatische Komplexität McCabe. Daneben gibt es aber eine Vielzahl von weiteren Parametern anhand derer man die Software bewerten kann. Beispiele sind:
- Anzahl der Zeilen pro Funktion
- Anzahl Variablen in einer Funktion
- Anzahl der Aussprungpunkte
- Verhältnis von Kommentarzeilen zu Codezeilen
Nach einem zwischenzeitlichen Hype um den Einsatz und der Verwendung dieser Metriken, zur Messung der Softwarequalität, hat sich nun die Erkenntnis durchgesetzt, dass die Aussagekraft doch recht begrenzt ist. Mehr als einen ersten Indikator für die Qualität stellen diese Metriken sicher nicht dar. Es müssen immer weitere Aspekte hinzugezogen werden, um die nachhaltige Qualität beurteilen zu können.
Analyse zur Erkennung von Laufzeitfehlern
Eine bisher in der breiten Anwendung eher unterschätzte statische Analyse ist die Laufzeitfehleranalyse. Berühmte Vertreter von Laufzeitfehlern sind:
- Division durch Null
- Feldzugriffe außerhalb der gültigen Feldgrenzen
- ungültige Zeigermanipulationen und -dereferenzierungen
- ganzzahlige arithmetische Überläufe und Gleitkommaüberläufe
Früher waren solche Prüfungen Teil des händisch, manuellen Code Reviews, insbesondere in der Luftfahrt. Natürlich war und ist es auch das Ziel von dynamischen Tests solche Fehler zu finden. Heutzutage gibt es aber Tools, welche per statischer Analyse diese Fehler aufdecken können. Je nach Tool kann dies sogar basierend auf mathematischer Korrektheit basieren. Diese Analyse ist in den meisten Fällen, dem dynamischen Test, bezogen auf das Finden von Laufzeitfehlern, deutlich überlegen. Drei bekannte Tools für diese Analyse sind
Was zeichnet den dynamischen Test aus?
Im Gegensatz zu den diskutierten verschiedenen statischen Analysen zeichnet sich der dynamische Test dadurch aus, dass das Testobjekt aktiv ausgeführt wird.
Die größte Stärke des dynamischen Tests liegt im systematischen Nachweis der Funktionalität des entwickelten Systems bzw. der Software. Es gibt, im Vergleich zum dynamischen Test, bis heute keine auch nur annährend so effektive statische Methode, um die Korrektheit der implementierten Funktionalität nachzuweisen.
Die Erfahrung der letzten 30 Jahre Industrieerfahrung zeigt, dass gute dynamische Testergebnisse dann erzielt werden, wenn das zu testende System auf 3 – 4 Ebenen aufgebrochen wird und auf jeder Ebene entsprechende Tests durchgeführt werden. Dies sind dann in der Regel auf unterer Ebene die Software Unittests, dann kommen die SW/SW bzw. HW/SW Integrationstests und auf oberer Ebene die Systemtests.
Auf jeder Ebene wird dann ein Mix aus verschiedenen Testentwurfsverfahren angewendet. Das Diagramm zeigt die wichtigsten groben Kategorien von Testentwurfsverfahren. Im Blogbeitrag Testentwurfsverfahren werden Details dazu beschrieben.
Der Aufwand von guten dynamischen Tests ist in der Regel um ein Vielfaches höher als der Aufwand für statische Analysen und Test. Da aber statische Analysen und Tests und dynamische Tests nicht gegenseitig vollständig ersetzen lassen, aufgrund der unterschiedlichen Fehler, die jeweils gefunden werden, ist eine kluge Verifikations- und Validationsstrategie der entscheidende Faktor um die Kosten im Griff zu behalten. Eine gute Strategie zeichnet sich dadurch aus, dass sie für das jeweilige Projekt die genannten Verfahren gezielt und sich gegenseitig ergänzend einsetzt. Sinnvollerweise, wird diese Strategie auch dokumentiert, um das Vorgehen transparent für alle Projektbeteiligten zu gestalten. Dass ist auch die beste Möglichkeit, um die Strategie Schritt für Schritt weiter anzupassen und optimieren.
Die dynamische Analyse verbindet dynamische Tests mit statischen Analysen
Es gibt in Embedded Systemen immer wieder Fragestellungen, welche sich nur mit einer Kombination aus statischer Analyse und dynamischen Test zufriedenstellend beantworten lassen. Dazu gehören insbesondere Worst-Case Betrachtungen. Den Worst-Case eines Systems sowohl in Bezug auf die Speichernutzung als auch das zeitliche Verhalten, lässt sich heutzutage nur noch mit einer dynamischen Analyse sinnvoll beantworten. Dabei nähert man sich in den meisten Fällen dem tatsächlichen Worst-Case nur noch an. Der exakte Wert lässt sich oft aufgrund der Komplexität der verwendeten Hardware und Software nicht mehr genau ermitteln. Damit diese Annäherung mit ausreichender Sicherheit und Korrektheit geschieht werden statische Analysen des Speicherverhaltens oder des zeitlichen Systemverhaltens erstellt. Basierend auf diesen Analyseergebnissen werden dann dynamische Tests erstellt, welche die statische Analyse bestätigen.
Ein Ähnliches Vorgehen ist oft auch bei Nachweisen zur Systemperformance notwendig. Hier kann es sein, dass man einen dynamischen Test durch eine statische Analyse ergänzen muss, da die physikalisch vorhandenen Testumgebungen nicht ausreichen, um gewisse Szenarien nachzuweisen. In diesem Fall wird dann ergänzend eine statische Analyse durchgeführt.
Auch Dauer- und Langzeittests werden oft noch durch statische Analysen ergänzt um ein valides Gesamtergebnis zu erhalten.
Fazit
Der Beitrag hat den Umfang von dynamischen und statischen Analysen und Tests aufgezeigt. Dabei hat sich gezeigt, dass die Maßnahmen sich nicht gegenseitig ersetzen lassen. Ein System welches nur statisch analysiert und getestet wurde, besitzt keinen Nachweis für die funktionale Korrektheit.
Ein System, welches nur dynamisch getestet wird, enthält oft Fehler welche durch die begrenzten funktionalen Tests im Labor nicht zur Wirkung kommen, sehr wohl aber in der Praxis auftreten können. Zudem ist ein dynamischer Test im Vergleich zur statischen Analyse/Test um ein Vielfaches teurer und aufwendiger.
Dementsprechend sollten sich dynamische und statische Tests klug ergänzen. Dies kann erreicht werden durch die Erstellung einer entsprechenden Validations- und Verifikationsstrategie, welche in einem Projektplanungsdokument aufgeschrieben wird. Damit wird auch eine systematische Verbesserung der Strategie ermöglicht.
Weitere HEICON Blog Beiträge zum Thema
- Risikobasiertes Testen: Methode für die Identifikation der richtigen Testfälle
- Gegenüberstellung und Bewertung verschiedener Testentwurfsverfahren
- Implizites Testen – Eine gute Idee (Teil 1)?
- Implizites Testen – Eine gute Idee (Teil 2)?
- Strukturelle Source Code Coverage und Requirements – Gibt’s da einen Zusammenhang?
- Psychologie des Testers
- Requirement Engineering – Aspekte die schon in der Theorie zu kurz kommen!
- Requirement Engineering für Embedded- und IT-Systeme – Es wird Zeit das sich die Embedded Community der Unterschiede bewusst wird!
- Requirement- und Test Traceability – Mit Köpfchen!
- Requirement/Code Review – Das bessere TDD?
- Requirements Reviews aus wirtschaftlicher Sicht betrachtet!
Ihre individuellen Fragen zum Test Engineering beantworten wir gerne in einem ersten, kostenlosen 30min Beratungsgespräch!
Vereinbaren Sie gleich einen Termin: Eine kurze Mail an info[at]heicon-ulm.de genügt, oder greifen Sie gleich zum Telefonhörer: +49 (0) 7353 981 781 (Mo bis Fr 08:00 – 18:00Uhr).