Unterschiedliche Arten von Softwaretests

Hier findest du einen Vergleich zwischen verschiedenen Arten von Softwaretests, beispielsweise Unit-Tests, Integrationstests, Funktionstests und Akzeptanztests.

Sten Pittet Sten Pittet

Es gibt viele verschiedene Arten von Tests, mit denen du sicherstellen kannst, dass Änderungen an deinem Code wie erwartet funktionieren. Nicht alle Tests sind jedoch gleich, und wir werden hier sehen, wie sich die wichtigsten Testverfahren voneinander unterscheiden.

Manuelle oder automatische Tests?

Grundsätzlich müssen wir zwischen manuellen und automatischen Tests unterscheiden. Manuelle Tests werden von einem Menschen durchgeführt, der sich durch die Anwendung klickt oder mit der Software und APIs und entsprechenden Tools interagiert. Dies ist sehr teuer, da jemand eine Umgebung einrichten und die Tests durchführen muss. Außerdem entstehen leicht Fehler, wenn sich der Tester vertippt oder versehentlich Schritte aus dem Testskript auslässt.

Automatische Tests werden von einem Computer durchgeführt, der ein zuvor geschriebenes Testskript ausführt. Die Komplexität dieser Tests kann sehr unterschiedlich sein – vom Überprüfen einer einzigen Methode in einer Klasse bis hin zur Ausführung einer Abfolge komplexer Aktionen, die in der UI zu denselben Ergebnissen führen sollen. Diese Tests sind wesentlich solider und zuverlässiger als manuelle Tests. Allerdings hängt die Qualität der automatischen Tests von der Qualität der Testskripts ab. Wenn du gerade erst in das Thema "Tests" einsteigst, erhältst du in unserem Tutorial zu Continuous Integration Tipps zum Erstellen deiner ersten Testsuite. Du interessiert dich für andere Testtools? Schau dir diese Tutorials zum Thema DevOps-Tests an.

Automatische Tests sind ein wichtiger Bestandteil von Continuous Integration und Continuous Delivery. Du kannst damit sehr gut den QA-Prozess skalieren, wenn du deiner Anwendung neue Features hinzufügst. Auch manuelle Tests haben weiterhin ihre Berechtigung, wenn es sich um sogenannte explorative Tests handelt, wie wir in diesem Leitfaden sehen werden.

Die unterschiedlichen Arten von Tests

Unit-Tests

Unit-Tests sind sehr einfach und erfolgen nah an der Quelle der Anwendung. Sie dienen zum Testen einzelner Methoden und Funktionen der von der Software verwendeten Klassen, Komponenten oder Module. In der Regel lassen sich Unit-Tests kostengünstig automatisieren und können von einem Continuous Integration-Server sehr schnell durchgeführt werden.

Integrationstests

Mit Integrationstests wird sichergestellt, dass verschiedene von deiner Anwendung genutzte Module oder Services problemlos ineinandergreifen. So kann beispielsweise die Interaktion mit der Datenbank oder das Zusammenspiel von Mikroservices getestet werden. Tests dieser Art sind kostspieliger, weil dafür mehrere Teile der Anwendung funktionsfähig sein müssen.

Funktionstests

Funktionstests konzentrieren sich auf die Geschäftsanforderungen einer Anwendung. Sie verifizieren nur die Ausgabe einer Aktion und überprüfen bei der Durchführung dieser Aktion nicht die Zwischenzustände des Systems.

Integrationstests und Funktionstests sind nicht ganz leicht auseinanderzuhalten, da bei beiden mehrere Komponenten miteinander interagieren müssen. Der Unterschied besteht darin, dass mit einem Integrationstest vielleicht nur überprüft wird, ob Datenbankabfragen generell möglich sind, während bei einem Funktionstest ein bestimmter, von den Produktanforderungen vorgegebener Wert aus der Datenbank abgerufen wird.

End-to-End-Tests

Bei End-to-End-Tests wird der Umgang des Benutzers mit der Software in einer vollständigen Anwendungsumgebung repliziert. Auf diese Weise wird das ordnungsgemäße Funktionieren von Benutzerabläufen überprüft. Die Szenarien können ganz einfach sein (z. B. Laden einer Website, Anmeldevorgang) oder auch sehr komplex (z. B. E-Mail-Benachrichtigungen, Onlinezahlungen).

End-to-End-Tests sind sehr nützlich, aber auch kostspielig und in automatisierter Form unter Umständen schwer zu verwalten. Es empfiehlt sich, nur wenige End-to-End-Tests zu implementieren und stattdessen eher auf weniger aufwendige Testarten (Unit- und Integrationstests) zu setzen, um riskante Änderungen schnell erkennen zu können.

Akzeptanztests

Akzeptanztests sind formelle Tests, mit denen überprüft wird, ob ein System die entsprechenden geschäftlichen Anforderungen erfüllt. Dazu muss die gesamte Anwendung funktionsfähig sein. Der Schwerpunkt liegt auf dem replizierten Benutzerverhalten. Darüber hinaus können die Tests eingesetzt werden, um die Systemleistung zu messen und Änderungen abzulehnen, wenn bestimmte Ziele nicht erfüllt werden.

Leistungstests

