paint-brush
Jasmine: Ein anfängerfreundlicher Leitfaden zu reinen Funktionen und grundlegenden Testsvon@marcinwosinek
200 Lesungen

Jasmine: Ein anfängerfreundlicher Leitfaden zu reinen Funktionen und grundlegenden Tests

von Marcin Wosinek6m2024/02/11
Read on Terminal Reader

Zu lang; Lesen

Reine Funktionen sind der perfekte Fall für Unit-Tests. Für eine gegebene Eingabe erwarten wir immer die gleiche Ausgabe – es ist kein interner Zustand beteiligt. Werfen wir einen Blick auf ein paar Beispiele und einige einfache Tests, die prüfen, ob die Methoden wie erwartet funktionieren.
featured image - Jasmine: Ein anfängerfreundlicher Leitfaden zu reinen Funktionen und grundlegenden Tests
Marcin Wosinek HackerNoon profile picture

Reine Funktionen sind der perfekte Fall für Unit-Tests. Für eine gegebene Eingabe erwarten wir immer die gleiche Ausgabe – es ist kein interner Zustand beteiligt. Schauen wir uns ein paar Beispiele und einige einfache Tests an, die prüfen, ob die Methoden wie erwartet funktionieren.

Jasmin

Jasmine ist ein Unit-Test-Framework für JavaScript. Es kann Tests sowohl in Node.js als auch im Browser ausführen. Es wird im Angular-Framework verwendet und ist besonders in Projekten beliebt, die auf Angular basieren. Es ist eine gute Wahl für Vanilla JS-Projekte oder auch Projekte, die auf anderen Frameworks basieren.

Viel Spaß beim Testen des Weges

Beim Happy-Path-Testen testen wir eine Methode mit Eingaben, von denen erwartet wird, dass sie normal funktioniert. Die Argumente sind gültig und liegen in angemessenen Grenzen. Bei diesen Tests wird überprüft, ob die Methode ihre Aufgabe korrekt erfüllt. Die Testfälle sollten einfache Beispiele dafür sein, wie die Methode in ihrer Dokumentation erklärt wird.


Pseudocode-Beispiele:

  • expect(add(2, 2)).toBe(4) ,


  • expect(concatenate(“Lorem”, “Ipsum”)).toBe(“LoremIpsum”)


Diese Tests sollen es automatisch abfangen, wenn das Verhalten des Methodenschlüssels fehlerhaft ist.

Methoden

Sehen wir uns ein paar einfache Methoden an: einfache Operationen, die wir möglicherweise in einigen realen Anwendungen benötigen.


Alle Implementierungen sind stark vereinfacht – alle Methoden werden auf hässliche Weise kaputt gehen, wenn wir ihnen nur Parameter zur Verfügung stellen, die geringfügig von den Erwartungen abweichen. Der Code ist alles andere als robust.

grüßen

Methode, die den Benutzer mit seinem Vor- und Nachnamen begrüßt:

 export function greet(name, surname) { return `Hello ${name} ${surname}!`; }

kurzes Date

shortDate ist eine Formatierungsmethode, die ein Datumsobjekt nimmt und es formatiert als kurze Zeichenfolge zurückgibt. Der Code:

 export function shortDate(date) { return date.toISOString().substring(0, 10); }

Ellipse

ellipsis nimmt eine lange Textzeichenfolge und einen optionalen Längenparameter und schneidet die Zeichenfolge dann so zu, dass sie in den Grenzwert passt:

 export function ellipsis(text, length = 50) { if (text.length > length) { return text.substring(0, length) + "…"; } return text; }

übersetzen

Eine Methode, die übersetzte Zeichenfolgenwerte für ein key und lang -Paar bereitstellt. Es handelt sich um eine vereinfachte Implementierung dessen, was durch fortschrittlichere Übersetzungsbibliotheken ersetzt werden könnte.

 export function translate(key, lang = "en") { switch (lang) { case "en": switch (key) { case "hello": return "Hello!"; } case "pl": switch (key) { case "hello": return "Cześć!"; } } }

applyDiscount

Methode zum Anwenden eines prozentualen Rabatts auf einen Preis. Mit dieser naiven Implementierung kann es sich übertrieben anfühlen, aber später, wenn wir anfangen, Randfälle zu untersuchen, wird es viel interessanter.

 export function applyDiscount(price, discountPercentage) { return price - (price * discountPercentage) / 100; }

berechne den Preis

