Es gibt einen Bug mit flutter drive -d chrome. Wenn man den Befehl ausführt, wird der Test zweimal ausgeführt. Einmal als Hintergrundprozess und einmal im Vordergrund. Als Entwickler bekommt man nichts von dem Hintergrundprozess mit. Mir ist es bloß aufgefallen, weil der Test sich merkwürdig verhalten hat, z.B. in meinen Test wird ein Testaccount erstellt und je nach Timing hat der Account schon existiert.
Es gibt das Issue bereits auf GitHub, bislang gab es kein für mich zufriedenstellende Lösung.
Ich hab jetzt ein Workaround gefunden, der alle meine Bedingungen erfüllt:
void main() {
if (kIsWeb && html.window.navigator.userAgent.contains('HeadlessChrome')) {
return;
}
// Tests hier
}
Die Idee ist, den Prozess, der im Hintergrund gestartet wird, direkt im Anfang zu beenden. Um zu unterscheiden, welcher Prozess gerade ist, benutze ich ich den UserAgent, ob ‘HeadlessChrome’ beinhaltet. Wenn ja, kann ich ihn einfach beenden.
Die anderen Lösungen und warum sie nicht für mich funktioniert haben
-d web-server statt -d chrome
flutter drive -d web-server --browser-name chrome --no-headless
Das ist die am häufigsten vorgeschlagene Lösung. Sie funktioniert – es wird nur eine Chrome-Instanz gestartet. Aber: Es gibt keine Logs im Terminal. Alle print()-Statements und Fehlerausgaben verschwinden. Für Debugging unbrauchbar.
Tests auf Android/Desktop statt Web
Manche Teams umgehen das Problem, indem sie ihre Integration Tests auf Android oder Desktop laufen lassen. Das funktioniert, testet aber nicht das Web-spezifische Verhalten. Einige Packages (z.B. Riverpod) verhalten sich auf Web anders – ein grüner Desktop-Test garantiert keine funktionierende Web-App.
Firestore-Flag als Synchronisation
Ein kreativer Workaround: Ein Firestore-Dokument als Flag nutzen, um zu erkennen, welche Instanz zuerst da war. Die zweite Instanz wartet dann, bis die erste fertig ist. Das funktioniert, ist aber extrem aufwändig und erfordert Firestore-Setup nur für diesen Workaround.
Meine Lösung: HeadlessChrome erkennen
Mein Ansatz ist simpler: Die zweite Instanz läuft als HeadlessChrome. Das steht im User Agent. Ein Check am Anfang der Tests beendet sie sofort:
if (kIsWeb && html.window.navigator.userAgent.contains('HeadlessChrome')) {
return;
}
- Keine Änderung am Befehl nötig
- Logs bleiben erhalten
- Kein externes Setup erforderlich
- Funktioniert mit bestehenden CI/CD-Pipelines