Leistungstests überprüfen das Verhalten des Systems, wenn es unter erheblicher Belastung steht. Diese Tests sind nicht funktionsfähig und können verschiedene Formen haben, um die Zuverlässigkeit, Stabilität und Verfügbarkeit der Plattform nachzuvollziehen. Zum Beispiel kann dies in Form von Beobachtung der Antwortzeiten bei der Ausführung einer hohen Anzahl von Anfragen geschehen. Oft wird auch untersucht, wie sich das System mit einer erheblichen Anzahl von Daten verhält.

Die Implementierung und die Durchführung von Leistungstests sind naturgemäß relativ teuer. Diese Tests können jedoch Aufschluss darüber geben, ob neue Änderungen die Systemleistung gefährden.

Smoke-Tests

Smoke-Tests sind einfache Tests zum Überprüfen der grundlegenden Funktionalität der Anwendung. Sie sollen schnell auszuführen sein und dir zeigen, ob die wichtigsten Features deines Systems wie erwartet funktionieren.

Smoke-Tests können unmittelbar nach der Erstellung eines neuen Builds nützlich sein, um zu entscheiden, ob du teurere Tests durchführen kannst oder nicht, oder um direkt nach einem Deployment sicherzustellen, dass die Anwendung in der neu bereitgestellten Umgebung ordnungsgemäß ausgeführt wird.

Automatisierung von Tests

Es ist möglich, alle oben genannten Tests von Menschen durchführen zu lassen. Dies wäre allerdings sehr teuer und kontraproduktiv. Ein Mensch kann nur eine begrenzte Anzahl von Aktionen reproduzierbar und zuverlässig durchführen. Computer arbeiten viel schneller und beschweren sich auch bei der hundertsten Wiederholung eines simplen Anmeldetests nicht.

Um Tests automatisieren zu können, musst du sie zunächst unter Verwendung eines zu deiner Anwendung passenden Test-Frameworks programmgesteuert schreiben. PHPUnit, Mocha und RSpec sind Beispiele für Test-Frameworks, die du für PHP, JavaScript bzw. Ruby nutzen kannst. Da es für jede Sprache viele Optionen gibt, musst du unter Umständen recherchieren und Entwickler-Communitys zu Rate ziehen, um das optimale Framework für deine Anforderungen zu ermitteln.

Wenn deine Tests per Skript über das Terminal ausgeführt werden können, kannst du sie von einem Continuous Integration-Server wie Bamboo oder einem Cloud-Service wie Bitbucket Pipelines automatisch ausführen lassen. Diese Tools überwachen deine Repositorys und führen die Testsuite aus, sobald neue Änderungen in das Haupt-Repository übernommen werden.

Jede Push-Übertragung in das Repository wird dank Bitbucket Pipelines überprüft.

Wenn du gerade erst in das Thema "Tests" einsteigst, erhältst du in unserem Tutorial zu Continuous Integration Tipps zum Erstellen deiner ersten Testsuite.

Exploratives Testen

Je mehr Features und Verbesserungen in deinen Code aufgenommen werden, umso mehr Tests sind nötig, um das ordnungsgemäße Funktionieren aller Systeme sicherzustellen. Außerdem solltest du jede Fehlerkorrektur in den Tests für neue Releases berücksichtigen, damit dieser Fehler nicht in einem späteren Release erneut auftritt. Automatisierung ist dafür entscheidend. Früher oder später wird das Schreiben von Tests Teil deines Entwicklungs-Workflows werden.

Die Frage ist also, ob sich manuelle Tests noch lohnen. Die kurze Antwort lautet: Ja! Der Schwerpunkt sollte dabei auf sogenannten explorativen Tests liegen, die zum Erkennen weniger offensichtlicher Fehler dienen.

Eine explorative Testsitzung sollte eine Dauer von zwei Stunden nicht überschreiten und über einen klaren Spielraum verfügen, damit sich die Tester auf einen bestimmten Bereich der Software konzentrieren können. Sobald alle Tester informiert wurden, müssen sie verschiedene Aktionen ausprobieren, um zu überprüfen, wie sich das System verhält. Diese Art von Tests ist natürlich teuer, aber sie sind sehr hilfreich, um Probleme mit der Benutzeroberfläche aufzudecken oder komplexe Benutzer-Workflows zu überprüfen. Es lohnt sich besonders, wenn deiner Anwendung eine wichtige neue Funktion hinzugefügt wird, um zu verstehen, wie sie sich unter Extrembedingungen verhält.

Ein Hinweis zu Tests

Zum Abschluss dieses Leitfadens sollten wir über das Ziel von Tests sprechen. Während es zwar wichtig ist zu testen, ob Benutzer deine Anwendung verwenden können (Kann ich mich einloggen? Kann ich ein Objekt speichern?), ist es ebenso wichtig zu testen, ob dein System nicht abstürzt, wenn ungültige Daten oder unerwartete Aktionen ausgeführt werden. Du musst vorhersehen, was passieren würde, wenn ein Benutzer einen Tippfehler macht, ein unvollständiges Formular speichern möchte oder die falsche API verwendet. Du musst überprüfen, ob Daten leicht kompromittierbar sind und ob unbefugte Personen Zugriff auf eine Ressource erhalten können. Eine gute Testsuite sollte versuchen, deine App zum Absturz zu bringen, um Grenzen auszuloten.

Und schließlich sind Tests auch Code! Vergiss sie also nicht während der Code-Prüfung, da sie das finale Gate zur Produktion sein könnten.