Dieser berechnet den Gesamtpreis beim Kauf mehrerer Einheiten zu einem bestimmten Preis. Es wird auch komplizierter, wenn interessante Randfälle hinzugefügt werden.

 export function calculatePrice(unitPrice, quantity) { return unitPrice * quantity; }

Vollständiger JS-Code

Der vollständige JS-Code, src/main.js :

 export function greet(name, surname) { return `Hello ${name} ${surname}!`; } export function shortDate(date) { return date.toISOString().substring(0, 10); } export function ellipsis(text, length = 50) { if (text.length > length) { return text.substring(0, length) + "…"; } return text; } export function translate(key, lang = "en") { switch (lang) { case "en": switch (key) { case "hello": return "Hello!"; } case "pl": switch (key) { case "hello": return "Cześć!"; } } } export function applyDiscount(price, discountPercentage) { return price - (price * discountPercentage) / 100; } export function calculatePrice(unitPrice, quantity) { return unitPrice * quantity; }

Jasmintests hinzufügen

Um Jasmine hinzuzufügen, beginnen wir mit der Konvertierung des Ordners in ein npm-Paket:

 $ npm init -y Wrote to …/package.json: …


Dann können wir das Jasmine-Paket installieren:

 $ npm install --save-dev jasmine added 42 packages, and audited 43 packages in 2s 13 packages are looking for funding run `npm fund` for details found 0 vulnerabilities


Dann können wir von Jasmine verwendete Ordner und Dateien generieren:

 $ npx jasmine init (no output)


Dieser Befehl generiert Folgendes:

  • spec/ – ein Ordner, in dem wir *.spec.js Dateien mit dem Test ablegen können, und


  • spec/support/jasmine.json – eine Datei mit der Jasmine-Konfiguration.

Unit-Tests

Bei den folgenden Komponententests konzentriere ich mich nur auf den glücklichen Weg – ich überprüfe, ob das Ergebnis für vernünftige Eingaben den Erwartungen entspricht. Der Test sollte selbsterklärend sein, also werfen wir einen Blick darauf:

 import { greet, shortDate, ellipsis, translate, applyDiscount, calculatePrice, } from "../src/main.js"; describe("main", () => { describe("greet", () => { it("should greet by name and surname", () => { expect(greet("Lorem", "Ipsum")).toEqual("Hello Lorem Ipsum!"); }); }); describe("shortDate", () => { it("should format correclty date", () => { const date = new Date("2023-11-02"); expect(shortDate(date)).toEqual("2023-11-02"); }); }); describe("shortDate", () => { it("should shorten long text at 50 chars", () => { expect( ellipsis( "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque a faucibus massa." ) ).toEqual("Lorem ipsum dolor sit amet, consectetur adipiscing…"); }); it("should leave short text unchanged", () => { expect(ellipsis("Lorem ipsum sin dolor")).toEqual( "Lorem ipsum sin dolor" ); }); it("should shorten to custom length", () => { expect(ellipsis("Lorem ipsum sin dolor", 10)).toEqual("Lorem ipsu…"); }); }); describe("translate", () => { it("should translate to supported langauges", () => { expect(translate("hello", "en")).toEqual("Hello!"); expect(translate("hello", "pl")).toEqual("Cześć!"); }); }); describe("applyDiscount", () => { it("should lower the price accordingly", () => { expect(applyDiscount(120, 25)).toEqual(90); expect(applyDiscount(8, 50)).toEqual(4); }); }); describe("calculatePrice", () => { it("should find a price of many products", () => { expect(calculatePrice(4, 3)).toEqual(12); expect(calculatePrice(9, 0.5)).toEqual(4.5); }); }); });

(Datei spec/main.spec.js )

Ausführen von Tests

Um die Tests auszuführen, können wir das folgende Skript zu package.json hinzufügen:

 .. "scripts": { "test": "jasmine" }, …


Nachdem dies geschehen ist, führt npm run test unsere Tests aus:

 $ npm run test > [email protected] test > jasmine Randomized with seed 76873 Started ........ 8 specs, 0 failures Finished in 0.004 seconds Randomized with seed 76873 (jasmine --random=true --seed=76873)

Zusammenfassung

In diesem Beitrag haben wir uns ein einfaches Beispiel für JS-Code angesehen und gezeigt, wie dieser durch Unit-Tests abgedeckt werden kann. Das vollständige Codebeispiel finden Sie auf GitHub .


Auch hier veröffentlicht