Skip to content

TDD in Node.js

Ziel dieser Übung ist es vorderrangig die Tools die in dieser Übung eingesetzt werden kennenzulernen. Hierzu greifen wir auf eine minimale Node.js Anwendung zurück und implementieren eine einfache Funktion unter der Verwendung von TDD.

Hierzu importieren wir zuerst einmal ein Repository mittels GitHub.

Hierzu navigieren wir zuerst in der oben Menüleiste nach rechts und klicken auf den Pfeil nach unten neben den Plus (1) und anschließend auf “Import repository” (2). Siehe auch Screenshot

Repository importieren in GitHub

Danach öffnet sich der folgende Dialog in dem wir die Felder

(1) - URL des Quell-Repositories, in unserem Fall

Terminal window
https://github.com/FHB-Student/Nodejs-Starter

(2) - Der Namen des zu erstellenden Repositories in unserem Account z.B.: TDD-Nodejs-Example

befüllen.

Repository importieren in GitHub - Dialog befüllt

Anschließend wählen wir noch aus das ein privates Repository angelegt werden soll und beginnen den Import mittels Klick auf den Button “Begin import”.

Nach einer kurzen Wartezeit sollte das neue Repository inklusive der importieren Daten zur Verfügung stehen.

Es sollte nun folgender Screen zu sehen sein. Repository importieren in GitHub - Import erfolgreich

Mittels Klick auf den Link bei der Anzeige des erfolgreichen Imports gelangen wir direkt zur Ansicht des Repos in GitHub.

Im Repository angekommen legen wir nun zu aller erst einmal eine Branch an.

Branch in GitHub anlegen

  • (1) Wie im Screenshot ersichtlich Klicken wir zuerst auf “main” um ins Branch-Menü zu gelangen.
  • (2) Anschließend vergeben wir einen klaren verständlichen Namen für unseren neuen Branch.
  • (3) Abschließend klicken wir auf “Create branch from main

Anschließend schickt und GitHub zurück zur Repo-Seite. Der neue Branch ist automatisch ausgewählt, dies kann wie unten im Screenshot überprüft werden.

Ausgewählter neuer Branch in GitHub

Hierzu klicken wir zuerst auf “Code” (1) danach wählen wir den Tab “Codespaces” (2) aus. Anschließend klicken wir auf “Create codespace on …” (3) um den Codespace zu starten.

Start eines GitHub Codespaces aus GitHub heraus

Es öffnet sich nun ein neuer Browser-Tab mit einer VS Code Oberfläche.

Wir installieren ein JavaScript Test-Framework names Mocha. Hierzu öffnen wir das Terminal und fügen den unten angeführten Aufruf ein.

Terminal window
npm install mocha --save-dev

Anschließend erstellen wir im Verzeichnis “src” die Datei “calculator.js”.

Für unsere automatischen Tests legen wir nun auf oberster Ebene ein Verzeichnis names “test” an.

In dem zuvor erstellten Verzeichnis legen wir nun eine Datei names “calculator.test.js” an und befüllen sie mich dem unten angeführten Inhalt.

calculator.test.js
const assert = require('assert');
describe('Simple Math Test', () => {
it('should return 2', () => {
assert.equal(1 + 1, 2);
});
});

Wir haben somit einen ersten automatischen Test mit Hilfe von Mocha erstellt. Nun ist es an der Zeit diesen auszuführen und verifizieren ob dies korrekt funktioniert.

Es ist eine Konvention in NPM das Tests mit einem Script names “test” ausgeführt werden können. Hierzu geben wir in die Kommandozeile nun den Befehl

Terminal window
npm run test

ein um unseren Test zu starten.

Wir bekommen nun die Rückmeldung “No test specified” obwohl wir doch zuvor eine Test angelegt haben.

Fehlermeldung beim Ausführen von npm run test
@FHB-Student /workspaces/TDD-Nodejs-Example (feature/tdd-example) $ npm run test
> nodejs-starter@1.0.0 test
> echo "No test specified" && exit 0
No test specified

Um die Ursache für diese Meldung herauszufinden navigieren wir zur Datei “package.json” im Quellverzeichnis.

package.json
"scripts": {
"start": "nodemon src/index.js",
"test": "echo \"No test specified\" && exit 0"
},

Wie im Ausschnitt der Datei “package.json” oben erkennbar ist das Script aktuell eben so definiert. Es gibt aktuell die Meldung “No test specified” aus und wird danach beendet.

Damit das von uns gewünscht Verhalten ausgeführt ist müssen wir dieses Script anpassen. Wie im unteren Beispiel angeführt ersetzen wir das bestehende Test-Script durch ein neues welches Mocha aufruft.

