Kurz: Tests prüfen automatisch, ob dein Code das Richtige tut. Sie sind das Sicherheitsnetz, mit dem du Änderungen wagen kannst.
Teil des Kurses JavaScript
Kapitel 36 von 40 im Kurs JavaScript. Mit Fortschritt, Quiz und Zertifikat auf der Lernseite.
Tests prüfen automatisch, ob dein Code das Richtige tut. Sie sind das Sicherheitsnetz, mit dem du Änderungen wagen kannst.
Der eingebaute Testrunner von Node.js
Seit Node.js 20 gibt es node:test und node:assert, ohne zusätzliche Pakete:
const test = require("node:test");
const assert = require("node:assert/strict");
function istPalindrom(text) {
const sauber = text.toLowerCase().replace(/[^a-z0-9]/g, "");
return sauber === [...sauber].reverse().join("");
}
test("erkennt Palindrome", () => {
assert.equal(istPalindrom("Anna"), true);
assert.equal(istPalindrom("Ein Neger mit Gazelle zagt im Regen nie"), true);
});
test("erkennt Nicht-Palindrome", () => {
assert.equal(istPalindrom("Hallo"), false);
});
test("leerer Text ist ein Palindrom", () => {
assert.equal(istPalindrom(""), true);
});Ausgabe von node —test (Zeiten gekürzt)
✔ erkennt Palindrome (0.9ms)
✔ erkennt Nicht-Palindrome (0.2ms)
✔ leerer Text ist ein Palindrom (0.2ms)
ℹ tests 3
ℹ pass 3
ℹ fail 0Starte alle Tests mit node --test. Dateien mit Namen wie *.test.js werden automatisch gefunden.
assert-Methoden
| Methode | Prüft |
|---|---|
assert.equal(a, b) | strikte Gleichheit (im strict-Modul) |
assert.deepEqual(a, b) | gleiche Struktur bei Objekten/Arrays |
assert.ok(x) | truthy |
assert.throws(fn, Fehler) | wirft den Fehler |
await assert.rejects(promise) | Promise wird abgelehnt |
assert.match(text, /regex/) | passt zum Muster |
const assert = require("node:assert/strict");
assert.deepEqual({ a: [1, 2] }, { a: [1, 2] });
assert.throws(() => JSON.parse("x"), SyntaxError);
try {
assert.equal(1 + 1, 3, "Rechnen klappt nicht");
} catch (e) {
console.log(e.name, "-", e.message.split("\n")[0]);
}
console.log("deepEqual und throws bestanden");Ausgabe:
AssertionError - Rechnen klappt nicht
deepEqual und throws bestandenAufbau eines guten Tests
Ein Test hat drei Teile (Arrange – Act – Assert):
- Arrange: Daten vorbereiten
- Act: die zu testende Funktion aufrufen
- Assert: das Ergebnis prüfen
Gute Tests sind klein, unabhängig voneinander, schnell und beschreiben im Namen, was erwartet wird.
Was testet man?
- Normale Fälle
- Grenzfälle: leer, 0, negativ, sehr groß,
null,undefined - Fehlerfälle: Was passiert bei falscher Eingabe?
- Jeden gefundenen Fehler zuerst als fehlschlagenden Test festhalten, dann beheben
Asynchronen Code testen
const test = require("node:test");
const assert = require("node:assert/strict");
const lade = async (id) => {
await new Promise(r => setTimeout(r, 10));
if (id < 0) throw new RangeError("ungültige ID");
return { id };
};
test("lädt einen Datensatz", async () => {
assert.deepEqual(await lade(5), { id: 5 });
});
test("lehnt negative IDs ab", async () => {
await assert.rejects(lade(-1), RangeError);
});Ausgabe von node —test (Zeiten gekürzt)
✔ lädt einen Datensatz (12ms)
✔ lehnt negative IDs ab (11ms)
ℹ tests 2
ℹ pass 2
ℹ fail 0Mocks und Fakes
Wenn dein Code Netzwerk, Zeit oder Zufall benutzt, ersetzt du diese Teile im Test durch kontrollierbare Varianten:
const test = require("node:test");
const assert = require("node:assert/strict");
test("zählt Aufrufe mit einer Mock-Funktion", (t) => {
const log = t.mock.fn();
[1, 2, 3].forEach(x => log(x));
assert.equal(log.mock.callCount(), 3);
assert.deepEqual(log.mock.calls[0].arguments, [1]);
});Ausgabe von node —test (Zeiten gekürzt)
✔ zählt Aufrufe mit einer Mock-Funktion (1ms)
ℹ tests 1
ℹ pass 1
ℹ fail 0Ein häufiger Trick: Übergib Abhängigkeiten als Parameter (Dependency Injection), dann kannst du im Test eine Fake-Variante hineingeben.
Andere Testwerkzeuge
| Werkzeug | Besonderheit |
|---|---|
| Vitest | schnell, Jest-ähnlich, passt gut zu Vite |
| Jest | weit verbreitet, viele Matcher |
| Playwright | End-to-End-Tests im echten Browser |
| Testing Library | testet UI-Komponenten aus Nutzersicht |
Alle folgen demselben Prinzip: test("beschreibung", () => { expect(...)... }).
Testabdeckung
node --test --experimental-test-coverage zeigt, welche Zeilen Tests durchlaufen. 100 % Abdeckung heißt nicht fehlerfrei, aber wenig Abdeckung zeigt Lücken.
Merke
- Tests prüfen Code automatisch (
node --test, Vitest, Jest) - Arrange – Act – Assert; klein, unabhängig, sprechende Namen
- Normalfälle, Grenzfälle und Fehlerfälle testen
- Async-Tests mit
async/awaitundassert.rejects - Abhängigkeiten über Parameter hereingeben, damit sie sich ersetzen lassen
Übungsaufgabe
Schreibe eine Funktion summe(liste) und mindestens vier Tests, darunter leere Liste und Fehler bei Nicht-Zahlen.
Quiz zur Selbstkontrolle
Wie startest du den eingebauten Node-Testrunner?
- node —test (richtig)
- node test.js —all
- npm testrun
- node —check
Was bedeutet Arrange – Act – Assert?
- Vorbereiten, ausführen, prüfen (richtig)
- Löschen, kopieren, speichern
- Planen, bauen, ausliefern
- Lesen, schreiben, schließen
Wozu dienen Grenzfälle?
- Sie prüfen extreme oder ungewöhnliche Eingaben (richtig)
- Sie beschleunigen Tests
- Sie ersetzen Fehlermeldungen
- Sie verändern den Code
Weiter im Kurs
Zurück: npm und Pakete
Weiter: Werkzeuge: Linter, Formatter, TypeScript
Alle Kapitel: JavaScript im Überblick