Heim > Web-Frontend > js-Tutorial > Hauptteil

Unit, Integration und ETesting in einem Beispiel mit Jest

DDD
Freigeben: 2024-11-20 19:53:15
Original
235 Leute haben es durchsucht

Einführung

Viele Entwickler stehen beim Testen ihres Codes vor Herausforderungen. Ohne ordnungsgemäße Tests können Fehler durchschlüpfen, was zu frustrierten Benutzern und kostspieligen Korrekturen führt.

In diesem Artikel erfahren Sie, wie Sie Unit-, Integrations- und End-to-End-Tests mit Jest, Supertest und Puppeteer effektiv an einem sehr einfachen Beispiel anwenden, das mit Node.js und MongoDB erstellt wurde.

Ich hoffe, dass Sie am Ende dieses Artikels ein klares Verständnis dafür haben, wie Sie diese Art von Tests in Ihren eigenen Projekten anwenden können.

?‍? Das vollständige Beispiel finden Sie hier in diesem Repo.

Wir stellen unsere Abhängigkeiten vor

Bevor ich unsere Abhängigkeiten installiere, möchte ich zunächst unser Beispiel vorstellen. Es handelt sich um ein sehr einfaches Beispiel, bei dem ein Benutzer die Registrierungsseite öffnen, seine Registrierungsdaten festlegen, auf die Registrierungsschaltfläche klicken und seine Informationen in der Datenbank speichern kann.

In diesem Beispiel verwenden wir die folgenden Pakete:

npm install --save jest express mongoose validator
npm install --save-dev jest puppeteer jest-puppeteer mongodb-memory-server supertest npm-run-all
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Die meisten dieser Abhängigkeiten sind unkompliziert, aber hier finden Sie Erläuterungen zu einigen davon:

  • Puppenspieler: Ermöglicht die Steuerung eines Headless-Browsers (Chrome) für automatisierte Tests und Web-Scraping.
  • Jest-Puppeteer: Es ist für Jest voreingestellt, das Puppeteer integriert, was die Einrichtung für die Ausführung von End-to-End-Tests in einer Browserumgebung vereinfacht. Sie können es als Voreinstellung in der Datei jest.config.js verwenden und das Puppeteer-Verhalten über eine Datei namens jest-puppeteer.config.js anpassen.
  • mongodb-memory-server: Es handelt sich um ein Dienstprogramm, das eine In-Memory-MongoDB-Instanz zum schnellen und isolierten Testen von Datenbankinteraktionen hochfährt.
  • npm-run-all: Ein CLI-Tool zum parallelen oder sequenziellen Ausführen mehrerer npm-Skripte.

Unit-Tests

  • Definition: Unit-Tests konzentrieren sich auf das isolierte Testen einzelner Komponenten oder Funktionen. Das Ziel besteht darin, zu überprüfen, ob jede Codeeinheit wie erwartet funktioniert.
  • Geschwindigkeit: Unit-Tests sind in der Regel sehr schnell, da sie kleine Codeteile testen, ohne auf externe Systeme oder Datenbanken angewiesen zu sein.
  • Beispiel: In unserem Beispiel für die Benutzerregistrierung könnte ein Komponententest die Funktion überprüfen, die eine E-Mail-Adresse validiert. Es würde beispielsweise überprüfen, ob die Funktion user@example.com korrekt als gültig identifiziert, während user@.com oder user.com abgelehnt wird.

Gut, lass uns das in Code übersetzen.

Einrichten der Unit-Testumgebung

Um Ihre Unit-Tests ohne unvorhersehbares Verhalten auszuführen, sollten Sie die Mock-Funktionen vor jedem Test zurücksetzen. Sie können dies mit dem Hook „beforeEach“ erreichen:

// setup.unit.js

beforeEach(() => {
  jest.resetAllMocks();
  jest.restoreAllMocks();
}); 
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Testen der E-Mail-Validierung

In diesem Fall möchten wir die Funktion „validateInput“ testen:

npm install --save jest express mongoose validator
npm install --save-dev jest puppeteer jest-puppeteer mongodb-memory-server supertest npm-run-all
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Es handelt sich um eine sehr einfache Funktion, die überprüft, ob die bereitgestellte Eingabe eine gültige E-Mail enthält. Hier ist der Unit-Test:

// setup.unit.js

beforeEach(() => {
  jest.resetAllMocks();
  jest.restoreAllMocks();
}); 
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