package.json
"scripts": {
"start": "nodemon src/index.js",
"test": "echo \"No test specified\" && exit 0"
"test": "mocha"
},

Nun wurde der Test erfolgreich ausgeführt, dies erkennen wir an der Ausgabe im CLI.

Um zu sehen wie ein fehlgeschlagener Test aussieht fügen wir den unten dargestellten (grünen) Block hinzu.

calculator.test.js
const assert = require('assert');
describe('Simple Math Test', () => {
it('should return 2', () => {
assert.equal(1 + 1, 2);
});
it('should also return 2', () => {
assert.equal(1 + 3, 2);
});
});

Anschließend führen wir den Test erneut aus. Wir sehen das nun wie gewohlt ein Test erfolgreich durchgelaufen ist und der andere mit eine fehlschlägt.

Dies zeigt uns die Ausgabe in der Kommandozeile farblich gekennzeichnet (wie im Screenshot ersichtlich) an.

Ein Test ist erfolgreich einer fehlgeschlagen

Jetzt testen wir aber aktuell nicht unsere Funktion sondern nur ob JavaScript den + Operator korrekt implementiert.

Hierzu müssen wir zuerst eine Funktion in der Datei “calculator.js” im Verzeichnis “src” erstellen.

calculator.js
const calculator = {};
calculator.calculate = (num1, num2, operation) => {
return num1 + num2;
}
module.exports = calculator;

Ebenso müssen wir noch die Tests in der Datei “calculator.test.js anpassen.

calculator.test.js
const assert = require('assert');
const calculator = require('../src/calculator');
describe('calculator.calculate() Test', () => {
it('1 + 1 should equal 2', () => {
const result = calculator.calculate(1, 1, '+');
assert.equal(result, 2);
});
});

Wir führen erneut den Test mittels

Terminal window
npm run test

aus und sehen das dieser ohne Fehler durchläuft.

Wir haben somit eine Funktion inklusive funktionierenden Unit-Test.

Nun wollen wir gemeinsam die Funktion erweitern und nutzen hierzu Test Driven Development (TDD).

Zur Erinnerung das Vorgehen bei TDD sieht wiefolgt aus:

  1. Einen neuen Test hinzufügen
  2. Alle (betroffenen) Tests ausführen => der neue Test sollte fehlschlagen
  3. Die betroffene Funktion wird so erweitert/angepasst das alle Tests erfolgreich durchlaufen
  4. Die Tests laufen fehlerfrei durch
  5. Refaktorisierung der Funktion => Test laufen auch danach fehlerfrei durch.

So nun spielen wir ein paar dieser Zyklen gemeinsam durch.

Nachdem wir nun diese Funktion gemäß TDD gemeinsam implementiert haben müssen wir diese noch mittels git festschreiben und mittels Pull-Request in die Haupt-Branch (main) integrieren.

Hierzu wählen wir im Menü auf der linken Seite das vierte Symbol von oben aus. Anschließend geben wir in dem Testfeld einen klaren nachvollziehbaren Namen der erklärt was wir geändert haben für unseren Commit.

Abschließend klicken wir auf den Pfeil rechts neben “Commit” und wählen die Option “Commit und Push” aus.

GitHub Codespaces Commit Dialog

Anschließend fragt die Web-UI nach einer Bestätigung ob wir alle Änderungen zuerst stagen und danach commiten wollen.

GitHub Codespaces Commit Bestätigungsdialog automatisches Staging

Dies bestätigen wir mittels eines Klicks auf “Ja”.

Anschließend stoppen wir noch unseren GitHub Codespace da wir ihn nicht weiter benötigen.

Hierzu betätigen wir zuerst die “F1”-Taste und geben dann in der Befehlsleiste “Codespaces: Stop Current Codespace” und wählen diese Option anschließend aus.

GitHub Codespace mittels Befehlszeile stoppen

Das dies erfolgreich durchgeführt wurde zeigt uns dieser Screenshot an.

GitHub Codespace erfolgreich gestoppt

Nun können wir uns in der GitHub Web-UI unsere Pull-Request ansehen und nach ausreichender Prüfung in den Hauptzweig übernehmen.

In diesem Lab haben wir erfolgreich

  • Einen Projekt in GitHub importiert
  • Einen Branch erstellt
  • GitHub Codespaces aufgerufen
  • Eine Abhängigkeit mittels NPM zum Projekt hinzugefügt
  • Unit-Tests geschrieben und ausgeführt
  • Den Ablauf bei TDD anhand eines einfachen Beispiels durchgespielt