„Es nützt nichts! Ich kann mit den Integrationstests von Flutter keinen End-to-End-Test durchführen“, rief einer unserer Kunden vor etwa 9 Monaten aus. Ich fragte, was das Problem sei, und sie erklärten, dass sie für die Anmeldung die Google-Authentifizierung und das Paket google_sign_in verwendeten, es aber nicht möglich sei, die Integrationstests von Flutter für die Interaktion mit den Anmeldebildschirmen zu verwenden. Ich verstand immer noch nicht ganz, wo das Problem lag, und dann machte es Klick: Dieses Plugin verwendet native UI-Komponenten , mit denen die Integrationstests nicht funktionieren.
Ich war ziemlich enttäuscht, dass ich damals keine Lösung anbieten konnte und musste es dabei belassen. Spulen wir jedoch bis heute vor, stellt sich eine fantastische neue Lösung namens „Patrol“ vor
Einer der Hauptgründe, warum Entwicklungsteams Continuous Integration (CI)-Dienste nutzen
Es gibt vier Haupttestmethoden, die im Rahmen Ihres CI-Workflows automatisiert werden können. Da das Testen ein Thema für sich ist, fasse ich es kurz, aber die Verwendung einer Kombination dieser Testmethoden wird Ihnen helfen, die Qualität Ihrer App zu verbessern und Probleme eher früher als später zu erkennen.
Erstens gibt es „Unit-Tests“ , die üblicherweise zum isolierten Testen Ihrer Funktionen und Methoden verwendet werden, um sicherzustellen, dass sie wie erwartet funktionieren. Es können auch Unit-Tests geschrieben werden, um sicherzustellen, dass Ihre Geschäftslogik in verschiedenen Szenarien ohne unerwartete Ergebnisse funktioniert.
Als nächstes haben wir Flutter- „Widget-Tests“ , mit denen Sie Ihre UI-Komponenten testen und sicherstellen können, dass sie korrekt gerendert werden und wie erwartet funktionieren.
Dann gibt es noch den „Integrationstest“ , bei dem Sie testen, ob die Einheiten und Komponenten Ihrer Anwendung wie erwartet zusammenarbeiten.
Schließlich gibt es noch den „End-to-End-UI-Test“, bei dem Sie die Anwendung so testen, als ob sie von einem echten Benutzer verwendet würde. In einem CI-Workflow wird dies normalerweise mithilfe von Simulatoren oder Emulatoren automatisiert, um verschiedene Pfade durch Ihre App zu testen und sicherzustellen, dass nach Änderungen an Ihrem Code keine Probleme auftreten.
Hier steckte der Kunde, von dem ich eingangs sprach, fest, weil er seine End-to-End-UI-Tests nicht durchführen konnte, weil es nicht möglich war, sich bei der App anzumelden. Damals testeten sie eine „Dev“-Version, die den Anmeldeteil umging.
Dies ist jedoch nicht mehr erforderlich, da „Patrol“ verfügbar ist!
Also zunächst einmal: Was ist Patrol? Nun, ich denke, die Dokumente sagen es am besten:
Patrol ist ein neues Open-Source-UI-Testframework für Flutter, das von LeanCode entwickelt wurde. Es baut auf den vorhandenen Testtools von Flutter auf und ermöglicht es Ihnen, Dinge zu tun, die zuvor unmöglich waren. Mit Patrol können Sie auf native Funktionen der Plattform zugreifen, auf der die Flutter-App ausgeführt wird.
Das Wichtigste dabei ist, dass Sie damit auf die nativen Funktionen der Plattform zugreifen können, auf der Ihre Flutter- App ausgeführt wird.
Das bedeutet, dass Sie jetzt Dinge tun können wie:
Okay, das klingt großartig, aber wo ist der Haken?
Nun, es gibt keinen! Und außerdem ist es nicht nur kostenlos , sondern auch
Darüber hinaus führt Patrol auch „benutzerdefinierte Finder“ ein, die Ihnen eine präzisere Syntax zum Schreiben Ihrer Tests bieten. Sie können mehr darüber lesen
Um mit Patrol zu beginnen, müssen Sie die CLI installieren, die Patrol-Abhängigkeit zu Ihrer pubspec.yaml hinzufügen und einige Konfigurationen in Ihren iOS- und Android-Projekten einrichten.
LeanCode hat einige großartige Dokumentationen erstellt
Wenn Sie auf Probleme stoßen, erhalten Sie am besten Hilfe auf dem Patrol Community Discord- Server, dem Sie beitreten können
Wenn Sie Fehler finden, können Sie ein Problem melden
Um mit Patrol zu beginnen, müssen Sie die CLI installieren, die Patrol-Abhängigkeit zu Ihrer pubspec.yaml hinzufügen und einige Konfigurationen in Ihren iOS- und Android-Projekten einrichten.
LeanCode hat einige großartige Dokumentationen erstellt
Wenn Sie auf Probleme stoßen, erhalten Sie am besten Hilfe auf dem Patrol Community Discord- Server, dem Sie beitreten können
Wenn Sie Fehler finden, können Sie ein Problem melden
Nachdem Sie alles eingerichtet haben, beginnen wir mit dem Testen einiger nativer Funktionen. Um es selbst auszuprobieren, habe ich eine einfache Flutter-App mit einer erhöhten Schaltfläche eingerichtet, die beim Klicken einen nativen Warndialog öffnet.
Durch Klicken auf „OK“ oder „Abbrechen“ wird der Dialog einfach geschlossen.
Auch hier würde ich empfehlen, die eigene Dokumentation von Patrol zu verwenden, die Sie finden können
Für meinen Test wollte ich also auf die erhöhte Schaltfläche mit dem Text „Klick mich!“ klicken. Es handelt sich um ein Standard-Flutter-Widget, sodass es mit dem folgenden Patrol-Finder angetippt werden kann:
await $('Click me!').tap();
Anschließend sollte der native Dialog angezeigt werden, sodass wir nun mit der Interaktion mit einer nativen UI-Komponente beginnen können. Fügen wir also den nativen Finder hinzu, der es uns ermöglicht, auf die Schaltfläche „OK“ zu tippen:
await $('Click me!').tap(); await $.native.tap(Selector(text: 'OK'));
Das war einfach! Ich möchte auch den „Abbrechen“-Button testen, also lasst uns auf den „Klick mich!“-Button tippen. Klicken Sie erneut auf die Schaltfläche und tippen Sie dann auf die Schaltfläche „Abbrechen“ des nativen Dialogs, indem Sie wie folgt ein paar weitere Zeilen hinzufügen:
await $('Click me!').tap(); await $.native.tap(Selector(text: 'OK')); await $('Click me!').tap(); await $.native.tap(Selector(text: 'Cancel'));
Ihre fertige Testdatei sollte so aussehen:
import 'package:cmpatrol/main.dart'; import 'package:patrol/patrol.dart'; void main() { patrolTest( 'Native tests', nativeAutomation: true, ($) async { await $.pumpWidgetAndSettle(const MyApp()); await $('Click me!').tap(); await $.native.tap(Selector(text: 'OK')); await $('Click me!').tap(); await $.native.tap(Selector(text: 'Cancel')); await $('Click me!').tap(); await $.native.tap(Selector(text: 'NO')); }, ); }
Sie sollten diesen Test nun auf Ihrem Emulator oder einem echten Gerät ausführen können, indem Sie den Befehl zum Starten des Tests verwenden. Meine Integrationstestdatei hieß „button_test“ , also habe ich die Tests wie folgt vom Terminal aus gestartet:
patrol test -t integration_test/button_test.dart
Ob Ihre Tests erfolgreich sind oder nicht, sehen Sie direkt im Terminal. Wenn die Tests fehlschlagen, erhalten Sie einen Link zum vollständigen Testbericht. Alternativ: Wenn Sie Ihre Tests wie ich auf Android ausführen, können Sie auf den Bericht zugreifen, indem Sie im folgenden Verzeichnis auf index.html klicken:
./build/app/reports/androidTest/connected
Sie können weiter mit anderen nativen Funktionen experimentieren, z. B. dem Öffnen der Benachrichtigungsleiste, dem Deaktivieren des WLANs, dem Aktivieren des Dunkelmodus sowie dem Minimieren und Maximieren der App:
// minimize app await $.native.pressHome(); await $.native.openNotifications(); await $.native.disableWifi(); await $.native.enableDarkMode(); // maximize app await $.native.openApp();
⚠️ Beachten Sie, dass es nicht möglich ist, Ihre App vollständig zu schließen und dann erneut zu öffnen, da sonst der gesamte Test beendet und somit fehlgeschlagen würde.
Konsultieren Sie die Patrouille
Um Patrol in Ihre Arbeitsabläufe zu integrieren, müssen Sie zunächst die Patrol-CLI auf der Build-Maschine installieren. Dies dauert nur wenige Sekunden und sobald dies erledigt ist, können Sie Ihr Testskript ausführen. Nachfolgend finden Sie ein Beispiel dafür, wie Sie diese Schritte zum Abschnitt „scripts“ Ihrer codemagic.yaml- Konfigurationsdatei hinzufügen würden. Ich würde empfehlen, das Skript zur Installation der Patrol-CLI als einen der ersten Skriptschritte auszuführen. Anschließend können Sie Ihre Patrol-Tests entweder unmittelbar danach oder nach anderen Tests ausführen, die Sie möglicherweise auch vorher ausführen möchten.
Bevor Sie Ihre Patrol-Tests ausführen, müssen Sie den Emulator starten. Daher fügen wir ein Skript hinzu, um den Emulator zu starten und darauf zu warten, dass er vollständig gestartet ist. Beachten Sie, dass die Android-Emulatoren nicht auf Maschinen verfügbar sind, die Apple Silicon M1- oder M2-Maschinen verwenden, da das Apple Virtualization Framework keine verschachtelte Virtualisierung unterstützt. Daher würde ich beim Testen von Android-Apps die Verwendung einer Linux- Instanz empfehlen.
Der Skriptabschnitt Ihrer codemagic.yaml sollte etwa so aussehen:
scripts: ... - name: Install Patrol CLI script: dart pub global activate patrol_cli - name: Launch Android emulator script: | cd $ANDROID_HOME/tools emulator -avd emulator & adb wait-for-device - name: Run tests with Patrol script: patrol test -t integration_test/your_test.dart ignore_failure: true ...
Die Patrol-Testergebnisse sind auch im JUnit-XML- Format verfügbar, was bedeutet, dass sie in den Build-Protokollen auf dem Codemagic-Build-Übersichtsbildschirm angezeigt werden können. Sie müssen lediglich die Eigenschaft test_report im Pfad zur generierten JUnit-XML-Datei hinzufügen. Sie können die Eigenschaft „ignore_failure“ mit einem booleschen Wert verwenden, um zu steuern, ob der Rest des Workflows weiter ausgeführt werden soll oder nicht. Wenn Sie Ihre Ergebnisse wie im nächsten Abschnitt beschrieben in ein Testmanagementsystem hochladen möchten, sollten Sie dies auf true setzen.
Hier ist ein Beispiel dafür, wie Ihr Skript aussehen sollte:
scripts: ... - name: Run tests with Patrol script: | patrol test -t integration_test/your_test.dart test_report: build/app/outputs/androidTest-results/connected/*.xml ignore_failure: true ...
Ein fehlgeschlagener Test könnte etwa so aussehen:
Möglicherweise möchten Sie außerdem die Ausgabe des Testberichts als Build-Artefakt sammeln, damit Sie den vollständigen Bericht anzeigen können, falls Fehler auftreten. Dadurch steht der Bericht als ZIP-Datei auf dem Build-Übersichtsbildschirm im Abschnitt „Artefakte“ auf der linken Seite zum Download zur Verfügung. Der einfachste Weg, dies zu tun, besteht darin, das Verzeichnis, in dem sich die Berichtsdateien befinden, in das Verzeichnis zu kopieren, das Codemagic zum Exportieren von Artefakten verwendet. Es gibt eine integrierte Umgebungsvariable namens $CM_EXPORT_DIR , die auf dieses Verzeichnis verweist, das Sie in Ihrem Skript verwenden können.
Das Skript dafür sollte wie folgt aussehen:
scripts: ... - name: Export Patrol test report script: | cp -r build/app/reports/androidTests/connected $CM_EXPORT_DIR/report ...
Patrol hat endlich das Problem der Durchführung von UI- und Integrationstests mit nativen Funktionen überwunden. Es ist jetzt möglich, native Funktionen zu testen und mit Authentifizierungsabläufen und nativen Dialogen zu interagieren und sogar native Funktionen wie WLAN, Mobilfunk und Dunkelmodus umzuschalten und sogar Ihre App zu minimieren und zu maximieren. Darüber hinaus ist es sowohl kostenlos als auch Open Source und bietet eine Lösung für ein echtes Problem, das seit der Einführung von Flutter besteht. Darüber hinaus lässt es sich ganz einfach hinzufügen und in Ihren Codemagic-Workflows verwenden. Wenn Sie die großartige Arbeit von LeanCode unterstützen möchten, geben Sie Patrol ein „Gefällt mir“ auf pub.dev
Dieser Artikel wurde von Kevin Suhajda, Head of Solutions Engineering bei, verfasst
Auch hier veröffentlicht.