Was sind automatisierte Tests?
In dieser Lerneinheit erfahren Sie mehr über die Vorteile der automatisierten Tests und die durchführbaren Testarten. Außerdem erfahren Sie, was einen guten Test ausmacht, und lernen einige Testtools kennen, die Ihnen zur Verfügung stehen.
Was sind automatisierte Tests?
Bei automatisierten Tests wird Software verwendet, um den Code auszuführen und die tatsächlichen Ergebnisse mit den erwarteten Ergebnissen zu vergleichen. Demgegenüber werden bei explorativen oder manuellen Tests in der Regel Anweisungen in einem Testplan von einem Menschen durchgeführt, um zu überprüfen, ob die Software erwartungsgemäß funktioniert.
Manuelle Tests haben ihre Vorteile. Da die Codebasis jedoch laufend umfangreicher wird, kann das Testen aller Features (einschließlich Grenzfälle) monoton, mühsam und fehleranfällig werden. Automatisierte Tests können dabei helfen, einen Teil dieser Last zu vermeiden und manuelle Tester in die Lage zu versetzen, sich auf das Wesentliche zu konzentrieren.
Die Testpyramide
Bei der Betrachtung automatisierter Tests werden Tests im Allgemeinen in Ebenen aufgeteilt. Mike Cohn schlägt dieses Konzept, die sogenannte Testpyramide, in seinem Buch Succeeding with Agile vor.
Obwohl es sich hierbei um eine vereinfachte Version des Modells von Cohn handelt, veranschaulicht das Konzept, dass das Schreiben von Tests, mit denen die Grundlagen der Software (1 in der Pyramide) wie Funktionen, Klassen und Methoden überprüft werden, am aufwändigsten ist. Der Aufwand wird nach und nach kleiner, wenn Features kombiniert werden, z. B. in der Benutzeroberflächenebene (2 in der Pyramide). Wenn Sie überprüfen können, ob alle Komponenten auf der unteren Ebene isoliert erwartungsgemäß funktionieren, muss bei Tests auf den höheren Ebenen nur überprüft werden, ob mehrere Komponenten zusammen das erwartete Ergebnis erzielen.
Wann sollten Tests geschrieben werden?
Die Antwort hängt in erster Linie von den jeweiligen Anforderungen und Ihrer Erfahrung beim Schreiben von Tests ab.
Es ist nie zu spät, um Tests für Code hinzuzufügen, den Sie bereits geschrieben und bereitgestellt haben. Dies gilt insbesondere für Features, die häufig nicht mehr richtig funktionieren oder den meisten Aufwand des Testteams erfordern.
Im Zusammenhang von Tests mit Continuous Integration- und Continuous Delivery-Pipelines werden die beiden Begriffe kontinuierliche Tests und Shift-Left-Tests verwendet.
Bei fortlaufenden Tests werden Tests frühzeitig im Entwicklungsprozess und bei jeder Änderung, die die Pipeline durchläuft, ausgeführt. Bei Shift-Left-Tests werden Softwarequalität und Tests zu einem frühen Zeitpunkt im Entwicklungsprozess betrachtet.
Entwickler fügen beispielsweise bei der Featureentwicklung häufig Testfälle hinzu und führen die gesamte Testsammlung aus, bevor die Änderung in die Pipeline geht. Durch diese Vorgehensweise wird sichergestellt, dass sich das erstellte Feature erwartungsgemäß verhält und vorhandene Features nicht negativ beeinflusst.
Abel Wang, Cloud Advocate bei Microsoft, erläutert in einem kurzen Video, wie Sie die Qualität in Ihrem Azure DevOps-Plan sicherstellen können.
Fragen an Abel
Bei Shift-Left-Tests müssen Tester am Entwurfsprozess beteiligt werden, sogar bevor der Code für das Feature geschrieben wird. Vergleichen Sie dies mit dem "Handoff"-Modell, bei dem das Testteam neue Features erst nach dem Entwurf und der Erstellung der Software testet. Ein spät im Prozess entdeckter Fehler kann sich auf den Zeitplan des Teams auswirken, und Fehler können Wochen oder sogar Monate, nachdem der Entwickler die Funktion ursprünglich erstellt hat, entdeckt werden.
Der Kompromiss
Automatisierte Tests ermöglichen einen Kompromiss. Obwohl sich Tester bei automatisierten Tests auf die Überprüfung der Endbenutzerfunktionalität konzentrieren können, müssen Entwickler u. U. mehr Zeit für das Schreiben und Verwalten Ihres Testcodes aufwenden.
Der entscheidende Punkt bei automatisierten Tests besteht jedoch darin, dass Tester nur qualitativ hochwertigen Code erhalten, d. h. Code, der erwiesenermaßen wie erwartet funktioniert. Daher können Entwickler Zeit einsparen, da sie weniger Fehler verarbeiten oder Code aufgrund eines Grenzfalls, der ursprünglich nicht berücksichtigt wurde umschreiben müssen.
Zusätzliche Vorteile
Die Dokumentation und die Möglichkeit zum einfacheren Refactoring Ihres Codes sind zwei zusätzliche Vorteile von automatisierten Tests.
Dokumentation
Manuelle Testpläne können als Dokumentation verwendet werden, die das gewünschte Softwareverhalten beschreibt und das Vorhandensein bestimmter Features erklärt.
Automatisierte Tests können denselben Zweck erfüllen. Der Code für automatisierte Tests verwendet häufig ein lesbares Format. Der bereitgestellten Eingaben stellen Werte dar, die Benutzer eingeben könnten. Jede zugehörige Ausgabe gibt das von den Benutzern erwartete Ergebnis an.
Tatsächlich verwenden viele Entwickler die testgesteuerte Entwicklung (TDD-Methode), indem sie den Testcode schreiben, ehe ein neues Feature implementiert wird. Die Idee besteht darin, Tests zu schreiben, die häufig als Spezifikationen bezeichnet werden, die zunächst fehlschlagen. Anschließend schreibt der Entwickler nach und nach den Code, um das Feature zu implementieren, bis alle Tests bestanden werden. Die Spezifikationen dokumentieren nicht nur die Anforderungen. Mit dem TDD-Prozess wird außerdem sichergestellt, dass nur der zum Implementieren des Features erforderliche Code geschrieben wird und kein überflüssiger Code.
Umgestaltung
Angenommen, Sie verfügen über eine umfangreiche Codebasis, die Sie umgestalten möchten, damit bestimmte Teile schneller ausgeführt werden. Woher wissen Sie, dass Ihr Refactoring nicht dazu führt, dass Teile Ihrer Anwendung negativ beeinflusst werden?
Automatisierte Tests dienen als eine Art Vertrag. Das heißt, Sie geben die Eingaben und die erwarteten Ergebnisse an. Wenn Sie über mehrere bestandenen Tests verfügen, können Sie Ihren Code besser ausprobieren und umgestalten. Wenn Sie eine Änderung vornehmen, müssen Sie lediglich die Tests ausführen und überprüfen, ob diese weiterhin bestanden werden. Nachdem Sie die Refactoringziele erreicht haben, können Sie Ihre Änderung an die Buildpipeline übergeben, damit alle davon profitieren können, aber das Risiko einer negativen Beeinflussung sinkt.
Welche Arten von automatisierten Tests gibt es?
Es gibt viele verschiedene automatisierte Tests. Jeder Test erfüllt einen bestimmten Zweck. Sie können beispielsweise Sicherheitstests ausführen, um zu überprüfen, ob nur autorisierte Benutzer auf eine Software oder bestimmte Features der Software zugreifen können.
Bei der Erwähnung von Continuous Integration und Buildpipeline beziehen wir uns in der Regel auf Entwicklungstests. Bei Entwicklungstests handelt es sich um Tests, die Sie ausführen können, bevor Sie die Anwendung in einer Test- oder Produktionsumgebung bereitstellen.
Mit Lint-Tests, einer Form der statischen Codeanalyse, wird beispielsweise der Quellcode überprüft, um festzustellen, ob er den Codierungsrichtlinien Ihres Teams entspricht. Einheitlich formatierter Code ist einfacher zu lesen und zu warten.
In diesem Modul verwenden Sie Komponententests und Code Coverage-Tests.
Bei Komponententests werden die grundlegendsten Komponenten des Programms oder der Bibliothek überprüft, z. B. eine einzelne Funktion oder Methode. Sie geben die Eingaben zusammen mit den erwarteten Ergebnissen an. Anschließend werden die einzelnen Tests durchgeführt und überprüft, ob die tatsächlichen Ergebnisse mit den erwarteten Ergebnissen übereinstimmen.
Angenommen, Sie verfügen über eine Funktion, die eine arithmetische Operation durchführt, die eine Division enthält. Sie können einige Werte angeben, deren Eingabe von den Benutzern erwartet wird. Sie können auch Grenzfallwerte wie 0 und -1 angeben. Wenn eine bestimmte Eingabe einen Fehler oder eine Ausnahme erzeugt, können Sie überprüfen, ob die Funktion denselben Fehler erzeugt.
Code Coverage-Tests berechnen den Prozentsatz Ihres Codes, der von den Komponententests abgedeckt wird. Code Coverage-Tests können bedingte Verzweigungen in Ihren Code einfügen, um sicherzustellen, dass eine Funktion abgedeckt wird.
Je größer der Code Coverage Prozentsatz ist, desto größer ist die Wahrscheinlichkeit, dass später in Code, der nicht vollständig getestet wurde, keine Fehler festgestellt werden. Sie müssen keinen Code Coverage-Prozentsatz von 100 erreichen. Wenn Sie beginnen, werden Sie wahrscheinlich feststellen, dass Sie einen niedrigen Prozentsatz haben, so erhalten Sie aber einen Ausgangspunkt, von dem aus weitere Tests hinzugefügt werden können, die problematischen oder häufig verwendeten Code abdecken.
Isolation von Komponententests
Wenn Sie sich mit Komponententests beschäftigen, stoßen Sie möglicherweise auf Begriffe wie Mocks, Stubs und Dependency Injection (deutsch Abhängigkeitsinjektion).
Bedenken Sie, dass ein Komponententest eine einzelne Funktion oder Methode überprüfen solle und nicht die Interaktion mehrerer Komponenten. Aber wie gehen Sie bei einer Funktion vor, die eine Datenbank oder einen Webserver aufruft?
Der Aufruf eines externen Diensts bricht nicht nur die Isolation auf, sondern kann die Ausführung verlangsamen. Wenn die Datenbank oder der Webserver ausfällt oder anderweitig nicht verfügbar ist, kann der-Aufruf auch den Testlauf unterbrechen.
Mit Techniken wie Mocking und Abhängigkeitsinjektion können Sie Komponenten erstellen, die diese externe Funktionalität imitieren. Ein entsprechendes Beispiel finden Sie später in diesem Modul.
Später können Sie Integrationstests ausführen, um zu überprüfen, ob die Anwendung mit einer echten Datenbank oder einem echten Webserver ordnungsgemäß funktioniert.
Was zeichnet einen guten Test aus?
Sie können einen guten Test zunehmend besser erkennen, wenn Sie eigene Tests schreiben und Tests lesen, die von anderen geschrieben wurden. Nachstehend finden Sie einige Richtlinien für den Einstieg:
- Testen Sie nicht um des Testens willen: Ihre Tests sollten einen Zweck erfüllen, der über das Abhaken von Checklisteneinträgen hinaus geht. Schreiben Sie Tests, mit denen überprüft wird, ob der kritische Code ordnungsgemäß funktioniert und bestehende Funktionalität nicht negativ beeinflusst werden.
- Halten Sie die Tests kurz: Tests sollten so schnell wie möglich beendet werden, besonders die Tests während der Entwicklungs- und Buildphasen. Wenn bei jeder Änderung in der Pipeline Tests ausgeführt werden, dürfen sie keinen Engpass bilden.
- Achten Sie darauf, dass die Tests reproduzierbar sind: Testläufe sollten stets zu demselben Ergebnis führen ganz gleich, ob sie auf Ihrem Computer, dem Computer eines Kollegen oder in der Buildpipeline ausgeführt werden.
- Sorgen Sie für fokussierte Tests: Ein häufiges Missverständnis besteht in der Annahme, dass mit Tests fremder Code getestet werden soll. Normalerweise sollten Sie nur Ihren eigenen Code testen. Wenn Sie beispielsweise in Ihrem Projekt eine Open-Source-Grafikbibliothek verwenden, müssen Sie diese Bibliothek nicht testen.
- Achten Sie auf die richtige Granularität: Bei Komponententests sollte ein einzelner Test beispielsweise nicht mehrere Funktionen oder Methoden kombinieren oder testen. Testen Sie jede Funktion einzeln, und schreiben Sie später Integrationstests, mit denen die reibungslose Interaktion mehrerer Komponenten überprüft wird.
Welche Typen von Testtools sind verfügbar?
Welche Testtools Sie verwenden, hängt vom Typ der zu erstellenden Anwendung und dem Typ der durchzuführenden Tests ab. Für UI-Tests können Sie bei vielen Webbrowsern und Betriebssystemen z. B. Selenium verwenden.
Unabhängig davon, in welcher Sprache Ihre Anwendung geschrieben ist, stehen Ihnen viele Testtools zur Auswahl.
Bei Java-Anwendungen können Sie beispielsweise für Lint-Tests „Checkstyle“ und für Komponententests „JUnit“ verwenden.
In diesem Modul verwenden wir NUnit für Komponententests, da es in der .NET-Community beliebt ist.