Experimentieren mit dem Node.js-Test-Runner
Die Veröffentlichung von Node.js 18 kam mit einer Überraschung: einem Testläufer, wenn auch hinter einer experimentellen Flagge.
Nachdem Mocha und Jest diese Lücke in den letzten zehn Jahren gefüllt haben, ist es an der Zeit, auf diesen nativen Testrunner umzusteigen? Keine Entwicklungsabhängigkeiten mehr, nur um die Testsuite auszuführen?
Klingt spannend!
Erster Versuch
Ich begann damit, den testSchritt in der package.jsonDatei zu ersetzen durch:
{
"scripts": {
"test": "node --test test/**/*.js"
}
}
Tonnen von Fehlern in der Konsole:
not ok * - <test path>
---
duration_ms: 1028.112875
failureType: 'subtestsFailed'
exitCode: 1
stdout: ''
stderr: |-
<test path>
^
ReferenceError: describe is not defined
at Object.<anonymous> (<test path>)
at Module._compile (node:internal/modules/cjs/loader:1159:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1213:10)
at Module.load (node:internal/modules/cjs/loader:1037:32)
at Module._load (node:internal/modules/cjs/loader:878:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
at node:internal/main/run_main_module:23:47
Node.js v18.12.1
error: 'test failed'
code: 'ERR_TEST_FAILURE'
...
const { describe, it, beforeEach, afterEach } = require('node:test');
// package.json
{
"scripts": {
"test": "node --test -r test.setup.js test/**/*.js"
}
}
// test.setup.js
global.describe = require('node:test').describe;
global.it = require('node:test').it;
global.beforeEach = require('node:test').beforeEach;
global.afterEach = require('node:test').afterEach;
global.before = require('node:test').before;
global.after = require('node:test').after;
Unable to resolve path to module 'node:test'. eslint(import/no-unresolved)
// .eslintrc.yml
settings:
import/core-modules: [ node:test ]
Immer noch jede Menge Fehler:
# Subtest: Errors thrown should be handled
not ok 3 - Errors thrown should be handled
---
duration_ms: 0.116958
failureType: 'hookFailed'
error: 'failed running beforeEach hook'
code: 'ERR_TEST_FAILURE'
stack: |-
checkWrappedMethod (node_modules/sinon/lib/sinon/util/core/wrap-method.js:67:21)
wrapMethod (node_modules/sinon/lib/sinon/util/core/wrap-method.js:132:13)
stub (node_modules/sinon/lib/sinon/stub.js:130:44)
node_modules/sinon/lib/sinon/util/core/walk-object.js:41:17
node_modules/sinon/lib/sinon/util/core/walk.js:28:22
Array.forEach (<anonymous>)
walkInternal (node_modules/sinon/lib/sinon/util/core/walk.js:20:5)
walk (node_modules/sinon/lib/sinon/util/core/walk.js:48:12)
walkObject (node_modules/sinon/lib/sinon/util/core/walk-object.js:26:5)
Function.stub (node_modules/sinon/lib/sinon/stub.js:103:16)
extendObjectWithWrappedMethods (node_modules/sinon/lib/sinon/util/core/wrap-method.js:167:34)
wrapMethod (node_modules/sinon/lib/sinon/util/core/wrap-method.js:155:5)
stub (node_modules/sinon/lib/sinon/stub.js:130:44)
node_modules/sinon/lib/sinon/util/core/walk-object.js:41:17
node_modules/sinon/lib/sinon/util/core/walk.js:28:22
Array.forEach (<anonymous>)
walkInternal (node_modules/sinon/lib/sinon/util/core/walk.js:20:5)
walk (node_modules/sinon/lib/sinon/util/core/walk.js:48:12)
walkObject (node_modules/sinon/lib/sinon/util/core/walk-object.js:26:5)
Function.stub (node_modules/sinon/lib/sinon/stub.js:103:16)
...
Zweiter Versuch
Dieses Mal habe ich die v18.16.0LTS-Version von Node.js verwendet. Keine kryptischen Fehler mehr! Das war eine Erleichterung.
Ließ den Abdeckungsbericht laufen. 45% Abdeckung! Häh? Warten. 60 % unserer Tests wurden nicht einmal ausgeführt!
Einige Recherchen führten mich zu diesem GitHub-Problem – ein Problem mit dem Glob-Parsing für den Testrunner. Schien wie ein grundlegendes Feature, aber ja, fehlt! Wir können also das Glob-Muster nicht verwenden test/**/*.js.
Wenn ein Verzeichnis mit dem Namen testgefunden wird, durchsucht der Test-Runner es rekursiv nach allen .js, .cjsund .mjs-Dateien.
https://nodejs.org/docs/latest-v18.x/api/test.html#test-runner-execution-model
Glücklicherweise hieß unser Testverzeichnis tatsächlich test. Also kein Klumpen mehr.
// package.json
{
"scripts": {
"test": "node --test -r test.setup.js"
}
}
Dritter Versuch?
Die Testsuite war endlich grün. Die Abdeckung war auch grün.
Als nächstes wurde weg von sinon.assertzum nativen migriert node:assert, indem alle Aufrufe ersetzt wurden durch:
sinon.assert.pass(condition);
sinon.assert.match(expected, received);
const assert = require('node:assert/strict');
assert.ok(condition);
assert.equal(expected, received);
Die Testsuite ist immer noch grün. Die Abdeckung ist auch grün. Aber die Leistung war den Bach runter. Hmm, das hatte ich vorher noch nicht überprüft.
Es dauerte über 16 Sekunden, um die Testsuite auszuführen, während Mocha in weniger als einer Sekunde fertig war! Sogar Jest hatte ähnliche Zeiten wie Mocha.
Mein Eindruck von der Verwendung eines nativen Testrunners war, dass er Tools von Drittanbietern wie Mocha und Jest übertreffen könnte. Dies scheint jedoch nicht der Fall zu sein, wie aus diesem GitHub-Problem hervorgeht .
Wir müssen also bis zum nächsten Minor-Release von Node.js warten, um einen dritten Versuch zu machen!
Abschließende Gedanken
In der Lage zu sein, eine Testsuite auszuführen, ohne eine Abhängigkeit von einem Drittanbieter zu installieren, hat sicherlich seine Vorzüge. Darüber hinaus macht die Unterstützung für Mocha-ähnliche Syntax die Migration kinderleicht.
Es gibt noch viele weitere Funktionen, die ich ausprobieren wollte: Mocks, Snapshots, Code-Coverage, Beobachter und mehr.
Aber die Aufführung war in der Tat eine Vertagung. Warte sehnsüchtig auf eine Lösung!

![Was ist überhaupt eine verknüpfte Liste? [Teil 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































