Worum geht es?
Der Wechsel von Manifest V2 zu Manifest V3 geht mit einer grundlegenden Änderung einher. In Manifest V2 befanden sich Erweiterungen auf einer Hintergrundseite. Die Kommunikation zwischen Erweiterungen und Webseiten wurde über Hintergrundseiten verwaltet. Manifest V3 verwendet stattdessen Service Worker.
In diesem Beitrag haben wir uns mit dem Testen von Service Workern für Erweiterungen befasst. Insbesondere prüfen wir, wie wir sicherstellen können, dass unser Produkt ordnungsgemäß funktioniert, wenn ein Service Worker gesperrt wird.
Wer sind wir?
eyeo hat es sich zur Aufgabe gemacht, Nutzern, Browsern, Werbetreibenden und Publishern einen ausgewogenen und nachhaltigen Online-Wertaustausch zu ermöglichen. Wir haben weltweit mehr als 300 Millionen Nutzer zur Anzeigenfilterung, die die Darstellung von Acceptable Ads zulassen, einem unabhängig abgeleiteten Anzeigenstandard, der bestimmt, ob eine Anzeige akzeptabel und nicht aufdringlich ist.
Unser Extension Engine-Team bietet eine Technologie zur Anzeigenfilterung, die einige der beliebtesten Browsererweiterungen auf dem Markt unterstützt, die Werbung blockieren, wie AdBlock und Adblock Plus mit mehr als 110 Millionen Nutzern weltweit. Darüber hinaus bieten wir diese Technologie als Open-Source-Bibliothek an, sodass sie auch anderen Browsererweiterungen zur Anzeigenfilterung zur Verfügung steht.
Was ist ein Service Worker?
Erweiterungsdienst-Worker sind der zentrale Event-Handler einer Browsererweiterung. Sie werden unabhängig im Hintergrund ausgeführt. Im Großen und Ganzen ist das in Ordnung. Im neuen Service Worker können wir die meisten Aktionen auf einer Hintergrundseite ausführen. Im Vergleich zu Hintergrundseiten gibt es jedoch einige Änderungen:
- Service Worker werden beendet, wenn sie nicht verwendet werden. Dazu müssen wir Anwendungsstatus beibehalten, anstatt globale Variablen zu verwenden. Das bedeutet, dass alle Einstiegspunkte in unser System für den Aufruf vorbereitet werden müssen, bevor das System initialisiert wird.
- Event-Listener müssen angehängt werden, bevor auf asynchrone Callbacks gewartet wird. Gesperrte Service Worker können weiterhin Ereignisse erhalten, die sie abonniert haben. Wenn der Listener für das Ereignis nicht in der ersten Runde der Ereignisschleife registriert ist, empfängt er das Ereignis nicht, falls der Service Worker durch dieses Ereignis geweckt wurde.
- Die Beendigung bei Inaktivität kann Timer unterbrechen, bevor sie abgeschlossen sind.
Wann werden Service Worker gesperrt?
Bei Chrome 119 haben wir festgestellt, dass Service Worker gesperrt werden:
- Nachdem 30 Sekunden lang keine Ereignisse empfangen oder Erweiterungs-APIs aufgerufen wurden.
- Nie, wenn die Entwicklertools geöffnet sind oder Sie eine ChromeDriver-basierte Testbibliothek verwenden (siehe Funktionsanfrage).
- Wenn Sie unter chrome://serviceworker-internals auf Beenden klicken.
Aktuelle Informationen finden Sie unter Service Worker-Lebenszyklus.
Warum ist das Testen ein Problem?
Ideal wäre es hilfreich gewesen, wenn es offizielle Leitlinien zum „Effizientes Testen von Service Workern“ oder Beispiele für funktionierende Tests hätten. Während unserer Tests der Service Worker standen wir vor einigen Herausforderungen:
- Die Testerweiterung enthält einen Zustand. Wenn der Service Worker beendet wird, gehen sein Status und die registrierten Ereignisse verloren. Wie würden wir die Daten in unserem Testablauf dauerhaft erhalten?
- Wenn Service Worker zu einem beliebigen Zeitpunkt gesperrt werden können, müssen wir testen, ob alle Funktionen bei einer Unterbrechung funktionieren.
- Selbst wenn wir in unseren Tests einen Mechanismus einführen würden, der Service Worker willkürlich sperrt, gibt es keine API im Browser, mit der sich dieser einfach sperren lässt. Wir haben das W3C-Team gebeten, diese Funktion hinzuzufügen, aber dies ist eine laufende Unterhaltung.
Service Worker-Sperrung testen
Wir haben mehrere Ansätze zum Auslösen der Service Worker-Sperrung während Tests ausprobiert:
Ansatz | Probleme mit dem Ansatz |
Beliebige Zeit warten (z. B. 30 Sekunden) | Dadurch werden Tests langsam und unzuverlässig, insbesondere wenn mehrere Tests ausgeführt werden. Bei Verwendung von WebDriver funktioniert es nicht, da WebDriver die DevTools API von Chrome verwendet und der Service Worker nicht gesperrt ist, wenn die Entwicklertools geöffnet sind. Selbst wenn wir es umgehen könnten, müssten wir trotzdem prüfen, ob der Service Worker gesperrt wurde, und wir haben keine Möglichkeit dazu. |
Endlosschleife im Service Worker ausführen | Laut Spezifikation kann dies zu einer Beendigung führen, je nachdem, wie der Browser diese Funktion implementiert. Chrome beendet den Service Worker in diesem Fall nicht, sodass wir das Szenario bei einer Sperrung des Service Workers nicht testen können. |
Nachricht im Service Worker zur Überprüfung der Sperrung | Durch das Senden einer Nachricht wird der Service Worker aktiviert. Damit kann geprüft werden, ob der Service Worker im Ruhemodus war. Die Ergebnisse für Tests, die sofort nach dem Anhalten des Service Workers überprüft werden müssen, werden dadurch aber nicht korrekt ausgegeben. |
Beenden Sie den Service Worker-Prozess mit chrome.processes.terminate() | Der Service Worker für die Erweiterung teilt einen Prozess mit anderen Teilen der Erweiterung. Wenn Sie diesen Prozess mit chrome.process.terminate() oder der GUI des Prozessmanagers von Chrome beenden, werden daher nicht nur der Service Worker, sondern auch alle Erweiterungsseiten beendet. |
Wir haben einen Test durchgeführt, bei dem geprüft wird, wie unser Code auf den gesperrten Service Worker reagiert, indem Selenium WebDriver chrome://serviceworker-internals/ geöffnet und für den Service Worker auf die Schaltfläche „Stopp“ geklickt hat.
Das ist bisher die beste Option, aber sie ist nicht ideal, da unsere Mocha-Tests, die auf einer Erweiterungsseite ausgeführt werden , dies nicht selbst erledigen können, sodass sie mit unserem WebDriver-Knotenprogramm kommunizieren müssen. Das bedeutet, dass diese Tests nicht nur mit der Erweiterung ausgeführt werden können. Sie müssen mit Selenium WebDriver ausgelöst werden.
Das folgende Diagramm zeigt, wie wir über verschiedene Abläufe mit der Browser-API kommunizieren und wie sich das Hinzufügen des Mechanismus zur Sperrung von Service Workern darauf auswirkt.
![Diagramm, das den Testablauf zeigt](https://developer.chrome.com/static/blog/eyeos-journey-to-testing-mv3-service worker-suspension/image/testing-flow.png?authuser=6&hl=de)
In einem neuen Ablauf, bei dem Service Worker gesperrt werden (blau), haben wir Selenium WebDriver hinzugefügt, um über die Benutzeroberfläche den Vorgang zu starten und so eine Aktion in der Browser-API auszulösen.
Es ist erwähnenswert, dass der Service Worker aufgrund eines Chrome-Fehlers mit Selenium WebDriver nicht wieder starten konnte. Dieses Problem wurde in Chrome 116 behoben. Glücklicherweise gibt es auch eine Problemumgehung: Wenn Sie festlegen, dass die Entwicklertools in Chrome automatisch auf jedem Tab geöffnet werden, startet der Service Worker ordnungsgemäß.
Das ist der Ansatz, den wir beim Testen verwenden, obwohl er nicht ideal ist, da das Klicken auf die Schaltfläche unter Umständen keine stabile API ist und das Öffnen der Entwicklertools (für ältere Browser) Kosten verursacht.
Wie deckt man die gesamte Funktionalität ab? Fuzzing-Tests
Als wir einen Mechanismus zum Testen der Sperrung hatten, mussten wir entscheiden, wie wir ihn in unsere Automatisierungs-Testsuiten integrieren. Wir haben unsere Standardtests in einer Umgebung durchgeführt, in der der Service Worker vor jeder Interaktion mit der Hintergrundseite gesperrt wurde, indem WebDriver auf der Seite chrome://serviceworker-internals/ auf Beenden klickte.
![Beispiel für einen Fuzz-Testlauf](https://developer.chrome.com/static/blog/eyeos-journey-to-testing-mv3-service worker-suspension/image/test-run.png?authuser=6&hl=de)
Die meisten, jedoch nicht alle Tests werden durchgeführt, da der Sperrmechanismus nicht vollständig stabil ist und manchmal unzuverlässig ist. Außerdem nimmt das Ausführen aller Testsuiten im Fuzz-Modus viel Zeit in Anspruch. Anstatt also alle „ähnlichen“ Fälle abzudecken, haben wir die kritischsten Pfade für Tests im Fuzz-Modus ausgewählt. Es ist erwähnenswert, dass wir bei Funktionstests im Fuzz-Modus die Zeitüberschreitungen der Tests erhöhen mussten, da das Anhalten und Neustarten von Service Workern mehr Zeit in Anspruch nimmt.
Diese Tests sind ein grober erster Durchlauf, bei dem viele Stellen aufgezeigt werden, an denen der Code fehlschlägt. Dabei werden aber nicht unbedingt alle subtilen Ursachen für Probleme durch das Sperren von Service Workern aufgedeckt.
Diese Arten von Tests werden intern als „Fuzz-Tests“ bezeichnet. Traditionell werden bei Fuzz-Tests ungültige Eingaben in Ihrem Programm ausgegeben und sichergestellt, dass das Programm angemessen reagiert oder zumindest nicht abstürzt. In unserem Fall bedeutet eine ungültige Eingabe, dass der Service Worker jederzeit gesperrt wird. Wir erwarten also, dass die Anzeigenfilterung wie gewohnt funktioniert. Das ist keine wirklich ungültige Eingabe, da dies in Manifest V3 erwartetes Verhalten ist, aber in Manifest V2 ungültig gewesen wäre, sodass es sich wie eine angemessene Terminologie anfühlt.
Zusammenfassung
Service Worker sind (neben den deklarativenNetRequest-Regeln) eine der größten Änderungen in Manifest V3. Die Migration zu Manifest V3 kann viele Codeänderungen in Browsererweiterungen und neue Ansätze für Tests erfordern. Außerdem müssen Entwickler von Erweiterungen mit dauerhaftem Status ihre Erweiterungen auf den Umgang mit einer unerwarteten Service-Worker-Sperrung vorbereiten.
Leider gibt es keine API, mit der die Sperrung auf eine einfache Art und Weise gehandhabt werden kann, die zu unserem Anwendungsfall passt. Da wir in einem frühen Stadium die Robustheit der Codebasis unserer Erweiterung gegenüber Sperrungsmechanismen testen wollten, mussten wir das Problem umgehen. Andere Entwickler von Erweiterungen, die vor ähnlichen Herausforderungen stehen, können diese Problemumgehung nutzen. Dies ist zwar in der Entwicklungs- und Wartungsphase zeitaufwendig, aber es lohnt sich, damit wir unsere Erweiterungen auch in einer Umgebung nutzen können, in der Service Worker regelmäßig gesperrt werden.
Auch wenn es bereits grundlegende Unterstützung für das Testen der Sperrung von Service Workern gibt, wünschen wir uns eine bessere Plattformunterstützung für das Testen von Service Workern innerhalb von Erweiterungen in Zukunft, da diese die Testausführungszeiten und den Wartungsaufwand erheblich verkürzen könnte.