Programmcode testen
Die besten Lösungen für alle Anforderungen in einem vorgegebenen Anwendungsbereich: Softwareentwickler verfolgen hochgesteckte Ziele. Ob sie ihrem Anspruch gerecht werden, ist in der Regel nicht auf den ersten Blick ersichtlich. Erst konsequente Überprüfung fördert die wahren Eigenschaften von Softwareprodukten zutage. Dabei lässt sich Qualität am besten dadurch beweisen, dass man sie hinterfragt. Die technischen Mittel dazu liefern systematische Testverfahren.
Was ist ein Test?
Der Begriff Test geht auf das lateinische Wort testa zurück, das wörtlich übersetzt Topf oder Schale heißt. Der Wandel hin zum heutigen Gebrauch erfolgte allmählich im Verlauf des Mittelalters, wobei sich die Bezeichnung test zunächst auf einen kleinen Tiegel bezog, in dem sich Metalle zur Prüfung ihrer Qualität und Reinheit schmelzen ließen. In seiner frühen Bedeutung war ein Test also ein Prüfverfahren und ein Prüfwerkzeug zugleich. Das moderne Verständnis vom Wesen eines Tests hat sich erst ab dem 16. Jahrhunderts entwickelt. Mit der Zeit hat sich dabei eine reichlich abstrakte Definition etabliert, die der Duden wie folgt angibt: nach einer genau durchdachten Methode vorgenommener Versuch, Prüfung zur Feststellung der Eignung, der Eigenschaften, der Leistung o. Ä. einer Person oder Sache Tests stellen also die Eigenschaften eines Prüflings auf die Probe. Das Ergebnis der Untersuchung ist für sich genommen nicht wertend. Erst im Vergleich mit den Erwartungen des Prüfers bekommen Testergebnisse das Etikett „gut“ oder „schlecht“ angeheftet. Dabei entscheiden im Einzelfall vorgegebene Qualitätsmerkmale über das jeweilige Testurteil.
Tests in der Softwareentwicklung
In der IT-Anwendungsentwicklung spielen Softwaretests eine entscheidende Rolle: Das Testen von Software beansprucht 25–40 % des Entwicklungsaufwands,bei kritischen Systemen liegt der Anteil noch erheblich darüber. [1] Planung, Entwurf, Durchführung und Überprüfung von Testverfahren gehören zu den Aufgaben des Software-Engineerings. Als Grundlage für die Bewertung der Testergebnisse dienen allgemeingültige Qualitätsvorgaben. Demnach gilt für Softwareprodukte die Anforderung von KorrektheitZuverlässigkeitPerformanzSicherheitNutzbarkeitVerständlichkeitWeiterentwickelbarkeitAnpassbarkeit undWartbarkeit. Was auf den ersten Blick abstrakt wirkt, erweist sich bei näherem Hinsehen als durchaus lebensnah. Ein Gedankenspiel kann die Alltagstauglichkeit der Qualitätskriterien illustrieren: Stellen Sie sich vor, Sie planen für Freunde und Nachbarn ein großes Gartenfest. Das Wohlbefinden und die Zufriedenheit Ihrer Gäste liegt Ihnen sehr am Herzen und sie entscheiden sich für eine aufwendige Bewirtung mit ausgesuchten Speisen und Getränken. Die Herausforderung: Sie können während der Vorbereitung nicht genau abschätzen, wie viele Personen anwesend sein werden. Sie müssen außerdem mit den unterschiedlichen kulinarischen Vorlieben, Weltanschauungen oder Diätvorgaben der Anwesenden rechnen. Sie möchten, dass sich Ihre Gäste schnell und leicht bedienen können, ohne dass der organisatorische Aufwand auf Ihrer Seite ausufert. In dieser Situation sind Sie als Anwendungsentwickler klar im Vorteil, denn sie können auf die Qualitätskriterien Ihres Berufsalltags zurückgreifen:
Im Alltag kann die Planung anhand von Qualitätskriterien gelegentlich Orientierungshilfe bieten. Im Software Engineering ist sie ein unentbehrliches Arbeitsmittel. Sie ist die Basis für die Festlegung individueller Anforderungen an ein Softwareprodukt. Ob die Anforderungen erfüllt sind, müssen geeignete Testverfahren im Entwicklungszyklus systematisch beweisen.
Wie funktionieren Softwaretests?
Softwareentwickler nutzen systematische Tests, um die Qualität ihrer Arbeit in zweierlei Hinsicht zu hinterfragen. Dabei geht es darum, ein System oder einen Programmcode einerseits zu validieren und andererseits zu verifizieren.
- Die Validierung befasst sich mit der Frage: Ist das, was wir tun, das Richtige? Genügt das Softwareprodukt den spezifizierten Anforderungen und verhält es sich in der Einsatzumgebung so, wie es Auftraggeber, Nutzer und Entwickler erwarten?
- Die Verifikation beantwortet die Frage: Tun wir das, was wir tun, richtig? Ist das Softwareprodukt fehlerfrei implementiert und wie lassen sich mögliche Defekte am besten finden und beseitigen?
Testmethoden im Software-Engineering unterscheiden sich hinsichtlich
- der Art, wie ein Test abläuft,
- dem Prüfbereich, den ein Test beleuchtet.
Hinsichtlich der Art der Durchführung lassen sich statische und dynamische Testverfahren unterscheiden:
Statische Testverfahren verzichten auf die Ausführung von Programmen auf einem Rechner. Im Vordergrund steht die Fehlererkennung in Anforderungsspezifikationen und Systemmodellen, die Analyse des Softwaredesigns und der Entwurfstechniken, die Prüfung des Umgangs mit Standards, Best Practices und Entwurfsmustern. Zu den statischen Testverfahren gehören außerdem Planungsrunden und Reviews im Team. Statische Testverfahren können eine Vielzahl von Mängeln frühzeitig aufdecken und die dynamischen Testverfahren entlasten.
Dynamische Testverfahren untersuchen das Verhalten von Softwareprodukten während der Ausführung auf einem Rechner. Im Vordergrund steht die Prüfung, ob einzelne Softwarebestandteile reibungslos miteinander interagieren, ob der Austausch mit Drittsystemen und dem Nutzer fehlerfrei und entsprechend den spezifizierten Anforderungen funktioniert. Dabei kommen unterschiedliche Testtechniken zum Einsatz:
- Zu den Tests, die jeder Entwickler in der Regel intuitiv durchführt, um seine Arbeit zu überprüfen, gehören die White-Box-Tests. Die Testfälle setzen die Kenntnis des Programmcodes voraus und dienen dazu, Fehler aufzudecken und erwartete Abläufe zu verifizieren.
- Black-Box-Tests legen Testfälle auf der Grundlage der spezifizierten Anforderungen, aber ohne Kenntnis des Programmcodes fest. Sie validieren das erwartete Verhalten und dienen gleichzeitig der Verifikation, indem sie technische Mängel aufdecken. Mit der Durchführung von Black-Box-Tests können sich Test-Ingenieure, aber auch Auftraggeber und Nutzer befassen.
Die umfassendsten Testergebnisse sind zu erwarten, wenn Entwickler, Test-Ingenieure, Auftraggeber und Anwender die Testfälle gemeinsam, auf der Grundlage ihres Wissens und ihrer Erfahrung erarbeiten.
Der Prüfbereich orientiert sich an den für die Softwareentwicklung festgelegten Qualitätskriterien. Sie geben die Ziele für die systematischen Tests vor. Dabei beziehen sie sich einerseits auf die Anforderungen an die spezifische Anwendung und andererseits auf die allgemeinen Vorgaben für Softwareprodukte.
Wann ist der richtige Zeitpunkt für einen Test?
Professionell aufgebaute Softwareprodukte sind keine monolithischen Gebilde, sondern bestehen aus einer beliebigen Zahl unterschiedlich komplexer Bestandteile. Systematische Testverfahren orientieren sich an diesem modularen Aufbau und stellen für jede Konstruktionsebene passende Teststufen bereit. Beginnend mit der kleinsten Softwarekomponente über Teilsysteme aus mehreren Komponenten bis hin zum Gesamtsystem mit allen seinen internen und externen Abhängigkeiten unterstützen unterschiedliche Testverfahren die Validierung und Verifikation der Programmeigenschaften.
[1]
Auf der ersten Teststufe ist der Komponententest angesiedelt. Er prüft die Funktionalität auf der Ebene des Quellcodes und betrachtet dabei eine einzelne Prozedur oder Klasse. Komponententests zählen zu den Entwicklertests und basieren auf der Technik des White-Box-Verfahrens, weil sie mit Kenntnis der Programmstruktur aufgebaut sind. Nach dem Debugging bieten sie die Möglichkeit, das Verhalten einzelner Softwarebausteine während der Programmausführung zu untersuchen und die Korrektheit der Arbeitsergebnisse zu verifizieren. Unter der Bezeichnung xUnit sind Frameworks für Modultests in unterschiedlichen Programmiersprachen zusammengefasst. Einer der bekanntesten Vertreter ist JUnit für Java. Ein JUnit-Test ist selbst ein vom Entwickler implementierter Code, der das Verhalten des zu untersuchenden Programms auf der Grundlage von erwarteten Ergebnissen bewertet. Ein grünes Testergebnis signalisiert dabei Fehlerfreiheit. Ein rotes Testergebnis weist auf erwartete (Failure) oder unerwartete (Error) Fehler hin.
Auf der zweiten Teststufe prüft der Integrationstest das Zusammenspiel zwischen einzelnen Komponenten oder Komponentengruppen. Dabei geht einerseits darum, dass jedes (teil-)selbstständige Softwaremodul (beispielsweise eine Klasse) für sich genommen korrekt funktioniert. Andererseits hat der Integrationstest die Aufgabe, den Datenaustausch zwischen unterschiedlichen, voneinander abhängigen Modulen (Klassen) zu verifizieren. Integrationstests gehören ebenfalls zu den Entwicklertests, die mithilfe von White-Box-Techniken aufgebaut sind. Eine Vielzahl von Testwerkzeugen bietet Unterstützung für die systematische, automatisierte Durchführung von Komponententests, die das modulübergreifende Verhalten prüfen.
Nach den Integrationstests folgt der technische Systemtest, der einerseits das funktionale Verhalten prüft, also die Korrektheit in Bezug auf die spezifizierten Anforderungen verifiziert und validiert. Andererseits geht es dabei um die Untersuchung, ob nichtfunktionale Qualitätskriterien wie beispielsweise Handhabbarkeit, Reaktionszeiten, oder das Verhalten unter Last erfüllt sind.
Der Abnahmetest ist ein validierender Systemtest, der die Funktionalität des Softwareprodukts aus der Sicht des Auftraggebers bewertet.
Softwareentwicklung und Test sind in der Regel keine linearen Prozesse, die konsequent und zeitlich aufeinanderfolgend von einer Stufe zur nächsten führen. Im Verlauf des Softwareentwurfs können sich beispielsweise während der Komponentenspezifikation Mängel ergeben, die eine Änderung oder Erweiterung des technischen Systementwurfs nötig machen. Oder es zeigen sich während der Programmierung Probleme, die eine Anpassung der Komponentenspezifikation verlangen. Der Komponententest kann direkt zurück zur Programmierung führen, wenn ein Unit-Test fehlschlägt. Oder ein Fehler zeigt sich erst im Integrationstest, sodass eine Änderung der Implementierung sowie neuerliche Komponenten- und Integrationstests fällig werden.
Wie ist der Testprozess aufgebaut?
Ähnlich wie die Softwareentwicklung sind systematische Tests als Prozess mit einer eigenen Planung und Steuerung organisiert. Für den Prozessablauf legt das Modell des ISTQB (International Software Testing Qualifications Board) unterschiedliche Phasen fest:
[1]
Analyse und Design untersuchen die Anforderungen an das Testobjekt anhand aller verfügbaren Spezifikationen und entwerfen erste Testfälle.
Die Realisierung umfasst die konkrete Beschreibung der Testfälle mit Ein- und Ausgaben, Vor- und Nachbedingungen sowie erwartetem Ergebnis.
Außerdem erfolgt die Gruppierung von mehreren Testfällen zu Testszenarien und Testsuiten.
Schließlich geht es an den Rechner, wo anhand der Vorgaben der eigentliche Test stattfindet.
Auswertung und Bericht dokumentieren sowohl die Qualität des Testobjekts, als auch die des Testverfahrens. Das Zusammenspiel zwischen Test, Entwicklung und Teststeuerung gestaltet sich dann optimal, wenn Fehler und Mängel direkt in einen Bug-Tracker oder in ein Projektmanagementsystem mit Ticketverwaltung einfließen und unmittelbar an die Bearbeiter zugewiesen werden können.
Die Grenzen von Software-Tests
“Durch Testen kann man stets nur die Anwesenheit, nie aber die Abwesenheit von Fehlern beweisen.” – The Humble Programmer, ACM Turing Lecture 1972 [2]
(Original engl.: “Program testing can be a very effective way to show the presence of bugs, but is hopelessly inadequate for showing their absence.“)
Selbst wenn sie nur einfache Aufgaben erfüllen, lassen sich Programme in der Regel nicht vollständig austesten. Es ist zwar möglich, mithilfe von Tools zu messen, in welchem Umfang die Codebestandteile eines Programms in den Testverlauf einbezogen sind. Es ist dabei aber kaum möglich alle Zustände durchzuspielen, die das Programm im realen Betrieb einnehmen kann.
Dennoch ist der systematische Aufbau von Testfällen ein unentbehrliches Arbeitsmittel im Software-Engineering. In Projekten mit agiler Arbeitsweise spielen Tests eine so wichtige Rolle, dass Entwickler zuerst den Test-Code implementieren und erst anschließend die Funktionen programmieren, die den Testanforderungen genügen. Das Vorgehen schärft den Sinn für die spezifischen und allgemeinen Qualitätskriterien und ruft die Projektziele kontinuierlich in Erinnerung.
[1] Spillner, Andreas: Systematisches Testen von Software, Ein Einstieg, dpunkt.verlag Heidelberg 2008
[2] Edsger Wybe Dijkstra http://www.cs.utexas.edu/~EWD/transcriptions/EWD03xx/EWD340.html https://de.wikiquote.org/wiki/Edsger_Wybe_Dijkstra