Node.js 테스트 실행기로 실험하기

May 03 2023
Node.js 18의 릴리스는 놀라운 결과를 가져왔습니다. 비록 실험적 플래그 뒤에 있지만 테스트 러너가 있다는 것입니다.
Unsplash에 있는 Jorge Rosal의 사진

Node.js 18의 릴리스는 놀라운 결과를 가져왔습니다. 비록 실험적 플래그 뒤에 있지만 테스트 러너가 있다는 것입니다.

Mocha와 Jest가 지난 10년 동안 이 공백을 채웠으므로 이제 이 기본 테스트 러너로 전환할 때입니까? 테스트 스위트를 실행하기 위한 개발 종속성이 더 이상 없습니까?

흥미롭게 들립니다!

첫 시도

test파일 의 단계를 다음으로 교체하여 시작했습니다 package.json.

{
  "scripts": {
    "test":  "node --test test/**/*.js"
  }
}

콘솔의 수많은 오류:

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 ]

여전히 많은 오류:

# 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)
  ...

두 번째 시도

이번에는 v18.16.0Node.js의 LTS 버전을 사용하고 있었습니다. 더 이상 난해한 오류는 없습니다! 그것은 안도감이었습니다.

취재 보고서를 실행했습니다. 커버리지 45%! 뭐? 기다리다. 테스트의 60%는 실행조차 되지 않았습니다!

몇 가지 연구를 수행하면서 테스트 러너를 위한 glob 구문 분석 문제인 이 GitHub 문제가 발생했습니다 . 기본 기능처럼 보였지만 네, 빠졌습니다! 따라서 glob 패턴을 사용할 수 없습니다 test/**/*.js.

명명된 디렉터리가 발견되면 테스트 러너는 모든 , 및 파일을 test재귀적으로 검색합니다 ..js.cjs.mjs

https://nodejs.org/docs/latest-v18.x/api/test.html#test-runner-execution-model

운 좋게도 우리의 테스트 디렉토리는 실제로 test. 더 이상 글롭이 없습니다.

// package.json

{
  "scripts": {
    "test":  "node --test -r test.setup.js"
  }
}

세 번째 시도?

테스트 세트는 마침내 녹색이었습니다. 범위도 녹색이었습니다.

다음은 모든 호출을 다음 sinon.assert으로 대체하여 네이티브 에서 마이그레이션하는 것입니다 .node:assert

sinon.assert.pass(condition);
sinon.assert.match(expected, received);

const assert = require('node:assert/strict');

assert.ok(condition);
assert.equal(expected, received);

테스트 스위트는 여전히 녹색입니다. 커버리지도 초록색입니다. 하지만 성능은 떨어졌다. 흠, 그건 내가 전에 확인하지 않은 것입니다.

테스트 도구 모음을 실행하는 데 16초 이상이 걸렸고 Mocha는 1초도 채 걸리지 않았습니다! Jest도 Mocha와 비슷한 시간을 보냈습니다.

네이티브 테스트 실행기를 사용하는 것에 대한 나의 인상은 Mocha 및 Jest와 같은 타사 도구를 능가할 수 있다는 것입니다. 그러나 이 GitHub 문제 에서 알 수 있듯이 그렇지 않은 것 같습니다 .

따라서 Node.js의 다음 마이너 릴리스가 나올 때까지 기다려야 세 번째 시도를 할 수 있습니다!

마지막 생각들

Unsplash의 캐롤라이나 사진

타사 종속성을 설치하지 않고 테스트 스위트를 실행할 수 있다는 것은 확실히 장점이 있습니다. 또한 Mocha와 유사한 구문을 지원하므로 마이그레이션이 매우 쉽습니다.

모의, 스냅샷, 코드 커버리지, 감시자 등 시도해보고 싶었던 기능이 더 많이 있습니다.

그러나 성능은 실제로 지연되었습니다. 수정을 간절히 기다리고 있습니다!