await Expect(async () => {}).rejects: Basierend auf der Jest-Dokumentation ist dies die Möglichkeit, den Grund für ein abgelehntes Versprechen zu erwarten.

Testen auf doppelte E-Mails

Testen wir eine weitere Funktion, die prüft, ob eine doppelte E-Mail in der Datenbank vorhanden ist. Eigentlich ist dies interessant, weil wir uns mit der Datenbank befassen müssen und sich Unit-Tests gleichzeitig nicht mit externen Systemen befassen sollten. Was sollen wir also tun? Nun, wir sollten Mocks verwenden.

Schauen Sie sich zunächst die Funktion emailShouldNotBeDuplicated an, die wir testen müssen:

// register.controller.js
const validator = require('validator');

const registerController = async (input) => {
  validateInput(input);
  ...
};

const validateInput = (input) => {
  const { name, email, password } = input;
  const isValidName = !!name && validator.isLength(name, { max: 10, min: 1 });
  if (!isValidName) throw new Error('Invalid name');
  ...
};
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Wie Sie sehen, sendet diese Funktion eine Anfrage an die Datenbank, um zu prüfen, ob es einen anderen Benutzer mit derselben E-Mail-Adresse gibt. So können wir den Datenbankaufruf verspotten:

// __tests__/unit/register.test.js
const { registerController } = require('../controllers/register.controller');

describe('RegisterController', () => {
  describe('validateInput', () => {
    it('should throw error if email is not an email', async () => {
      const input = { name: 'test', email: 'test', password: '12345678' };
      await expect(async () => await registerController(input)).rejects.toThrow('Invalid email');
    });
  });
});
Nach dem Login kopieren
Nach dem Login kopieren

Wir haben die findOne-Datenbankmethode mit jest.spyOn(object, methodName) gemobbt (ausspioniert), wodurch eine Scheinfunktion erstellt und ihre Aufrufe verfolgt werden. Dadurch können wir die Anzahl der Aufrufe und die übergebenen Parameter der ausspionierten findOne-Methode mithilfe von toHaveBeenNthCalledWith.

verfolgen

Integrationstests

  • Definition: Integrationstests bewerten, wie mehrere Komponenten zusammenarbeiten. Es überprüft die Interaktionen zwischen verschiedenen Funktionen, Modulen oder Diensten.
  • Geschwindigkeit: Integrationstests sind langsamer als Unit-Tests, da sie mehrere Komponenten umfassen und möglicherweise Datenbankzugriff oder Netzwerkaufrufe erfordern.
  • Beispiel: Für den Benutzerregistrierungsprozess könnte ein Integrationstest überprüfen, ob beim Senden der Registrierungsanfrage die Benutzerdaten korrekt validiert und in der Datenbank gespeichert werden. Dieser Test würde sicherstellen, dass alle Komponenten – wie die Eingabevalidierung, der API-Endpunkt und die Datenbankinteraktion – wie vorgesehen zusammenarbeiten.

Einrichten der Integrationstestumgebung

Bevor wir unseren Integrationstest schreiben, müssen wir unsere Umgebung konfigurieren:

npm install --save jest express mongoose validator
npm install --save-dev jest puppeteer jest-puppeteer mongodb-memory-server supertest npm-run-all
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
  • Wie Sie sehen, exportieren wir die TestingApp, da wir sie in den Integrationstests benötigen. Und wir exportieren es als Funktion, weil es exportiert wird, bevor es vollständig initialisiert ist. Da beforeAll asynchron ist, wird die Anweisung module.exports ausgeführt, bevor testingApp ein Wert zugewiesen wird, was dazu führt, dass sie undefiniert ist, wenn wir versuchen, sie in unserem Test zu verwenden Dateien.
  • Durch die Verwendung von Jest-Hooks konnten wir Folgendes erreichen:
    • beforeAll: Startet den Express-Server und stellt eine Verbindung zur In-Memory-MongoDB-Datenbank her.
    • afterAll: Schließt den Express-Server und stoppt die laufende In-Memory-MongoDB-Datenbank.
    • beforeEach: Bereinigt die Datenbank, indem die Benutzersammlung vor jedem Testfall gelöscht wird.

Jetzt sind wir bereit, unseren Integrationstest durchzuführen.

Testen der Registrierungs-API-Anfrage

