Zu wenig zu tun führt manchmal zu einer verrückten Idee, und dieses Mal; Es ging darum, einen Headless-Browser in Go zu schreiben, mit vollständiger DOM-Implementierung und JavaScript-Unterstützung, durch Einbettung der v8-Engine.
Alles begann mit dem Schreiben einer HTMX-Anwendung und der Notwendigkeit, sie zu testen, was mich neugierig machte, ob es eine reine Go-Implementierung eines Headless-Browsers gab.
Die Suche nach „go headless browser“ führte nur zu Suchergebnissen, in denen es um die Automatisierung eines Headless-Browsers ging, d. h. die Verwendung eines echten Browsers wie Chrome oder Firefox im Headless-Modus.
Aber nichts im reinen Go.
Also habe ich angefangen, eines zu bauen.
Es mag albern erscheinen, weil das Schreiben eines Headless-Browsers nie wie ein echter Browser funktionieren wird; und würde daher nicht wirklich überprüfen, ob Ihre Anwendung in allen Browsern, die Sie unterstützen möchten, korrekt funktioniert. Dies ermöglicht Ihnen auch nicht, nette Funktionen wie Screenshots der Anwendung zu erhalten, wenn etwas nicht mehr funktioniert.
Warum dann?
Um in einer effektiven TDD-Schleife zu arbeiten, müssen Tests schnell sein. Eine langsame Testausführung entmutigt TDD und Sie verlieren die Effizienzvorteile, die eine schnelle Feedbackschleife bietet.
Die Verwendung der Browser-Automatisierung für diese Art der Überprüfung ist mit einem erheblichen Mehraufwand verbunden, und solche Tests werden normalerweise geschrieben, nachdem der Code geschrieben wurde; und als solche dienen sie nicht mehr als Hilfe beim Schreiben der korrekten Implementierung; werden aber im Nachhinein auf einen Wartungsaufwand reduziert; die nur gelegentlich einen Fehler entdecken, bevor es Ihre zahlenden Kunden tun.
Ziel ist es, ein Tool zu erstellen, das einen TDD-Prozess unterstützt. Um verwendbar zu sein, muss es im Prozess ausgeführt werden.
Es muss in Go geschrieben werden.
Wenn das DOM in Bearbeitung ist, können bessere Wrapper auf dem DOM geschrieben werden. Dies kann dazu beitragen, eine weniger fehlerhafte Schnittstelle für Ihre Tests bereitzustellen, wie es die Testbibliothek für JavaScript tut.
Anstatt von CSS-Klassennamen, Element-IDs oder der DOM-Struktur abhängig zu sein, schreiben Sie Ihre Tests in einer benutzerzentrierten Sprache, wie dieser.
Geben Sie „me@example.com“ in das Textfeld mit der Bezeichnung „E-Mail“ ein
Oder im hypothetischen Code.
testing.GetElement(Query{ role: "textbox", // The accessibility "name" of a textbox _is_ the label name: "Email", }).type("me@example.com")
Diesem Test ist es egal, ob die Bezeichnung als
Dadurch wird die Überprüfung des Verhaltens von UI-Änderungen entkoppelt; aber es erzwingt , dass der Text „E-Mail“ auf zugängliche Weise mit dem Eingabefeld verknüpft ist. Dies koppelt den Test an wie der Benutzer mit der Seite interagiert; einschließlich derjenigen, die bei der Nutzung Ihrer Seite auf Screenreader angewiesen sind.
Damit wird der wichtigste Aspekt von TDD erreicht; Tests zu schreiben, die an konkretes Verhalten gekoppelt sind.1
Obwohl es wahrscheinlich technisch möglich ist, dieselben Tests für einen Out-of-Process-Browser zu schreiben; Der Vorteil von nativem Code ist für die Art des Direktzugriffs auf das DOM, den Sie höchstwahrscheinlich für diese Art von Helfern benötigen, von entscheidender Bedeutung.
Um die Art des Tests zu veranschaulichen, verwende ich ein ähnliches Beispiel aus JavaScript; auch eine Anwendung, die HTMX verwendet. Der Test überprüft einen allgemeinen Anmeldefluss durch die Anforderung einer Seite, die eine Authentifizierung erfordert.
Es ist etwas lang, da ich hier den gesamten Setup- und Hilfscode in einer Testfunktion zusammengefasst habe.
testing.GetElement(Query{ role: "textbox", // The accessibility "name" of a textbox _is_ the label name: "Email", }).type("me@example.com")
Vereinfacht ausgedrückt bewirkt der Test Folgendes:
Intern startet der Test einen HTTP-Server. Da dies im Testprozess ausgeführt wird, ist es möglich, die Geschäftslogik zu verspotten und zu blockieren. Der Test verwendet jsdom, um mit dem HTTP-Server zu kommunizieren. die sowohl die HTML-Antwort in ein DOM analysieren, aber auch clientseitige Skripte in einer Sandbox ausführen, die initialisiert wurde, z. B. mit Fenster als globalem Bereich.3
Dies ermöglicht das Schreiben von Tests der HTTP-Schicht, bei denen die Validierung des Inhalts der Antwort nicht ausreicht. In diesem Fall; dass die Antwort von HTMX wie vorgesehen verarbeitet wird.
Aber abgesehen vom Warten auf einige HTMX-Ereignisse, um nicht zu früh (oder zu spät) fortzufahren, kümmert sich der Test eigentlich nicht um HTMX. Wenn ich HTMX aus dem Formular entferne und auf klassische Weiterleitungen zurückgreife, besteht der Test sogar noch.
(Wenn ich das HTMX-Tag