Stabile Produktlieferung mit Cypress
Fei Han
February 7, 2021
Das Apache APISIX Dashboard wurde entwickelt, um Benutzern die Bedienung von Apache APISIX über eine Front-End-Oberfläche so einfach wie möglich zu machen. Seit dem Start des Projekts gab es 552 Commits und 10 Releases. Bei einer so schnellen Produktiteration ist es wichtig, die Qualität des Open-Source-Produkts sicherzustellen. Aus diesem Grund haben wir ein E2E-Testmodul eingeführt, um eine stabile Produktlieferung zu gewährleisten.
Was ist Front-End E2E?
E2E steht für "End to End" und kann als "End-to-End"-Test übersetzt werden. Es simuliert das Benutzerverhalten, beginnend mit einem Einstiegspunkt und führt Schritt für Schritt Aktionen aus, bis ein Job abgeschlossen ist. Solide Tests verhindern, dass Codeänderungen die ursprüngliche Logik brechen.
Warum Cypress
Während der Auswahlphase haben wir Taiko, Puppeteer, TestCafe und Cypress verwendet, um Testfälle für das Erstellen von Routen zu schreiben. Wir haben mit jedem Testframework Fälle geschrieben, um deren jeweilige Funktionen zu erleben.
Taiko zeichnet sich durch einen intelligenten Selektor aus, der basierend auf Textinhalt und Positionsbeziehungen die Elemente, die Sie bedienen möchten, intelligent lokalisieren kann. Es hat niedrige Startkosten, sodass Sie Testfälle schnell abschließen können. Es ist jedoch nicht benutzerfreundlich beim Schreiben von Testfällen. Wenn der Benutzer versehentlich das Terminal verlässt, gehen alle geschriebenen Testfälle verloren, und wenn Sie einen vollständigen Testfall ausführen möchten, müssen Sie es mit anderen Testläufern kombinieren, was zweifellos die Lernkosten für den Benutzer erhöht.
Puppeteer hat die beste Leistung. Allerdings liegt der Schwerpunkt von Puppeteer nicht auf Tests. Es wird häufig für Web-Crawler verwendet. Unser Projekt begann mit Puppeteer, dem offiziellen E2E-Testframework, das von ANTD empfohlen wird. Nach einer Weile stellten wir fest, dass Puppeteer für Nicht-Front-End-Entwickler nicht so freundlich aussah und es schwierig war, andere Benutzer einzubeziehen. Wenn Benutzer Testfälle schreiben, macht das Fehlen einer intelligenten Elementpositionierung die Lernkurve sehr steil.
TestCafe ist überraschend einfach zu installieren, es hat einen eingebauten Wartemechanismus, sodass Benutzer nicht aktiv schlafen müssen, um auf Seiteninteraktionen zu warten, und es unterstützt gleichzeitige Multi-Browser-Tests, was für Multi-Browser-Kompatibilitätstests hilfreich ist. Der Nachteil ist, dass sein Debugging-Prozess nicht so benutzerfreundlich ist, und Sie müssen nach jeder Änderung des Testfalls einen neuen Anwendungsfall ausführen. Für die Entwickler ist es erforderlich, dass sie über grundlegende Javascript-Syntaxkenntnisse verfügen. Zweitens ist seine Ausführungsgeschwindigkeit im Vergleich zu mehreren anderen Frameworks relativ langsam, insbesondere bei der Ausführung von withText(), um Elemente zu finden.
Nach einem umfassenden Vergleich haben wir uns schließlich für Cypress als unser Front-End-E2E-Framework entschieden, wobei wir vier Hauptgründe anführen:
- Einfache Syntax
Die in Cypress-Tests verwendete Syntax ist sehr einfach und leicht zu lesen und zu schreiben. Mit ein wenig Übung können Sie das Erstellen von Testfällen beherrschen, was für Open-Source-Projekte wichtig ist, da es der Community, die an E2E-Testfällen interessiert ist, ermöglicht, mit minimalen Lernkosten am Schreiben von Testfällen teilzunehmen.
- Einfaches Debugging
Beim Debugging von Testfällen können wir den Test Runner von Cypress verwenden, der mehrdimensionale Daten präsentiert, die es uns ermöglichen, das Problem schnell zu lokalisieren.
- Zeigt den Status der Testfallausführung an, einschließlich der Anzahl der Erfolge, Fehler und laufenden Tests.
- Zeigt die gesamte Zeit an, die für die Ausführung des gesamten Testsets aufgewendet wurde.
- Ein eingebauter Selector Playground, der bei der Lokalisierung von Elementen hilft.
- Zeigt jeden Schritt der Ausführung für jeden Anwendungsfall an und bildet einen Snapshot, der Informationen über jeden Ausführungsschritt nach dessen Abschluss anzeigen kann.
- Aktive Community
Cypress hat eine große Community von Benutzern, und es gibt immer viele Menschen in der Community, die ihre Erfahrungen und Ideen teilen.
Dies ist hilfreich, wenn Probleme auftreten, und es ist wahrscheinlich, dass Sie auf Probleme stoßen, die andere zuvor bereits hatten. Außerdem können wir, wenn neue Funktionen angefordert werden, an der Community teilnehmen, indem wir diskutieren und Funktionen zu Cypress hinzufügen, die wir hinzufügen möchten, genau wie wir es in der APISIX-Community tun: der Community zuhören und sie zurückmelden.
- Klare Dokumentation
Die Dokumentationsstruktur von Cypress ist klarer und umfassender. In den frühen Nutzungsphasen konnten wir Cypress schnell in unser Projekt einführen und unseren ersten Fall basierend auf den offiziellen Dokumentationsrichtlinien schreiben. Darüber hinaus gibt es auf der Dokumentationsseite eine große Menge an Dokumentation, die den Benutzern eine gute Anleitung darüber gibt, was die beste Praxis ist.
Cypress und APISIX Dashboard
Derzeit gibt es 49 Testfälle, die für das APISIX Dashboard geschrieben wurden. Wir haben die entsprechende CI in GitHub Action konfiguriert, um sicherzustellen, dass der Code vor jedem Merge bestanden wird, um die Codequalität sicherzustellen. Wir teilen die Nutzung von Cypress im APISIX Dashboard mit Ihnen, indem wir auf Cypress-Best-Practices verweisen und sie mit unserem Projekt kombinieren.
- Häufig verwendete Funktionen werden in Befehle gekapselt.
Nehmen wir das Login als Beispiel. Das Login ist ein wesentlicher Bestandteil des Systems, daher kapseln wir es als Befehl, sodass der Login-Befehl vor jedem Fallaufruf aufgerufen werden kann.
Cypress.Commands.add("login", () => {
cy.request(
"POST",
'http://127.0.0.1/apisix/admin/user/login',
{
username: "user",
password: "user",
}
).then((res) => {
expect(res.body.code).to.equal(0);
localStorage.setItem("token", res.body.data.token);
});
});
beforeEach(() => {
// init login
cy.login();
})
- Extraktion des Selektors und der Daten als öffentliche Variablen.
Um es für den Benutzer intuitiver zu machen, die Bedeutung des Testcodes zu verstehen, extrahieren wir den Selektor und die Daten als öffentliche Variablen.
const data = {
name: 'hmac-auth',
deleteSuccess: 'Delete Plugin Successfully',
};
const domSelector = {
tableCell: '.ant-table-cell',
empty: '.ant-empty-normal',
refresh: '.anticon-reload',
codemirror: '.CodeMirror',
switch: '#disable',
deleteBtn: '.ant-btn-dangerous',
};
- Entfernen von cy.wait(someTime)
Wir haben cy.wait(someTime) in den frühen Tagen von Cypress verwendet, stellten jedoch fest, dass cy.wait(someTime) zu stark von der Netzwerkumgebung und der Leistung der Testmaschine abhängt, was dazu führen kann, dass Testfälle Fehler melden, wenn die Netzwerkumgebung oder die Maschinenleistung schlecht ist. Die empfohlene Praxis ist, es in Verbindung mit cy.intercept() zu verwenden, um explizit die Netzwerkressourcen anzugeben, auf die gewartet werden soll.
cy.intercept("https://apisix.apache.org/").as("fetchURL");
cy.wait("@fetchURL");
Zusammenfassung
Derzeit hat das APISIX Dashboard 49 Testfälle geschrieben. In Zukunft werden wir die Front-End-E2E-Abdeckung weiter verbessern und von der Community verlangen, dass sie zustimmt, Testfälle für jede neue Funktion oder Bugfix-Einreichung zu schreiben, um die Stabilität des Produkts sicherzustellen.
Willkommen, uns dabei zu helfen, ein weltweit führendes Gateway-Produkt zu verfeinern.
Projektadresse: https://github.com/apache/apisix-dashboard