Testen wir den gesamten serverseitigen Registrierungsprozess – vom Senden der Registrierungsanfrage über das Speichern von Benutzerdetails in der Datenbank bis hin zur Weiterleitung zur Erfolgsseite:

// setup.unit.js

beforeEach(() => {
  jest.resetAllMocks();
  jest.restoreAllMocks();
}); 
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Wie Sie sehen, integriert die Funktion „registerController“ mehrere Komponenten (Funktionen) sowie die Funktionen „validateInput“, „emailShouldNotBeDuplicated“ und „createUser“.

Also schreiben wir unseren Integrationstest:

// register.controller.js
const validator = require('validator');

const registerController = async (input) => {
  validateInput(input);
  ...
};

const validateInput = (input) => {
  const { name, email, password } = input;
  const isValidName = !!name && validator.isLength(name, { max: 10, min: 1 });
  if (!isValidName) throw new Error('Invalid name');
  ...
};
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
  • Wie Sie sehen, verwenden wir in diesem Testfall das Supertest-Paket, um eine Registrierungsanfrage an unsere API zu senden. Dadurch wird das reale Nutzerverhalten während des Registrierungsprozesses simuliert.
  • In diesem Fall haben wir die Datenbankaufrufe nicht verspottet, da wir das tatsächliche Verhalten testen müssen.

End-to-End-Tests (E2E).

  • Definition: E2E-Tests simulieren reale Benutzerszenarien, um den gesamten Anwendungsfluss von Anfang bis Ende zu validieren. Es testet die Anwendung als Ganzes, einschließlich der Benutzeroberfläche und der Backend-Dienste.
  • Geschwindigkeit: E2E-Tests sind die langsamsten unter den drei Typen, da sie die Navigation durch die Anwendungsschnittstelle und die Interaktion mit verschiedenen Komponenten erfordern, was oft mehrere Netzwerkanfragen erfordert.
  • Beispiel: Im Zusammenhang mit der Benutzerregistrierung würde ein E2E-Test simulieren, dass ein Benutzer die Registrierungsseite öffnet, seine Daten (wie Name, E-Mail-Adresse und Passwort) eingibt und auf die Schaltfläche „Registrieren“ klickt und dann prüfen, ob sie auf eine Erfolgsseite weitergeleitet werden. Dieser Test bestätigt, dass jeder Teil des Registrierungsprozesses aus Sicht des Benutzers nahtlos zusammenarbeitet.

Lass uns auf unser Beispiel eingehen.

Einrichten der E2E-Testumgebung

Tatsächlich in unserem Beispiel ähnelt die Umgebungskonfiguration für End-to-End-Tests der für Integrationstests.

Testen des Registrierungsprozesses von Anfang bis Ende

In diesem Fall müssen wir das tatsächliche Benutzerregistrierungsverhalten genau simulieren, vom Öffnen der Registrierungsseite über die Eingabe der Daten (Name, E-Mail-Adresse, Passwort) bis hin zum Klicken auf die Schaltfläche „Registrieren“ und schließlich der Weiterleitung auf eine Erfolgsseite . Schauen Sie sich den Code an:

npm install --save jest express mongoose validator
npm install --save-dev jest puppeteer jest-puppeteer mongodb-memory-server supertest npm-run-all
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Lassen Sie uns diesen Code aufschlüsseln:

  • Es gibt viele Tools, mit denen Sie Ihre End-to-End-Tests implementieren können. Hier verwenden wir Jest zusammen mit Puppeteer, um unsere End-to-End-Tests zu implementieren.
  • Sie fragen sich vielleicht, was eine Seitenvariable ist? Wie Jest erwartet, handelt es sich um eine von Puppeteer bereitgestellte globale Variable, die eine einzelne Registerkarte in einem Browser darstellt, auf der wir Aktionen wie Navigieren und Interagieren mit Elementen ausführen können.
  • Wir verwenden Puppeteer, um das Benutzerverhalten zu simulieren, indem wir diese Seite mit der Goto-Funktion öffnen, die Eingaben mit der Type-Funktion ausfüllen und mit der Click-Funktion auf die Registrierungsschaltfläche klicken.

Alle Tests zusammen mit unterschiedlichen Konfigurationen ausführen

Unit, Integration, and ETesting in One Example Using Jest

Foto von Nathan Dumlao auf Unsplash

