Für stabile End-to-End-Tests (E2E) benötigen wir eine möglichst von außen isolierte Umgebung.
Flaky-Tests sind Tests, die aus Gründen fehlschlagen, die nichts mit Ihrem Code zu tun haben. Sie erschweren den Einsatz von E2E als zuverlässige Prüfung der Richtigkeit des Antrags. In extremen Fällen wird Ihr Team durch unzuverlässige Tests lernen, E2E-Ergebnisse zu ignorieren. Dies kann den Aufwand für die Automatisierung der Qualitätskontrolle (QS) zunichtemachen.
Der hier vorgestellte Ansatz geht auf zwei große Ursachen potenzieller Probleme in Ihren Testläufen ein:
Es gibt andere Ursachen für Schuppenbildung, die von diesem Ansatz nicht betroffen sind:
Bevor mein Team und ich meine Tests mit einem dedizierten Backend-Container durchführten, verwendeten wir einen unserer Nicht-Produktionsserver. Dieser Ansatz war in der Experimentierphase unserer E2E-Lösung in Ordnung.
Als es nur wenige Tests gab, konnten wir die Testergebnisse ohnehin nicht für Entscheidungen nutzen.
Als wir jedoch immer mehr Tests hinzufügten und längere Ausführungszeiten generierten, begann dieser Ansatz zu scheitern. Die Hauptprobleme waren wie folgt:
Eine Lösung für dieses Problem bestand darin, für jeden Testauftrag einen separaten Backend-Server und eine separate Datenbank bereitzustellen. Ohne Docker wäre dieser Ansatz eine große Herausforderung.
Docker-Container sind ein perfektes Werkzeug zum Erstellen einer geschlossenen Umgebung mit allem, was eine Anwendung zum Ausführen benötigt:
Für Ihren Test können Sie einen dedizierten Datenbankcontainer vorbereiten, der vorhersehbare Testdaten enthält. Auf diese Weise können Sie den Startpunkt bei jeder E2E-Ausführung exakt reproduzieren und Ihre Tests stabiler machen.
Sie können für Ihr Docker-Image verschiedene Tags verwenden, um die Testdatenbank zu versionieren. Dieselbe Testdatenbank kann auch in einer Entwicklungsumgebung verwendet werden. Für manuelle Tests in der Entwicklung benötigen Sie ähnliche Beispielentitäten wie für automatisierte Tests.
Wenn Sie Docker bereits für die Bereitstellung Ihres Backends verwendet haben, ist es ziemlich einfach, dasselbe Image für die Ausführung Ihres E2E wiederzuverwenden. In meinem Team stellen wir ein Backend als Container bereit und stellen Datenbank-URLs und Anmeldeinformationen als Umgebungsvariablen bereit.
Dieselbe Containerversion kann in der Produktion bereitgestellt oder in der kontinuierlichen Integration (CI) zum Ausführen von Tests verwendet werden – jede Umgebung bietet die richtigen Werte für die Verbindung mit der Datenbank.
Abhängig von Ihrer Bereitstellungsstrategie können Sie einen der folgenden Schritte ausführen:
Verwenden Sie die von Ihnen erstellten Container als Teil des Frontend-Builds.
Holen Sie sich die kompilierten Dateien und stellen Sie sicher, dass sie für die Tests über HTTP verfügbar sind.
In unserem Fall verwenden wir Option 2: Wir stellen die Anwendung als statische Dateien bereit, also haben wir einfach einen dedizierten Container erstellt, um die erstellten Dateien während der E2E-Jobausführung bereitzustellen.
Wir nutzen GitLab als Plattform zum Betrieb unserer CI. Jeder Job in GitLab wird in einem Container mit einem Image Ihrer Wahl ausgeführt. Neben dem Hauptcontainer können Sie Dienste definieren: Zusätzliche Container, die neben Ihren Tests ausgeführt werden. Die Konfiguration ist so einfach wie:
<job-name>: services: - name: <image> alias: <container-url>
Die verfügbaren Optionen ähneln denen in Docker Compose, sind jedoch eingeschränkter.
Ein „Fallstrick“ in der GitLab-Konfiguration besteht darin, die Variable FF_NETWORK_PER_BUILD
auf 1 zu setzen, wenn Sie den Diensten während des Testlaufs erlauben möchten, aufeinander zuzugreifen.
Irgendwann haben wir alle Tests parallel in einem Job ausgeführt. Damals war es notwendig, eine noch stärkere Isolierung durchzusetzen – jeder Test nutzte dasselbe Backend und dieselbe Datenbank.
Um dieses Problem zu umgehen, haben wir unsere Tests so aktualisiert, dass sie hauptsächlich auf den Zufallsdaten basieren, die wir direkt in den before
Abschnitt der Tests einfügen. Dadurch konnten Tests unabhängig von anderen Änderungen in anderen Threads ausgeführt werden.
Dieser Ansatz kann zunächst etwas schwierig sein, kann aber je nach Ihren Umständen sinnvoll sein.
Obwohl wir für jeden Testauftrag eine neue Datenbank erstellen, versuchen wir dennoch, dass unsere Tests die Anwendung in demselben Zustand verlassen, in dem sie sie vorgefunden haben. Vielleicht ist es ein Überbleibsel aus der Zeit, als wir Tests in einer gemeinsamen Umgebung durchgeführt haben.
Es ist nicht mehr entscheidend, kann aber in den folgenden Fällen während der Testentwicklung dennoch hilfreich sein:
Es gibt Fälle, in denen das Verschieben von Diensten in einen Container keine Option ist. Zum Beispiel:
In beiden Fällen können Sie zum Isolieren der Testläufe die Anforderungen verspotten, die an diese Dienste gehen. Dadurch wird verhindert, dass unvorhersehbare externe Dienste Ihre Testergebnisse beeinflussen. Ein Nachteil dieses Ansatzes besteht darin, dass Ihre Tests vom Kontext, in dem Ihre Anwendungen ausgeführt werden, abgekoppelt werden.
Wenn Mocks vorhanden sind, erkennen Ihre Tests keine Fälle, in denen sich Änderungen an diesen Diensten auf Ihre Anwendung auswirken.
Wenn Sie mehr über Tests oder andere programmbezogene Themen erfahren möchten, können Sie sich hier anmelden, um Updates zu erhalten, wenn ich verwandte Inhalte veröffentliche.