React -Integrationstests: größere Abdeckung, weniger Tests
Für interaktive Websites wie die mit React erstellten Integrationstests ist eine natürliche Wahl. Sie bestätigen, wie Benutzer mit Anwendungen ohne den zusätzlichen Aufwand von End-to-End-Tests interagieren.
Dieser Artikel zeigt es mit einer Übung, die mit einer einfachen Website beginnt, Unit -Tests und Integrationstests verwendet, um Verhaltensweisen zu überprüfen, und zeigt, wie Integrationstests mit weniger Codezeilen einen höheren Wert erreichen können. In diesem Artikel geht davon aus, dass Sie mit Testen in React und JavaScript vertraut sind. Die Vertrautheit mit der Scherz- und React -Testbibliothek kann hilfreich sein, aber nicht erforderlich.
Es gibt drei Arten von Tests:
- Unit -Tests überprüfen unabhängig einen Code. Sie sind leicht zu schreiben, können aber das Gesamtbild ignorieren.
- End-to-End-Test (E2E) Verwenden Sie ein automatisiertes Framework wie Cypress oder Selen, um wie Benutzer mit Ihrer Website zu interagieren: Seitenladen, Ausfüllen von Formularen, Klicken auf Schaltflächen und mehr. Sie sind normalerweise geschrieben und laufen langsamer, sind aber der wirklichen Benutzererfahrung sehr nahe.
- Integrationstests sind irgendwo dazwischen. Sie überprüfen, wie mehrere Einheiten einer Anwendung zusammenarbeiten, sind jedoch leichter als E2E -Tests. Zum Beispiel verfügt der Scherz mit einigen integrierten Versorgungsunternehmen, um Integrationstests zu erleichtern. Jest verwendet JSDOM im Hintergrund, um gemeinsame Browser -APIs mit weniger Overhead als Automatisierung zu simulieren, und seine leistungsstarken Spottwerkzeuge können externe API -Aufrufe simulieren.
Eine andere zu beachten: In React -Anwendungen werden Unit -Tests und Integrationstests auf die gleiche Weise geschrieben, und die Tools werden verwendet .
Reagentests beginnen
Ich habe eine einfache Reaktionsanwendung (auf GitHub verfügbar) mit einem Anmeldebildform erstellt. Ich habe es mit reqres.in verbunden, eine praktische API, die ich zum Testen von Front-End-Projekten verwendet habe.
Sie können sich erfolgreich anmelden:
... oder begegnen eine Fehlermeldung aus der API:
Die Codestruktur lautet wie folgt:
<code>LoginModule/ ├── components/ │ ├── Login.js // 渲染LoginForm、错误消息和登录确认│ └── LoginForm.js // 渲染登录表单字段和按钮├── hooks/ │ └── useLogin.js // 连接到API 并管理状态└── index.js // 将所有内容整合在一起</code>
Option 1: Unit -Tests
Wenn Sie gerne Tests wie ich schreiben - vielleicht können Sie Kopfhörer tragen und auf Spotify schöne Musik spielen -, dann können Sie für jede Datei möglicherweise nicht widerstehen, Unit -Tests zu schreiben.
Selbst wenn Sie kein Testbegeisterter sind, arbeiten Sie möglicherweise an einem Projekt, das "versuchen, gute Arbeit zu leisten" ohne klare Strategie, und die Testmethode lautet: "Ich denke, jede Datei sollte ihren eigenen Test haben?"
Dies sieht so aus (ich habe die Einheit im Test -Dateinamen für Klarheit hinzugefügt):
<code>LoginModule/ ├── components/ │ ├── Login.js │ ├── Login.unit.test.js │ ├── LoginForm.js │ └── LoginForm.unit.test.js ├── hooks/ │ ├── useLogin.js │ └── useLogin.unit.test.js ├── index.js └── index.unit.test.js</code>
Ich habe die Übung auf GitHub abgeschlossen, um alle diese Unit-Tests hinzuzufügen, und erstellte einen Test: Abdeckung: Einheitskript, um Deckungsberichte (ein integriertes Merkmal von Scherz) zu generieren. Wir können eine 100% ige Abdeckung über vier Testdateien der Unit -Test erzielen:
Eine 100% ige Abdeckung ist normalerweise überwältigend, ist jedoch für eine so einfache Codebasis möglich.
Lassen Sie uns in einen der für den Onlogin React -Haken erstellten Einheitstests graben. Wenn Sie nicht mit React -Hooks vertraut sind oder wie man sie testet, mach dir keine Sorgen.
test ('erfolgreicher Anmeldefluss', async () => { // erfolgreiche API -Antwort scherzen .spyon (Fenster, 'Fetch') .MockResolvedValue ({json: () => ({token: '123'})}); const {Ergebnis, WaitForRextUpdate} = renderhook (() => uselogin ()); act (() => { result.current.onsubmit ({{{ E -Mail: '[E -Mail geschützt]', Passwort: 'Passwort', }); }); // Setzen Sie den Status auf ausstehend erwarten (result.current.state) .toEqual ({{{{{{{{{ Status: 'ausstehend', Benutzer: null, Fehler: null, }); Warten Sie WaitForNextUpdate (); // Legen Sie den Status auf die Auflösung fest und speichern Sie die E -Mail -Adresse (result.current.state) .toEqual ({{{{{{{{ Status: 'gelöst', Benutzer: { E -Mail: '[E -Mail geschützt]', }, Fehler: null, }); });
Dieser Test ist interessant zu schreiben (da die Testbibliothek der React Hooks Tests zum Kinderspiel macht), aber einige Probleme haben.
Erstens ändert sich der interne Status der Testvalidierung von 'ausstehend' zu 'gelöst'; Diese Implementierungsdetails sind dem Benutzer nicht ausgesetzt, daher ist es möglicherweise nicht gut zu testen. Wenn wir die Anwendung neu umstellen, müssen wir diesen Test aktualisieren, auch wenn sich nichts aus der Sicht des Benutzers ändert.
Auch als Einheitstest ist dies nur ein Teil davon. Wenn wir andere Funktionen des Anmeldeprozesses überprüfen möchten, z. B. das Ändern des Submission -Schaltfläche in "Laden", müssen wir dies in einer anderen Testdatei tun.
Option 2: Integrationstests
Erwägen wir eine Alternative zum Integrationstest, um diesen Prozess zu validieren:
<code>LoginModule/ ├── components/ │ ├── Login.js │ └── LoginForm.js ├── hooks/ │ └── useLogin.js ├── index.js └── index.integration.test.js</code>
Ich habe diesen Test und einen Test implementiert: Abdeckung: Integrationsskript, um Berichte zu erstellen. Genau wie Unit -Tests können wir eine 100% ige Abdeckung erreichen, aber diesmal ist alles in einer Datei und benötigt weniger Codezeilen.
Hier sind die Integrationstests, die den erfolgreichen Anmeldungsprozess abdecken:
test ('erfolgreicher Login', async () => { Scherz .spyon (Fenster, 'Fetch') .MockResolvedValue ({json: () => ({token: '123'})}); machen(<loginmodule></loginmodule> ); const Emailfield = screen.getByrole ('textbox', {name: 'E -Mail'}); const passwordfield = screen.getByLabeltext ('Passwort'); const taste = screen.getByrole ('button'); // Füllen Sie das Formular fireEvent.change aus und senden Sie ein (E -MailField, {Ziel: {value: '[E -Mail geschützt]'}}); fireEvent.change (PasswortField, {Ziel: {value: 'password'}}); fireEvent.click (button); // Es legt den Laststatus erwartet (Taste) .ToBediSabled (); erwarten (button) .tohavextContent ('laden ...'); Warten Sie auf Waitfor (() => { // Es verbirgt das Formelement -Element -Erwartung (Taste) .not.TobeinThedocument (); erwarten (E -Mailfield) .Not.TobeinThedocument (); erwarten (passwordfield) .not.tobeinthedocument (); // Es zeigt den Erfolgstext und die E -Mail -Adresse const laggedintext = screen.getByText ('angemeldet AS'); erwarten (fooggedinText) .TobeinThedocument (); const EmailaddressText = screen.getByText ('[E -Mail geschützt]'); erwarten (EmailaddressText) .TobeinThedocument (); }); });
Ich mag diesen Test wirklich, weil er den gesamten Anmeldungsprozess aus der Perspektive eines Benutzers überprüft: Formulare, Laststatus und erfolgreiche Bestätigungsnachrichten. Integrationstests eignen sich hervorragend für React -Anwendungen, genau aufgrund dieses Anwendungsfalls. Die Benutzererfahrung ist das, was wir testen möchten, und dies beinhaltet fast immer mehrere verschiedene Codeausschnitte, die zusammenarbeiten .
Dieser Test versteht nicht die Komponenten oder Haken, die das erwartete Verhalten funktionieren, was schön ist. Solange die Benutzererfahrung gleich bleibt, können wir diese Implementierungsdetails neu schreiben und refaktorieren, ohne den Test zu brechen.
Ich werde nicht in den Anfangszustand des Anmeldungsprozesses und anderer Integrationstests für Fehlerbehandlungen eingehen, aber ich ermutige Sie, sie auf GitHub anzusehen.
Was ist also für Unit -Tests erforderlich ?
Machen wir einen Schritt zurück und überlegen Sie, wie wir entscheiden, was wir überhaupt testen müssen. LoginModule muss getestet werden, da es sich um eine Entität handelt, die Benutzer (andere Dateien in der Anwendung) mit Vertrauen verwenden können.
Andererseits müssen der Onlogin -Hook nicht testen, da es sich nur um die Implementierungsdetails der LoginModule handelt. Wenn sich unsere Anforderungen jedoch ändern und Onlogin Anwendungsfälle an anderer Stelle hat, müssen wir unsere eigenen (Einheiten-) Tests hinzufügen, um seine Funktionalität als wiederverwendbares Dienstprogramm zu überprüfen. (Wir müssen auch die Datei verschieben, da sie nicht mehr für LoginModule spezifisch ist.)
Unit -Tests haben weiterhin viele Anwendungsfälle, z. B. die Notwendigkeit, wiederverwendbare Selektoren, Haken und normale Funktionen zu überprüfen. Bei der Entwicklung Ihres Codes finden Sie es möglicherweise auch hilfreich, die Entwicklung von Unit -Tests zu verwenden, auch wenn Sie diese Logik später auf Integrationstests verschieben.
Darüber hinaus leistet Unit -Tests eine hervorragende Aufgabe, um mehrere Eingaben und Anwendungsfälle gründlich zu testen. Wenn mein Formular beispielsweise die Inline -Validierung für verschiedene Szenarien angezeigt hat (z. B. ungültiges E -Mail, fehlendes Passwort, zu kurzes Passwort), werde ich einen repräsentativen Fall im Integrationstest behandeln und dann in den speziellen Fall im Unit -Test eingraben.
Andere Vorteile
Jetzt, wo wir hier sind, möchte ich über einige Syntax -Tipps sprechen, die meine Integrationstests klar und ordentlich halten.
Löschen Sie Wait für Block
Unser Test muss die Latenz zwischen dem Ladezustand und dem erfolgreichen Status der LoginModule berücksichtigen:
const taste = screen.getByrole ('button'); fireEvent.click (button); erwarten (button) .not.tobeinThedocument (); // Zu schnell ist der Knopf immer noch da!
Wir können dies mit der Waitfor For Helper -Funktion der DOM -Testbibliothek tun:
const taste = screen.getByrole ('button'); fireEvent.click (button); Warten Sie auf Waitfor (() => { erwarten (button) .not.tobeinThedocument (); // ah, es ist viel besser});
Aber was ist, wenn wir einige andere Projekte testen wollen? Es gibt nicht viele gute Beispiele im Internet darüber, wie man damit umgeht, und in früheren Projekten habe ich andere Projekte außerhalb von Wartezeiten gestellt:
// WAIT -Taste wartet für (() => { erwarten (button) .not.tobeinThedocument (); }); // Testen Sie dann die Bestätigungsmeldung Const BestätigungText = getByText ('Anmelde als [E -Mail geschützt]'); erwarten (BestätigungsText) .TobeinThedocument ();
Dies funktioniert, aber ich mag es nicht, weil der Knopfzustand besonders aussieht, auch wenn wir die Reihenfolge dieser Aussagen leicht wechseln können:
// Warte auf die Bestätigungsnachricht wartet für (() => { const bestätigende text = getByText ('angemeldet als [E -Mail geschützt]'); erwarten (BestätigungsText) .TobeinThedocument (); }); // dann die Schaltfläche Erwartung testen (Taste) .Not.TobeinThedocument ();
Es scheint mir, dass es viel besser ist, alles zu gruppieren, was mit demselben Update in den Kellner für Rückrufe in Verbindung steht:
Warten Sie auf Waitfor (() => { erwarten (button) .not.tobeinThedocument (); const bestätigende text = screen.getByText ('angemeldet als [E -Mail geschützt]'); erwarten (BestätigungsText) .TobeinThedocument (); });
Ich mag diese Technik für einfache Behauptungen wie diese wirklich, aber in einigen Fällen kann es die Tests verlangsamen und auf einen Fehler warten, der unmittelbar außerhalb von Wartungen vorkommt. In diesem Beispiel sehen Sie in der React -Testbibliothek "Mehrere Behauptungen in einem einzigen Kellner für Rückruf".
Für Tests, die mehrere Schritte enthalten, können wir nacheinander mehrere Waitforen -Blöcke verwenden:
const taste = screen.getByrole ('button'); const Emailfield = screen.getByrole ('textbox', {name: 'E -Mail'}); // füllen Sie das Formular fireevent.change aus (E -MailField, {Ziel: {value: '[E -Mail geschützt]'}}); Warten Sie auf Waitfor (() => { // Überprüfen Sie, ob die Schaltfläche aktiviert ist (Schaltfläche) .not.tobediDabled (); erwarten (button) .tohaveTextContent ('subieren'); }); // Senden Sie das Formular fireEvent.click (Button); Warten Sie auf Waitfor (() => { // Überprüfen Sie, ob die Schaltfläche nicht mehr erwartet (Taste) .Not.TobeinThedocument (); });
Wenn Sie darauf warten, dass nur ein Element angezeigt wird, können Sie stattdessen eine FindBy -Abfrage verwenden. Es verwendet Kellner im Hintergrund.
Inline IT kommentiert
Ein weiterer Best -Practice -Test besteht darin, weniger, längere Tests zu schreiben. Auf diese Weise können Sie Testfälle mit wichtigen Benutzerprozessen korrelieren und gleichzeitig Tests isoliert halten, um ein unerwartetes Verhalten zu vermeiden. Ich stimme diesem Ansatz zu, aber er kann eine Herausforderung darstellen, um den Code zu organisieren und das erforderliche Verhalten zu dokumentieren. Wir brauchen zukünftige Entwickler, um zum Test zurückzukehren und zu verstehen, was es tut, warum es fehlschlägt usw.
Angenommen, eine dieser Erwartungen beginnt zu scheitern:
It ('verarbeitet einen erfolgreichen Anmeldeblust', async () => { // Verstecke den Beginn des Tests für Klarheit erwarten (Taste) .ToBediabled (); erwarten (button) .tohavextContent ('laden ...'); Warten Sie auf Waitfor (() => { erwarten (button) .not.tobeinThedocument (); erwarten (E -Mailfield) .Not.TobeinThedocument (); erwarten (passwordfield) .not.tobeinthedocument (); const bestätigende text = screen.getByText ('angemeldet als [E -Mail geschützt]'); erwarten (BestätigungsText) .TobeinThedocument (); }); });
Entwickler, die diesen Inhalt betrachten, können nicht leicht feststellen, was getestet wird, und es kann schwierig sein zu bestimmen, ob der Fehler ein Fehler ist (was bedeutet, dass wir den Code beheben sollten) oder eine Verhaltensänderung (was bedeutet, dass wir den Test beheben sollten).
Meine bevorzugte Lösung ist es, die wenig bekannte Testsyntax für jeden Test zu verwenden und einen Kommentar im Inline-Stil hinzuzufügen, in dem jedes zu testende Schlüsselverhalten beschrieben wird:
test ('erfolgreicher Login', async () => { // Verstecke den Beginn des Tests für Klarheit // Es legt den Ladestatus -Erwartung (Taste) .ToBediSabled () fest; erwarten (button) .tohavextContent ('laden ...'); Warten Sie auf Waitfor (() => { // Es verbirgt das Formelement -Element -Erwartung (Taste) .not.TobeinThedocument (); erwarten (E -Mailfield) .Not.TobeinThedocument (); erwarten (passwordfield) .not.tobeinthedocument (); // Es zeigt den Erfolgstext und die E -Mail -Adresse const bestätigt. erwarten (BestätigungsText) .TobeinThedocument (); }); });
Diese Kommentare integrieren sich nicht magisch in den Scherz. Wenn Sie also auf einen Fehler stoßen, entspricht der fehlgeschlagene Test Name den Parametern, die Sie an das Test -Tag übergeben haben, in diesem Fall "erfolgreiche Login". Die Fehlermeldungen von Scherz enthalten jedoch den umgebenden Code, sodass diese Kommentare immer noch dazu beitragen, fehlgeschlagenes Verhalten zu identifizieren. Wenn ich nicht aus einer Erwartung entferne, erhalte ich die folgende Fehlermeldung:
Um explizitere Fehler zu erhalten, gibt es ein Paket namens Scherz-Exepe-Message, mit dem Sie Fehlermeldungen für jede Erwartung definieren können:
Erwartung (Taste, 'Taste ist noch im Dokument'). Nicht.tobeinthEdocument ();
Einige Entwickler bevorzugen diesen Ansatz, aber ich finde ihn in den meisten Fällen ein bisschen zu körnig, als einzelner es beinhaltet normalerweise mehrere Erwartungen.
Nächste Schritte für das Team
Manchmal wünschte ich, wir könnten Linterregeln für den Menschen treffen. In diesem Fall können wir eine Vorzugs-Integrationstestregel für unser Team festlegen und es endet.
Leider müssen wir eine ähnliche Lösung finden, um die Entwickler in einigen Fällen zur Auswahl der Integrationstests zu ermutigen, z. B. das zuvor eingeführte LoginModule -Beispiel. Wie die meisten Dinge kommt es darauf an, dass das Team über Ihre Teststrategie diskutiert, einverstanden ist, was für das Projekt sinnvoll ist, und - vor allem - in ADR zu dokumentieren.
Bei der Entwicklung eines Testplans sollten wir eine Kultur vermeiden, die Entwickler dazu zwingt, Tests für jede Datei zu schreiben. Entwickler müssen in der Lage sein, fundierte Testentscheidungen mit Zuversicht zu treffen, ohne sich über ihr „Gesamtbetrieb“ zu sorgen. Der Deckungsbericht von Scherz kann dazu beitragen, dieses Problem zu lösen, indem eine Vernunftprüfung durchgeführt wird, auch wenn die Tests auf der Integrationsebene zusammengeführt werden.
Ich betrachte mich immer noch nicht als Experte für Integrationstests, aber diese Übung hat mir geholfen, einen Anwendungsfall aufzubrechen, bei dem Integrationstests mehr Wert als Unit -Tests bieten. Ich hoffe, dass das Teilen dieses Teilens mit Ihrem Team oder bei ähnlichen Übungen in Ihrer Codebasis Ihnen dabei hilft, Integrationstests in Ihren Workflow einzubeziehen.
Das obige ist der detaillierte Inhalt vonReact -Integrationstests: größere Abdeckung, weniger Tests. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

Video Face Swap
Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen

Es ist aus! Herzlichen Glückwunsch an das Vue -Team, dass es eine massive Anstrengung war und lange kommt. Alle neuen Dokumente auch.

Ich sage "Website" passt besser als "Mobile App", aber ich mag dieses Rahmen von Max Lynch:

Ich ließ jemanden mit dieser sehr legitimen Frage einschreiben. Lea hat gerade darüber gebloggt, wie Sie gültige CSS -Eigenschaften selbst aus dem Browser erhalten können. Das ist so.

Neulich habe ich dieses besonders schöne Stück von der Website von Corey Ginnivan entdeckt, auf der eine Sammlung von Karten aufeinander stapelt.

Wenn wir dem Benutzer direkt im WordPress -Editor Dokumentation anzeigen müssen, wie können Sie dies am besten tun?

Es gibt eine Reihe dieser Desktop -Apps, in denen das Ziel Ihre Website gleichzeitig in verschiedenen Dimensionen angezeigt wird. So können Sie zum Beispiel schreiben

Fragen zu lila Schrägstrichen in Flex -Layouts Bei der Verwendung von Flex -Layouts können Sie auf einige verwirrende Phänomene stoßen, wie beispielsweise in den Entwicklerwerkzeugen (D ...

CSS Grid ist eine Sammlung von Eigenschaften, die das Layout einfacher machen als jemals zuvor. Wie alles andere ist es eine kleine Lernkurve, aber das Gitter ist
