Alle Artikel

Flutter Web Integration Tests laufen doppelt

Flutter Testing Web

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
Till Friebe

Über Till Friebe

Teil des FriebeDev Teams - vier Geschwister aus Berlin, die gemeinsam Flutter Apps entwickeln. Mit über 300.000 Downloads und Projekten für Unternehmen wie get2Card und BlazeSQL.

Mehr über unser Team →

Bereit für Ihre App?

Lassen Sie uns in einem kostenlosen Erstgespräch über Ihr Projekt sprechen.

Kostenloses Erstgespräch