EMZETT.
Login

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 0

Starte alle Tests mit node --test. Dateien mit Namen wie *.test.js werden automatisch gefunden.

assert-Methoden

MethodePrü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 bestanden

Aufbau eines guten Tests

Ein Test hat drei Teile (Arrange – Act – Assert):

  1. Arrange: Daten vorbereiten
  2. Act: die zu testende Funktion aufrufen
  3. 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 0

Mocks 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 0

Ein häufiger Trick: Übergib Abhängigkeiten als Parameter (Dependency Injection), dann kannst du im Test eine Fake-Variante hineingeben.

Andere Testwerkzeuge

WerkzeugBesonderheit
Vitestschnell, Jest-ähnlich, passt gut zu Vite
Jestweit verbreitet, viele Matcher
PlaywrightEnd-to-End-Tests im echten Browser
Testing Librarytestet 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/await und assert.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

Weiter im Kurs

Zurück: npm und Pakete

Weiter: Werkzeuge: Linter, Formatter, TypeScript

Alle Kapitel: JavaScript im Überblick