An diesem Punkt fragen Sie sich vielleicht, wie Sie alle Testtypen gleichzeitig ausführen können, wenn jeder seine eigene Konfiguration hat. Zum Beispiel:

  • Bei Unit-Tests müssen Sie alle Mocks vor jedem Testfall zurücksetzen, während dies bei Integrationstests nicht notwendig ist.
  • Bei Integrationstests müssen Sie Ihre Datenbankverbindung einrichten, bevor Sie Ihre Tests ausführen, bei Unit-Tests ist dies jedoch nicht erforderlich.

Wie können wir also alle Testtypen gleichzeitig ausführen und gleichzeitig sicherstellen, dass jeder seine entsprechende Konfiguration berücksichtigt?

Um dieses Problem zu lösen, befolgen Sie diese Schritte:

1. Lassen Sie uns drei verschiedene Konfigurationsdateien erstellen, jest.unit.config.js:

// setup.unit.js

beforeEach(() => {
  jest.resetAllMocks();
  jest.restoreAllMocks();
}); 
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

jest.integration.config.js:

// register.controller.js
const validator = require('validator');

const registerController = async (input) => {
  validateInput(input);
  ...
};

const validateInput = (input) => {
  const { name, email, password } = input;
  const isValidName = !!name && validator.isLength(name, { max: 10, min: 1 });
  if (!isValidName) throw new Error('Invalid name');
  ...
};
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

jest.e2e.config.js:

// __tests__/unit/register.test.js
const { registerController } = require('../controllers/register.controller');

describe('RegisterController', () => {
  describe('validateInput', () => {
    it('should throw error if email is not an email', async () => {
      const input = { name: 'test', email: 'test', password: '12345678' };
      await expect(async () => await registerController(input)).rejects.toThrow('Invalid email');
    });
  });
});
Nach dem Login kopieren
Nach dem Login kopieren

2. Als Nächstes aktualisieren Sie Ihre npm-Skripte in der Datei „package.json“ wie folgt:

// register.controller.js
const { User } = require('../models/user');

const registerController = async (input) => {
    ...
  await emailShouldNotBeDuplicated(input.email);
  ...
};

const emailShouldNotBeDuplicated = async (email) => {
  const anotherUser = await User.findOne({ email });
  if (anotherUser) throw new Error('Duplicated email');
};
Nach dem Login kopieren

--config: Gibt den Pfad zur Jest-Konfigurationsdatei an.

npm-run-all --parallel: Ermöglicht die parallele Ausführung aller Tests.

3. Erstellen Sie dann drei Setup-Dateien mit den Namen setup.unit.js, setup.integration.js und setup.e2e.js, die den erforderlichen Setup-Code enthalten, der in den vorherigen Abschnitten verwendet wurde.
4. Führen Sie abschließend alle Tests aus, indem Sie diesen Befehl npm run test ausführen. Dieser Befehl führt alle Unit-, Integrations- und End-to-End-Tests entsprechend ihrer jeweiligen Konfiguration parallel aus.

Abschluss

In diesem Artikel haben wir Unit-, Integrations- und End-to-End-Tests (E2E) untersucht und deren Bedeutung für die Erstellung zuverlässiger Anwendungen hervorgehoben. Wir haben in einem einfachen Benutzerregistrierungsbeispiel mit Node.js und MongoDB gezeigt, wie diese Testmethoden mit Jest, Supertest und Puppeteer implementiert werden.

Tatsächlich verbessert eine solide Teststrategie nicht nur die Codequalität, sondern stärkt auch das Vertrauen der Entwickler und erhöht die Benutzerzufriedenheit.

Ich hoffe, dieser Artikel hat Ihnen nützliche Erkenntnisse geliefert, die Sie auf Ihre eigenen Projekte anwenden können. Viel Spaß beim Testen!

Denken Sie darüber nach

Wenn Sie diesen Artikel nützlich fanden, schauen Sie sich auch diese Artikel an:

  • MongoDB GridFS leicht gemacht
  • Wie ich das Video-Streaming mit FFmpeg und Node.js verbessert habe
  • 4 Möglichkeiten, mit asynchronem JavaScript umzugehen

Vielen Dank, dass Sie bis hierher bei mir geblieben sind. Ich wünsche Ihnen viel Spaß beim Lesen dieses Artikels.

Das obige ist der detaillierte Inhalt vonUnit, Integration und ETesting in einem Beispiel mit Jest. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage