Skip to content

テストランナー

[履歴]

バージョン変更
v20.0.0テストランナーは安定版になりました。
v18.0.0, v16.17.0追加: v18.0.0, v16.17.0

[安定版: 2 - 安定版]

安定版: 2 安定度: 2 - 安定版

ソースコード: lib/test.js

node:test モジュールは、JavaScript テストの作成を容易にします。アクセスするには:

js
import test from 'node:test'
js
const test = require('node:test')

このモジュールは、node: スキームでのみ使用できます。

test モジュールで作成されたテストは、単一の関数で構成され、3 つの方法のいずれかで処理されます。

次の例は、test モジュールを使用してテストを作成する方法を示しています。

js
test('同期通過テスト', t => {
  // このテストは、例外をスローしないため、パスします。
  assert.strictEqual(1, 1)
})

test('同期失敗テスト', t => {
  // このテストは、例外をスローするため、失敗します。
  assert.strictEqual(1, 2)
})

test('非同期通過テスト', async t => {
  // このテストは、非同期関数が返すPromiseが解決され、拒否されないため、パスします。
  assert.strictEqual(1, 1)
})

test('非同期失敗テスト', async t => {
  // このテストは、非同期関数が返すPromiseが拒否されるため、失敗します。
  assert.strictEqual(1, 2)
})

test('Promise を使用した失敗テスト', t => {
  // Promise も直接使用できます。
  return new Promise((resolve, reject) => {
    setImmediate(() => {
      reject(new Error('これはテストを失敗させます'))
    })
  })
})

test('コールバック通過テスト', (t, done) => {
  // done() はコールバック関数です。setImmediate() が実行されると、引数なしで done() を呼び出します。
  setImmediate(done)
})

test('コールバック失敗テスト', (t, done) => {
  // setImmediate() が実行されると、Error オブジェクトを使用して done() が呼び出され、テストが失敗します。
  setImmediate(() => {
    done(new Error('コールバック失敗'))
  })
})

テストに失敗があると、プロセスの終了コードが 1 に設定されます。

サブテスト

テストコンテキストのtest()メソッドを使用すると、サブテストを作成できます。これにより、上位のテスト内にネストされたテストを作成できる階層的な方法でテストを構成できます。このメソッドは、最上位のtest()関数と同様に動作します。次の例は、2 つのサブテストを持つ最上位のテストの作成を示しています。

js
test('トップレベルテスト', async t => {
  await t.test('サブテスト1', t => {
    assert.strictEqual(1, 1)
  })

  await t.test('サブテスト2', t => {
    assert.strictEqual(2, 2)
  })
})

この例では、awaitを使用して、両方のサブテストが完了していることを確認しています。これは、スイート内で作成されたテストとは異なり、テストはサブテストの完了を待機しないため必要です。親テストが終了した時点で未処理のサブテストはキャンセルされ、失敗として扱われます。サブテストのいずれかが失敗すると、親テストも失敗します。

テストのスキップ

skipオプションをテストに渡すか、次の例に示すようにテストコンテキストのskip()メソッドを呼び出すことで、個々のテストをスキップできます。

js
// skipオプションが使用されていますが、メッセージは提供されていません。
test('skipオプション', { skip: true }, t => {
  // このコードは実行されません。
})

// skipオプションが使用されており、メッセージが提供されています。
test('skipオプションとメッセージ', { skip: 'これはスキップされます' }, t => {
  // このコードは実行されません。
})

test('skip()メソッド', t => {
  // テストに追加のロジックが含まれている場合もここで返すようにしてください。
  t.skip()
})

test('skip()メソッドとメッセージ', t => {
  // テストに追加のロジックが含まれている場合もここで返すようにしてください。
  t.skip('これはスキップされます')
})

TODO テスト

次の例に示すように、todoオプションをテストに渡すか、テストコンテキストのtodo()メソッドを呼び出すことで、個々のテストを不安定または未完成としてマークできます。これらのテストは、実装が保留中であるか、修正が必要なバグを表しています。TODO テストは実行されますが、テストの失敗として扱われず、そのためプロセスの終了コードに影響しません。テストが TODO とスキップの両方としてマークされている場合、TODO オプションは無視されます。

js
// todoオプションが使用されていますが、メッセージは提供されていません。
test('todoオプション', { todo: true }, t => {
  // このコードは実行されますが、失敗として扱われません。
  throw new Error('これはテストを失敗させません')
})

// todoオプションが使用されており、メッセージが提供されています。
test('todoオプションとメッセージ', { todo: 'これはTODOテストです' }, t => {
  // このコードは実行されます。
})

test('todo()メソッド', t => {
  t.todo()
})

test('todo()メソッドとメッセージ', t => {
  t.todo('これはTODOテストであり、失敗として扱われません')
  throw new Error('これはテストを失敗させません')
})

describe()it() のエイリアス

スイートとテストは、describe() 関数と it() 関数を使って記述することもできます。describe()suite() のエイリアスであり、it()test() のエイリアスです。

js
describe('A thing', () => {
  it('should work', () => {
    assert.strictEqual(1, 1)
  })

  it('should be ok', () => {
    assert.strictEqual(2, 2)
  })

  describe('a nested thing', () => {
    it('should work', () => {
      assert.strictEqual(3, 3)
    })
  })
})

describe()it()node:test モジュールからインポートされます。

js
import { describe, it } from 'node:test'
js
const { describe, it } = require('node:test')

only テスト

Node.js が --test-only コマンドラインオプションで起動されている場合、またはテストの分離が無効になっている場合、実行するテストの選択されたサブセットに only オプションを渡すことで、選択されたサブセットを除くすべてのテストをスキップできます。only オプションが設定されているテストがある場合、すべてのサブテストも実行されます。スイートに only オプションが設定されている場合、そのスイート内のすべてのテストが実行されますが、only オプションが設定されている子孫がある場合は、それらのテストのみが実行されます。

サブテストtest()/it() 内で使用する場合、選択されたサブセットのテストのみを実行するには、すべての祖先テストに only オプションを付ける必要があります。

テストコンテキストの runOnly() メソッドを使用して、サブテストレベルで同じ動作を実装できます。実行されないテストは、テストランナーの出力から省略されます。

js
// Node.js が --test-only コマンドラインオプションで実行されていると仮定します。
// スイートの 'only' オプションが設定されているため、これらのテストは実行されます。
test('this test is run', { only: true }, async t => {
  // このテスト内では、すべてのサブテストがデフォルトで実行されます。
  await t.test('running subtest')

  // テストコンテキストを更新して、'only' オプションでサブテストを実行できます。
  t.runOnly(true)
  await t.test('this subtest is now skipped')
  await t.test('this subtest is run', { only: true })

  // コンテキストを元に戻して、すべてのテストを実行します。
  t.runOnly(false)
  await t.test('this subtest is now run')

  // 明示的にこれらのテストを実行しません。
  await t.test('skipped subtest 3', { only: false })
  await t.test('skipped subtest 4', { skip: true })
})

// 'only' オプションが設定されていないため、このテストはスキップされます。
test('this test is not run', () => {
  // このコードは実行されません。
  throw new Error('fail')
})

describe('a suite', () => {
  // 'only' オプションが設定されているため、このテストは実行されます。
  it('this test is run', { only: true }, () => {
    // このコードは実行されます。
  })

  it('this test is not run', () => {
    // このコードは実行されません。
    throw new Error('fail')
  })
})

describe.only('a suite', () => {
  // 'only' オプションが設定されているため、このテストは実行されます。
  it('this test is run', () => {
    // このコードは実行されます。
  })

  it('this test is run', () => {
    // このコードは実行されます。
  })
})

名前によるテストのフィルタリング

--test-name-pattern コマンドラインオプションを使用すると、指定されたパターンに一致する名前のテストのみを実行でき、--test-skip-pattern オプションを使用すると、指定されたパターンに一致する名前のテストをスキップできます。テスト名のパターンは、JavaScript の正規表現として解釈されます。ネストされたテストを実行するために、--test-name-pattern--test-skip-pattern オプションは複数回指定できます。実行される各テストについて、beforeEach()などの対応するテストフックも実行されます。実行されないテストは、テストランナーの出力から省略されます。

次のテストファイルの場合、--test-name-pattern="test [1-3]" オプションで Node.js を起動すると、テストランナーは test 1test 2test 3 を実行します。test 1 がテスト名パターンに一致しなかった場合、そのサブテストは、パターンに一致していても実行されません。同じテストセットは、--test-name-pattern を複数回渡すことによっても実行できます(例:--test-name-pattern="test 1"--test-name-pattern="test 2" など)。

js
test('test 1', async t => {
  await t.test('test 2')
  await t.test('test 3')
})

test('Test 4', async t => {
  await t.test('Test 5')
  await t.test('test 6')
})

テスト名パターンは、正規表現リテラルを使用して指定することもできます。これにより、正規表現フラグを使用できます。前の例では、--test-name-pattern="/test [4-5]/i"(または --test-skip-pattern="/test [4-5]/i")で Node.js を起動すると、パターンは大文字と小文字を区別しないため、Test 4Test 5 に一致します。

パターンを使用して単一のテストに一致させるには、一意になるように、すべての祖先テスト名をスペースで区切って接頭辞を付けることができます。たとえば、次のテストファイルの場合:

js
describe('test 1', t => {
  it('some test')
})

describe('test 2', t => {
  it('some test')
})

--test-name-pattern="test 1 some test" で Node.js を起動すると、test 1some test のみに一致します。

テスト名パターンは、テストランナーが実行するファイルのセットを変更しません。

--test-name-pattern--test-skip-pattern の両方が指定されている場合、テストは実行されるために両方の要件を満たす必要があります。

余分な非同期アクティビティ

テスト関数の実行が完了すると、テストの順序を維持しながら、できるだけ早く結果が報告されます。しかし、テスト関数自体よりも長く存続する非同期アクティビティをテスト関数が生成する可能性があります。テストランナーはこのタイプのアクティビティを処理しますが、それを考慮するためにテスト結果の報告を遅らせることはありません。

次の例では、2 つのsetImmediate()操作が未処理の状態でテストが完了します。最初のsetImmediate()は新しいサブテストを作成しようとします。親テストは既に終了して結果を出力しているので、新しいサブテストはすぐに失敗としてマークされ、後で<TestsStream>に報告されます。

2 番目のsetImmediate()uncaughtExceptionイベントを作成します。完了したテストから発生したuncaughtExceptionunhandledRejectionイベントは、testモジュールによって失敗としてマークされ、<TestsStream>によって最上位レベルで診断警告として報告されます。

js
test('a test that creates asynchronous activity', t => {
  setImmediate(() => {
    t.test('subtest that is created too late', t => {
      throw new Error('error1')
    })
  })

  setImmediate(() => {
    throw new Error('error2')
  })

  // The test finishes after this line.
})

ウォッチモード

追加されたバージョン: v19.2.0, v18.13.0

[Stable: 1 - Experimental]

Stable: 1 Stability: 1 - Experimental

Node.js テストランナーは、--watchフラグを渡すことでウォッチモードで実行できます。

bash
node --test --watch

ウォッチモードでは、テストランナーはテストファイルとその依存関係の変更を監視します。変更が検出されると、テストランナーは変更の影響を受けたテストを再実行します。テストランナーはプロセスが終了するまで実行を続けます。

コマンドラインからのテストの実行

Node.js テストランナーは、--test[/api/cli#--test]フラグを渡すことでコマンドラインから呼び出すことができます。

bash
node --test

デフォルトでは、Node.js はこれらのパターンに一致するすべてのファイルを実行します。

  • **/*.test.{cjs,mjs,js}
  • **/*-test.{cjs,mjs,js}
  • **/*_test.{cjs,mjs,js}
  • **/test-*.{cjs,mjs,js}
  • **/test.{cjs,mjs,js}
  • **/test/**/*.{cjs,mjs,js}

--experimental-strip-typesが指定されている場合、以下の追加パターンが一致されます。

  • **/*.test.{cts,mts,ts}
  • **/*-test.{cts,mts,ts}
  • **/*_test.{cts,mts,ts}
  • **/test-*.{cts,mts,ts}
  • **/test.{cts,mts,ts}
  • **/test/**/*.{cts,mts,ts}

あるいは、以下に示すように、1 つ以上の glob パターンを Node.js コマンドの最後の引数として指定できます。glob パターンはglob(7)の動作に従います。システム間での移植性を高めるために、glob パターンはコマンドラインで二重引用符で囲む必要があります。

bash
node --test "**/*.test.js" "**/*.spec.js"

一致するファイルはテストファイルとして実行されます。テストファイルの実行に関する詳細は、テストランナー実行モデルセクションを参照してください。

テストランナーの実行モデル

プロセスレベルのテスト分離が有効になっている場合、一致する各テストファイルは別々の子プロセスで実行されます。一度に実行される子プロセスの最大数は、--test-concurrency フラグで制御されます。子プロセスが終了コード 0 で終了した場合、テストは成功とみなされます。それ以外の場合は、テストは失敗とみなされます。テストファイルは Node.js によって実行可能である必要がありますが、内部でnode:testモジュールを使用する必要はありません。

各テストファイルは、通常のスクリプトであるかのように実行されます。つまり、テストファイル自体がnode:testを使用してテストを定義している場合、test()concurrencyオプションの値に関係なく、それらのテストはすべて単一アプリケーションスレッド内で実行されます。

プロセスレベルのテスト分離が無効になっている場合、一致する各テストファイルはテストランナープロセスにインポートされます。すべてのテストファイルがロードされると、最上位レベルのテストがコンカレンシー 1 で実行されます。テストファイルはすべて同じコンテキスト内で実行されるため、分離が有効になっている場合とは不可能な方法でテストが相互に作用する可能性があります。たとえば、テストがグローバル状態に依存している場合、別のファイルに由来するテストによってその状態が変更される可能性があります。

コードカバレッジの収集

[安定版: 1 - 実験的]

安定版: 1 安定性: 1 - 実験的

Node.js が--experimental-test-coverageコマンドラインフラグで起動されると、コードカバレッジが収集され、すべてのテストが完了すると統計が報告されます。NODE_V8_COVERAGE環境変数を使用してコードカバレッジディレクトリを指定した場合、生成された V8 カバレッジファイルはそのディレクトリに書き込まれます。デフォルトでは、Node.js コアモジュールとnode_modules/ディレクトリ内のファイルはカバレッジレポートに含まれません。ただし、--test-coverage-includeフラグを使用して明示的に含めることができます。デフォルトでは、一致するすべてのテストファイルはカバレッジレポートから除外されます。除外は--test-coverage-excludeフラグを使用してオーバーライドできます。カバレッジが有効になっている場合、カバレッジレポートは'test:coverage'イベントを介してテストレポーターに送信されます。

次のコメント構文を使用して、一連の行でカバレッジを無効にすることができます。

js
/* node:coverage disable */
if (anAlwaysFalseCondition) {
  // この分岐のコードは実行されませんが、行はカバレッジの目的で無視されます。'disable'コメントに続くすべての行は、対応する'enable'コメントが検出されるまで無視されます。
  console.log('これは実行されません')
}
/* node:coverage enable */

指定された行数に対してカバレッジを無効にすることもできます。指定された行数後、カバレッジは自動的に再度有効になります。行数が明示的に指定されていない場合、1 行が無視されます。

js
/* node:coverage ignore next */
if (anAlwaysFalseCondition) {
  console.log('これは実行されません')
}

/* node:coverage ignore next 3 */
if (anAlwaysFalseCondition) {
  console.log('これは実行されません')
}

カバレッジレポーター

tapレポーターとspecレポーターは、カバレッジ統計のサマリーを出力します。また、lcovレポーターは、詳細なカバレッジレポートとして使用できる lcov ファイルを作成します。

bash
node --test --experimental-test-coverage --test-reporter=lcov --test-reporter-destination=lcov.info
  • このレポーターはテスト結果を報告しません。
  • このレポーターは、他のレポーターと併用するのが理想的です。

モッキング

node:testモジュールは、トップレベルのmockオブジェクトを介して、テスト中のモッキングをサポートしています。次の例では、2 つの数値を加算する関数のスパイを作成します。その後、このスパイを使用して、関数が期待通りに呼び出されたことをアサートします。

js
import assert from 'node:assert'
import { mock, test } from 'node:test'

test('spies on a function', () => {
  const sum = mock.fn((a, b) => {
    return a + b
  })

  assert.strictEqual(sum.mock.callCount(), 0)
  assert.strictEqual(sum(3, 4), 7)
  assert.strictEqual(sum.mock.callCount(), 1)

  const call = sum.mock.calls[0]
  assert.deepStrictEqual(call.arguments, [3, 4])
  assert.strictEqual(call.result, 7)
  assert.strictEqual(call.error, undefined)

  // Reset the globally tracked mocks.
  mock.reset()
})
js
'use strict'
const assert = require('node:assert')
const { mock, test } = require('node:test')

test('spies on a function', () => {
  const sum = mock.fn((a, b) => {
    return a + b
  })

  assert.strictEqual(sum.mock.callCount(), 0)
  assert.strictEqual(sum(3, 4), 7)
  assert.strictEqual(sum.mock.callCount(), 1)

  const call = sum.mock.calls[0]
  assert.deepStrictEqual(call.arguments, [3, 4])
  assert.strictEqual(call.result, 7)
  assert.strictEqual(call.error, undefined)

  // Reset the globally tracked mocks.
  mock.reset()
})

同じモッキング機能は、各テストのTestContextオブジェクトにも公開されています。次の例では、TestContextで公開されている API を使用して、オブジェクトメソッドのスパイを作成します。テストコンテキストを介したモッキングの利点は、テストが終了すると、テストランナーがすべてのモック機能を自動的に復元することです。

js
test('spies on an object method', t => {
  const number = {
    value: 5,
    add(a) {
      return this.value + a
    },
  }

  t.mock.method(number, 'add')
  assert.strictEqual(number.add.mock.callCount(), 0)
  assert.strictEqual(number.add(3), 8)
  assert.strictEqual(number.add.mock.callCount(), 1)

  const call = number.add.mock.calls[0]

  assert.deepStrictEqual(call.arguments, [3])
  assert.strictEqual(call.result, 8)
  assert.strictEqual(call.target, undefined)
  assert.strictEqual(call.this, number)
})

タイマー

タイマーのモック化は、setIntervalsetTimeoutなどのタイマーの動作を、指定された時間間隔を実際に待つことなくシミュレートして制御するために、ソフトウェアテストで一般的に使用される手法です。

メソッドと機能の完全なリストについては、MockTimersクラスを参照してください。

これにより、開発者は、時間依存の機能に対して、より信頼性が高く予測可能なテストを作成できます。

以下の例は、setTimeoutをモックする方法を示しています。.enable({ apis: ['setTimeout'] }); を使用すると、node:timersnode:timers/promisesモジュール、および Node.js のグローバルコンテキストのsetTimeout関数がモックされます。

注記: import { setTimeout } from 'node:timers'などのデストラクチャリング関数は、現在この API ではサポートされていません。

js
import assert from 'node:assert'
import { mock, test } from 'node:test'

test('mocks setTimeout to be executed synchronously without having to actually wait for it', () => {
  const fn = mock.fn()

  // Optionally choose what to mock
  mock.timers.enable({ apis: ['setTimeout'] })
  setTimeout(fn, 9999)
  assert.strictEqual(fn.mock.callCount(), 0)

  // Advance in time
  mock.timers.tick(9999)
  assert.strictEqual(fn.mock.callCount(), 1)

  // Reset the globally tracked mocks.
  mock.timers.reset()

  // If you call reset mock instance, it will also reset timers instance
  mock.reset()
})
js
const assert = require('node:assert')
const { mock, test } = require('node:test')

test('mocks setTimeout to be executed synchronously without having to actually wait for it', () => {
  const fn = mock.fn()

  // Optionally choose what to mock
  mock.timers.enable({ apis: ['setTimeout'] })
  setTimeout(fn, 9999)
  assert.strictEqual(fn.mock.callCount(), 0)

  // Advance in time
  mock.timers.tick(9999)
  assert.strictEqual(fn.mock.callCount(), 1)

  // Reset the globally tracked mocks.
  mock.timers.reset()

  // If you call reset mock instance, it will also reset timers instance
  mock.reset()
})

同じモック機能は、各テストのTestContextオブジェクトの mock プロパティにも公開されています。テストコンテキストを介してモック化することの利点は、テストが終了すると、テストランナーがすべてのモック化されたタイマー機能を自動的に復元することです。

js
import assert from 'node:assert'
import { test } from 'node:test'

test('mocks setTimeout to be executed synchronously without having to actually wait for it', context => {
  const fn = context.mock.fn()

  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['setTimeout'] })
  setTimeout(fn, 9999)
  assert.strictEqual(fn.mock.callCount(), 0)

  // Advance in time
  context.mock.timers.tick(9999)
  assert.strictEqual(fn.mock.callCount(), 1)
})
js
const assert = require('node:assert')
const { test } = require('node:test')

test('mocks setTimeout to be executed synchronously without having to actually wait for it', context => {
  const fn = context.mock.fn()

  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['setTimeout'] })
  setTimeout(fn, 9999)
  assert.strictEqual(fn.mock.callCount(), 0)

  // Advance in time
  context.mock.timers.tick(9999)
  assert.strictEqual(fn.mock.callCount(), 1)
})

日付

モックタイマー API では、Dateオブジェクトのモックも可能です。これは、時間依存の機能のテストや、Date.now()などの内部カレンダー関数のシミュレーションに役立つ機能です。

日付の実装もMockTimersクラスの一部です。メソッドと機能の完全なリストについては、そちらを参照してください。

注記: 日付とタイマーは、一緒にモックされた場合に依存関係を持ちます。つまり、DatesetTimeoutの両方をモックした場合、時間を進めると、単一の内部クロックをシミュレートするため、モックされた日付も進みます。

以下の例は、Dateオブジェクトをモックし、現在のDate.now()値を取得する方法を示しています。

js
import assert from 'node:assert'
import { test } from 'node:test'

test('mocks the Date object', context => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['Date'] })
  // If not specified, the initial date will be based on 0 in the UNIX epoch
  assert.strictEqual(Date.now(), 0)

  // Advance in time will also advance the date
  context.mock.timers.tick(9999)
  assert.strictEqual(Date.now(), 9999)
})
js
const assert = require('node:assert')
const { test } = require('node:test')

test('mocks the Date object', context => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['Date'] })
  // If not specified, the initial date will be based on 0 in the UNIX epoch
  assert.strictEqual(Date.now(), 0)

  // Advance in time will also advance the date
  context.mock.timers.tick(9999)
  assert.strictEqual(Date.now(), 9999)
})

初期のエポックが設定されていない場合、初期日付は UNIX エポックの 0 に基づきます。これは、1970 年 1 月 1 日 00:00:00 UTC です。.enable()メソッドにnowプロパティを渡すことで、初期日付を設定できます。この値は、モックされたDateオブジェクトの初期日付として使用されます。正の整数または別の Date オブジェクトのいずれかです。

js
import assert from 'node:assert'
import { test } from 'node:test'

test('mocks the Date object with initial time', context => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['Date'], now: 100 })
  assert.strictEqual(Date.now(), 100)

  // Advance in time will also advance the date
  context.mock.timers.tick(200)
  assert.strictEqual(Date.now(), 300)
})
js
const assert = require('node:assert')
const { test } = require('node:test')

test('mocks the Date object with initial time', context => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['Date'], now: 100 })
  assert.strictEqual(Date.now(), 100)

  // Advance in time will also advance the date
  context.mock.timers.tick(200)
  assert.strictEqual(Date.now(), 300)
})

.setTime()メソッドを使用して、モックされた日付を手動で別の時間に変更できます。このメソッドは正の整数のみを受け付けます。

注記: このメソッドは、新しい時間から過去にあるモックされたタイマーを実行します。

以下の例では、モックされた日付の新しい時間を設定しています。

js
import assert from 'node:assert'
import { test } from 'node:test'

test('sets the time of a date object', context => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['Date'], now: 100 })
  assert.strictEqual(Date.now(), 100)

  // Advance in time will also advance the date
  context.mock.timers.setTime(1000)
  context.mock.timers.tick(200)
  assert.strictEqual(Date.now(), 1200)
})
js
const assert = require('node:assert')
const { test } = require('node:test')

test('sets the time of a date object', context => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['Date'], now: 100 })
  assert.strictEqual(Date.now(), 100)

  // Advance in time will also advance the date
  context.mock.timers.setTime(1000)
  context.mock.timers.tick(200)
  assert.strictEqual(Date.now(), 1200)
})

過去に実行するように設定されているタイマーがある場合、.tick()メソッドが呼び出されたかのように実行されます。これは、すでに過去にある時間依存の機能をテストする場合に役立ちます。

js
import assert from 'node:assert'
import { test } from 'node:test'

test('runs timers as setTime passes ticks', context => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['setTimeout', 'Date'] })
  const fn = context.mock.fn()
  setTimeout(fn, 1000)

  context.mock.timers.setTime(800)
  // Timer is not executed as the time is not yet reached
  assert.strictEqual(fn.mock.callCount(), 0)
  assert.strictEqual(Date.now(), 800)

  context.mock.timers.setTime(1200)
  // Timer is executed as the time is now reached
  assert.strictEqual(fn.mock.callCount(), 1)
  assert.strictEqual(Date.now(), 1200)
})
js
const assert = require('node:assert')
const { test } = require('node:test')

test('runs timers as setTime passes ticks', context => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['setTimeout', 'Date'] })
  const fn = context.mock.fn()
  setTimeout(fn, 1000)

  context.mock.timers.setTime(800)
  // Timer is not executed as the time is not yet reached
  assert.strictEqual(fn.mock.callCount(), 0)
  assert.strictEqual(Date.now(), 800)

  context.mock.timers.setTime(1200)
  // Timer is executed as the time is now reached
  assert.strictEqual(fn.mock.callCount(), 1)
  assert.strictEqual(Date.now(), 1200)
})

.runAll()を使用すると、キューにあるすべてのタイマーを実行します。これにより、時間が経過したかのように、実行された最後のタイマーの時間にモックされた日付も進みます。

js
import assert from 'node:assert'
import { test } from 'node:test'

test('runs timers as setTime passes ticks', context => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['setTimeout', 'Date'] })
  const fn = context.mock.fn()
  setTimeout(fn, 1000)
  setTimeout(fn, 2000)
  setTimeout(fn, 3000)

  context.mock.timers.runAll()
  // All timers are executed as the time is now reached
  assert.strictEqual(fn.mock.callCount(), 3)
  assert.strictEqual(Date.now(), 3000)
})
js
const assert = require('node:assert')
const { test } = require('node:test')

test('runs timers as setTime passes ticks', context => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['setTimeout', 'Date'] })
  const fn = context.mock.fn()
  setTimeout(fn, 1000)
  setTimeout(fn, 2000)
  setTimeout(fn, 3000)

  context.mock.timers.runAll()
  // All timers are executed as the time is now reached
  assert.strictEqual(fn.mock.callCount(), 3)
  assert.strictEqual(Date.now(), 3000)
})

スナップショットテスト

[安定版: 1 - 試験版]

安定版: 1 安定性: 1.0 - 開発初期段階

スナップショットテストでは、任意の値を文字列値にシリアライズし、一連の既知の良好な値と比較できます。既知の良好な値はスナップショットと呼ばれ、スナップショットファイルに保存されます。スナップショットファイルはテストランナーによって管理されますが、デバッグを容易にするために人間が読めるように設計されています。ベストプラクティスとして、スナップショットファイルはテストファイルと一緒にソースコード管理にチェックインします。

スナップショットファイルは、--test-update-snapshotsコマンドラインフラグを使用して Node.js を起動することで生成されます。各テストファイルごとに個別のスナップショットファイルが生成されます。デフォルトでは、スナップショットファイルの名前は、.snapshotファイル拡張子付きのテストファイルと同じになります。この動作は、snapshot.setResolveSnapshotPath()関数を使用して構成できます。各スナップショットアサーションは、スナップショットファイル内のエクスポートに対応します。

スナップショットテストの例を以下に示します。このテストを初めて実行すると、対応するスナップショットファイルが存在しないため失敗します。

js
// test.js
suite('suite of snapshot tests', () => {
  test('snapshot test', t => {
    t.assert.snapshot({ value1: 1, value2: 2 })
    t.assert.snapshot(5)
  })
})

--test-update-snapshotsを使用してテストファイルを実行することで、スナップショットファイルを生成します。テストはパスし、テストファイルと同じディレクトリにtest.js.snapshotという名前のファイルが作成されます。スナップショットファイルの内容を以下に示します。各スナップショットは、テストの完全名と、同じテスト内のスナップショットを区別するためのカウンターによって識別されます。

js
exports[`suite of snapshot tests > snapshot test 1`] = `
{
  "value1": 1,
  "value2": 2
}
`

exports[`suite of snapshot tests > snapshot test 2`] = `
5
`

スナップショットファイルが作成されたら、--test-update-snapshotsフラグなしでテストを再度実行します。これでテストはパスするはずです。

テストレポーター

[履歴]

バージョン変更内容
v19.9.0, v18.17.0レポーターは node:test/reporters で公開されるようになりました。
v19.6.0, v18.15.0追加: v19.6.0, v18.15.0

node:test モジュールは、テストランナーで特定のレポーターを使用するために --test-reporter フラグを渡すことをサポートしています。

以下の組み込みレポーターがサポートされています。

  • spec spec レポーターは、テスト結果を人間が読める形式で出力します。これはデフォルトのレポーターです。
  • tap tap レポーターは、TAP 形式でテスト結果を出力します。
  • dot dot レポーターは、コンパクトな形式でテスト結果を出力します。合格したテストは . で、失敗したテストは X で表されます。
  • junit junit レポーターは、JUnit XML 形式でテスト結果を出力します。
  • lcov lcov レポーターは、--experimental-test-coverage フラグと併用すると、テストカバレッジを出力します。

これらのレポーターの正確な出力は、Node.js のバージョン間で変更される可能性があり、プログラム的に依存すべきではありません。テストランナーの出力にプログラムからアクセスする必要がある場合は、<TestsStream>によって発行されるイベントを使用してください。

レポーターは node:test/reporters モジュールを介して利用できます。

js
import { tap, spec, dot, junit, lcov } from 'node:test/reporters'
js
const { tap, spec, dot, junit, lcov } = require('node:test/reporters')

カスタムレポーター

--test-reporter を使用して、カスタムレポーターへのパスを指定できます。カスタムレポーターは、stream.compose で受け入れられる値をエクスポートするモジュールです。レポーターは、<TestsStream>によって発行されるイベントを変換する必要があります。

<stream.Transform> を使用したカスタムレポーターの例:

js
import { Transform } from 'node:stream'

const customReporter = new Transform({
  writableObjectMode: true,
  transform(event, encoding, callback) {
    switch (event.type) {
      case 'test:dequeue':
        callback(null, `test ${event.data.name} dequeued`)
        break
      case 'test:enqueue':
        callback(null, `test ${event.data.name} enqueued`)
        break
      case 'test:watch:drained':
        callback(null, 'test watch queue drained')
        break
      case 'test:start':
        callback(null, `test ${event.data.name} started`)
        break
      case 'test:pass':
        callback(null, `test ${event.data.name} passed`)
        break
      case 'test:fail':
        callback(null, `test ${event.data.name} failed`)
        break
      case 'test:plan':
        callback(null, 'test plan')
        break
      case 'test:diagnostic':
      case 'test:stderr':
      case 'test:stdout':
        callback(null, event.data.message)
        break
      case 'test:coverage': {
        const { totalLineCount } = event.data.summary.totals
        callback(null, `total line count: ${totalLineCount}\n`)
        break
      }
    }
  },
})

export default customReporter
js
const { Transform } = require('node:stream')

const customReporter = new Transform({
  writableObjectMode: true,
  transform(event, encoding, callback) {
    switch (event.type) {
      case 'test:dequeue':
        callback(null, `test ${event.data.name} dequeued`)
        break
      case 'test:enqueue':
        callback(null, `test ${event.data.name} enqueued`)
        break
      case 'test:watch:drained':
        callback(null, 'test watch queue drained')
        break
      case 'test:start':
        callback(null, `test ${event.data.name} started`)
        break
      case 'test:pass':
        callback(null, `test ${event.data.name} passed`)
        break
      case 'test:fail':
        callback(null, `test ${event.data.name} failed`)
        break
      case 'test:plan':
        callback(null, 'test plan')
        break
      case 'test:diagnostic':
      case 'test:stderr':
      case 'test:stdout':
        callback(null, event.data.message)
        break
      case 'test:coverage': {
        const { totalLineCount } = event.data.summary.totals
        callback(null, `total line count: ${totalLineCount}\n`)
        break
      }
    }
  },
})

module.exports = customReporter

ジェネレーター関数を使用したカスタムレポーターの例:

js
export default async function* customReporter(source) {
  for await (const event of source) {
    switch (event.type) {
      case 'test:dequeue':
        yield `test ${event.data.name} dequeued\n`
        break
      case 'test:enqueue':
        yield `test ${event.data.name} enqueued\n`
        break
      case 'test:watch:drained':
        yield 'test watch queue drained\n'
        break
      case 'test:start':
        yield `test ${event.data.name} started\n`
        break
      case 'test:pass':
        yield `test ${event.data.name} passed\n`
        break
      case 'test:fail':
        yield `test ${event.data.name} failed\n`
        break
      case 'test:plan':
        yield 'test plan\n'
        break
      case 'test:diagnostic':
      case 'test:stderr':
      case 'test:stdout':
        yield `${event.data.message}\n`
        break
      case 'test:coverage': {
        const { totalLineCount } = event.data.summary.totals
        yield `total line count: ${totalLineCount}\n`
        break
      }
    }
  }
}
js
module.exports = async function* customReporter(source) {
  for await (const event of source) {
    switch (event.type) {
      case 'test:dequeue':
        yield `test ${event.data.name} dequeued\n`
        break
      case 'test:enqueue':
        yield `test ${event.data.name} enqueued\n`
        break
      case 'test:watch:drained':
        yield 'test watch queue drained\n'
        break
      case 'test:start':
        yield `test ${event.data.name} started\n`
        break
      case 'test:pass':
        yield `test ${event.data.name} passed\n`
        break
      case 'test:fail':
        yield `test ${event.data.name} failed\n`
        break
      case 'test:plan':
        yield 'test plan\n'
        break
      case 'test:diagnostic':
      case 'test:stderr':
      case 'test:stdout':
        yield `${event.data.message}\n`
        break
      case 'test:coverage': {
        const { totalLineCount } = event.data.summary.totals
        yield `total line count: ${totalLineCount}\n`
        break
      }
    }
  }
}

--test-reporter に提供される値は、JavaScript コードの import() で使用されるものと同様の文字列、または --import に提供される値である必要があります。

複数のレポーター

--test-reporter フラグは複数回指定して、複数のフォーマットでテスト結果をレポートできます。この場合、--test-reporter-destination を使用して、各レポーターの出力先を指定する必要があります。出力先は stdoutstderr、またはファイルパスです。レポーターと出力先は、指定された順序に従ってペアになります。

次の例では、spec レポーターは stdout に出力され、dot レポーターは file.txt に出力されます。

bash
node --test-reporter=spec --test-reporter=dot --test-reporter-destination=stdout --test-reporter-destination=file.txt

レポーターを 1 つだけ指定した場合、出力先が明示的に指定されていない限り、出力先は stdout になります。

run([options])

[履歴]

バージョン変更
v23.0.0cwd オプションを追加
v23.0.0カバレッジオプションを追加
v22.8.0isolation オプションを追加
v22.6.0globPatterns オプションを追加
v22.0.0, v20.14.0forceExit オプションを追加
v20.1.0, v18.17.0testNamePatterns オプションを追加
v18.9.0, v16.19.0v18.9.0、v16.19.0 で追加
  • options <Object> テスト実行の構成オプション。次のプロパティがサポートされています。

    • concurrency <number> | <boolean> 数値を指定すると、その数のテストプロセスが並列で実行されます。各プロセスは 1 つのテストファイルに対応します。true の場合、os.availableParallelism() - 1 個のテストファイルが並列で実行されます。false の場合、一度に 1 つのテストファイルしか実行されません。デフォルト: false

    • cwd: <string> テストランナーが使用する現在の作業ディレクトリを指定します。テストランナーの実行モデルに従ってファイルを解決するためのベースパスとして機能します。デフォルト: process.cwd()

    • files: <Array> 実行するファイルのリストを含む配列。デフォルト: テストランナーの実行モデルからの一致するファイル。

    • forceExit: <boolean> イベントループがアクティブなままであっても、既知のすべてのテストの実行が終了したら、テストランナーがプロセスを終了するように構成します。デフォルト: false

    • globPatterns: <Array> テストファイルと一致させる glob パターンのリストを含む配列。このオプションはfiles と同時に使用できません。デフォルト: テストランナーの実行モデルからの一致するファイル。

    • inspectPort <number> | <Function> テスト子プロセスのインスペクターポートを設定します。これは数値、または引数を引数として受け取り数値を返す関数にすることができます。nullish な値が提供された場合、各プロセスは主プロセスの process.debugPort から増分された独自のポートを取得します。isolation オプションが 'none' に設定されている場合、子プロセスは生成されないため、このオプションは無視されます。デフォルト: undefined

    • isolation <string> テストの分離の種類を構成します。'process' に設定すると、各テストファイルは別々の子プロセスで実行されます。'none' に設定すると、すべてのテストファイルが現在のプロセスで実行されます。デフォルト: 'process'

    • only: <boolean> 真理値の場合、テストコンテキストは only オプションが設定されているテストのみを実行します。

    • setup <Function> TestsStream インスタンスを受け取る関数で、テストが実行される前にリスナーを設定するために使用できます。デフォルト: undefined

    • execArgv <Array> サブプロセスの生成時に node 実行可能ファイルに渡す CLI フラグの配列。isolation'none' の場合、このオプションは効果がありません。デフォルト: []

    • argv <Array> サブプロセスの生成時に各テストファイルに渡す CLI フラグの配列。isolation'none' の場合、このオプションは効果がありません。デフォルト: []

    • signal <AbortSignal> 実行中のテストの実行を中止できます。

    • testNamePatterns <string> | <RegExp> | <Array> 文字列、正規表現、または正規表現の配列で、指定されたパターンと一致する名前のテストのみを実行するために使用できます。テスト名パターンは JavaScript 正規表現として解釈されます。実行される各テストについて、beforeEach()などの対応するテストフックも実行されます。デフォルト: undefined

    • testSkipPatterns <string> | <RegExp> | <Array> 文字列、正規表現、または正規表現の配列で、指定されたパターンと一致する名前のテストの実行を除外するために使用できます。テスト名パターンは JavaScript 正規表現として解釈されます。実行される各テストについて、beforeEach()などの対応するテストフックも実行されます。デフォルト: undefined

    • timeout <number> テスト実行が失敗するまでのミリ秒数。指定されていない場合、サブテストは親からこの値を継承します。デフォルト: Infinity

    • watch <boolean> ウォッチモードで実行するかどうか。デフォルト: false

    • shard <Object> 特定のシャードでテストを実行します。デフォルト: undefined

    • index <number> 実行するシャードのインデックスを指定する、1 から\<total\>の間の正の整数です。このオプションは必須です。

    • total <number> テストファイルを分割するシャードの総数を指定する正の整数です。このオプションは必須です。

    • coverage <boolean> コードカバレッジの収集を有効にします。デフォルト: false

    • coverageExcludeGlobs <string> | <Array> glob パターンを使用して、絶対パスと相対パスの両方に一致する特定のファイルをコードカバレッジから除外します。このプロパティは、coveragetrue に設定されている場合にのみ適用されます。coverageExcludeGlobscoverageIncludeGlobs の両方が提供されている場合、ファイルはカバレッジレポートに含めるために両方の条件を満たす必要があります。デフォルト: undefined

    • coverageIncludeGlobs <string> | <Array> glob パターンを使用して、絶対パスと相対パスの両方に一致する特定のファイルをコードカバレッジに含めます。このプロパティは、coveragetrue に設定されている場合にのみ適用されます。coverageExcludeGlobscoverageIncludeGlobs の両方が提供されている場合、ファイルはカバレッジレポートに含めるために両方の条件を満たす必要があります。デフォルト: undefined

    • lineCoverage <number> カバレッジされた行の最小パーセンテージを要求します。コードカバレッジが指定されたしきい値に達しない場合、プロセスはコード 1 で終了します。デフォルト: 0

    • branchCoverage <number> カバレッジされたブランチの最小パーセンテージを要求します。コードカバレッジが指定されたしきい値に達しない場合、プロセスはコード 1 で終了します。デフォルト: 0

    • functionCoverage <number> カバレッジされた関数の最小パーセンテージを要求します。コードカバレッジが指定されたしきい値に達しない場合、プロセスはコード 1 で終了します。デフォルト: 0

  • 戻り値: <TestsStream>

注: shard は、さまざまな環境にわたる大規模な実行に最適な、マシンまたはプロセス間でのテスト実行を水平方向に並列化するために使用されます。ファイルの変更時にテストを自動的に再実行することで、迅速なコード反復に最適化されたwatch モードとは互換性がありません。

js
import { tap } from 'node:test/reporters'
import { run } from 'node:test'
import process from 'node:process'
import path from 'node:path'

run({ files: [path.resolve('./tests/test.js')] })
  .on('test:fail', () => {
    process.exitCode = 1
  })
  .compose(tap)
  .pipe(process.stdout)
js
const { tap } = require('node:test/reporters')
const { run } = require('node:test')
const path = require('node:path')

run({ files: [path.resolve('./tests/test.js')] })
  .on('test:fail', () => {
    process.exitCode = 1
  })
  .compose(tap)
  .pipe(process.stdout)

suite([name][, options][, fn])

追加:v22.0.0, v20.13.0

  • name <string> テスト結果を報告する際に表示されるスイートの名前。デフォルト: fnname プロパティ、または fn に名前がない場合は '<anonymous>'
  • options <Object> スイートのオプション設定。test([name][, options][, fn]) と同じオプションをサポートします。
  • fn <Function> | <AsyncFunction> ネストされたテストとスイートを宣言するスイート関数。この関数の最初の引数は SuiteContext オブジェクトです。デフォルト: 何もしない関数。
  • 戻り値: <Promise> undefined で即座に解決されます。

suite() 関数は node:test モジュールからインポートされます。

suite.skip([name][, options][, fn])

追加:v22.0.0, v20.13.0

スイートをスキップするための省略形。suite([name], { skip: true }[, fn]) と同じです。

suite.todo([name][, options][, fn])

追加:v22.0.0, v20.13.0

スイートを TODO としてマークするための省略形。suite([name], { todo: true }[, fn]) と同じです。

suite.only([name][, options][, fn])

追加:v22.0.0, v20.13.0

スイートを only としてマークするための省略形。suite([name], { only: true }[, fn]) と同じです。

test([name][, options][, fn])

[履歴]

バージョン変更
v20.2.0, v18.17.0skiptodoonly の省略形を追加
v18.8.0, v16.18.0signal オプションを追加
v18.7.0, v16.17.0timeout オプションを追加
v18.0.0, v16.17.0追加
  • name <string> テスト結果を報告する際に表示されるテストの名前。デフォルト: fnname プロパティ、または fn に名前がない場合は '<anonymous>'

  • options <Object> テストの設定オプション。以下のプロパティをサポートします。

    • concurrency <number> | <boolean> 数値を指定すると、アプリケーションスレッド内でその数のテストが並列に実行されます。true の場合、スケジュールされた非同期テストはすべてスレッド内で同時に実行されます。false の場合、一度に 1 つのテストしか実行されません。指定しない場合、サブテストはこの値を親から継承します。デフォルト: false
    • only <boolean> 真理値の場合、テストコンテキストが only テストを実行するように設定されていると、このテストが実行されます。それ以外の場合は、テストはスキップされます。デフォルト: false
    • signal <AbortSignal> 実行中のテストの中断を許可します。
    • skip <boolean> | <string> 真理値の場合、テストはスキップされます。文字列を指定すると、その文字列がテスト結果にテストスキップの理由として表示されます。デフォルト: false
    • todo <boolean> | <string> 真理値の場合、テストは TODO としてマークされます。文字列を指定すると、その文字列がテスト結果にテストが TODO である理由として表示されます。デフォルト: false
    • timeout <number> テストが完了するまでに許容されるミリ秒数。指定しない場合、サブテストはこの値を親から継承します。デフォルト: Infinity
    • plan <number> テストで実行されるアサーションとサブテストの数。テストで実行されるアサーションの数が計画で指定された数と一致しない場合、テストは失敗します。デフォルト: undefined
  • fn <Function> | <AsyncFunction> テスト対象の関数。この関数の最初の引数は TestContext オブジェクトです。テストがコールバックを使用する場合、コールバック関数は 2 番目の引数として渡されます。デフォルト: 何もしない関数。

  • 戻り値: <Promise> テストが完了すると undefined で解決されます。または、テストがスイート内で実行される場合はすぐに解決されます。

test() 関数は test モジュールからインポートされた値です。この関数の各呼び出しにより、テストが <TestsStream> に報告されます。

fn 引数に渡される TestContext オブジェクトを使用して、現在のテストに関連するアクションを実行できます。これには、テストのスキップ、追加の診断情報の追加、またはサブテストの作成などが含まれます。

test() は、テストが完了すると解決される Promise を返します。test() がスイート内で呼び出された場合、すぐに解決されます。トップレベルテストの場合、戻り値は通常破棄できます。ただし、サブテストの戻り値は、親テストが先に終了してサブテストをキャンセルするのを防ぐために使用してください。次の例を参照してください。

js
test('トップレベルテスト', async t => {
  // 次のサブテストの setTimeout() は、次の行で 'await' を削除した場合、親テストよりも長生きする可能性があります。親テストが完了すると、未処理のサブテストはすべてキャンセルされます。
  await t.test('長時間実行されるサブテスト', async t => {
    return new Promise((resolve, reject) => {
      setTimeout(resolve, 1000)
    })
  })
})

timeout オプションを使用して、timeout ミリ秒より長くかかるとテストを失敗させることができます。ただし、実行中のテストがアプリケーションスレッドをブロックし、スケジュールされたキャンセルを防ぐ可能性があるため、テストをキャンセルするための信頼できるメカニズムではありません。

test.skip([name][, options][, fn])

テストをスキップするための省略記法。test([name], { skip: true }[, fn])と同じです。

test.todo([name][, options][, fn])

テストをTODOとしてマークするための省略記法。test([name], { todo: true }[, fn])と同じです。

test.only([name][, options][, fn])

テストをonlyとしてマークするための省略記法。test([name], { only: true }[, fn])と同じです。

describe([name][, options][, fn])

suite()のエイリアスです。

describe()関数はnode:testモジュールからインポートされます。

describe.skip([name][, options][, fn])

スイートをスキップするための省略記法。describe([name], { skip: true }[, fn])と同じです。

describe.todo([name][, options][, fn])

スイートをTODOとしてマークするための省略記法。describe([name], { todo: true }[, fn])と同じです。

describe.only([name][, options][, fn])

追加されたバージョン: v19.8.0, v18.15.0

スイートをonlyとしてマークするための省略記法。describe([name], { only: true }[, fn])と同じです。

it([name][, options][, fn])

[履歴]

バージョン変更
v19.8.0, v18.16.0it()の呼び出しは、test()の呼び出しと同等になりました。
v18.6.0, v16.17.0追加されたバージョン: v18.6.0, v16.17.0

test()のエイリアスです。

it()関数はnode:testモジュールからインポートされます。

it.skip([name][, options][, fn])

テストをスキップするための省略記法。it([name], { skip: true }[, fn])と同じです。

it.todo([name][, options][, fn])

テストをTODOとしてマークするための省略記法。it([name], { todo: true }[, fn])と同じです。

it.only([name][, options][, fn])

追加されたバージョン: v19.8.0, v18.15.0

テストをonlyとしてマークするための省略記法。it([name], { only: true }[, fn])と同じです。

before([fn][, options])

追加: v18.8.0, v16.18.0

  • fn <Function> | <AsyncFunction> フック関数。フックがコールバックを使用する場合、コールバック関数は第二引数として渡されます。デフォルト: 何もしない関数。
  • options <Object> フックの構成オプション。以下のプロパティがサポートされています。
    • signal <AbortSignal> 実行中のフックの中断を許可します。
    • timeout <number> フックが失敗するまでのミリ秒数。指定しない場合、サブテストは親からこの値を継承します。デフォルト: Infinity

この関数は、スイートを実行する前に実行されるフックを作成します。

js
describe('tests', async () => {
  before(() => console.log('about to run some test'))
  it('is a subtest', () => {
    assert.ok('some relevant assertion here')
  })
})

after([fn][, options])

追加: v18.8.0, v16.18.0

  • fn <Function> | <AsyncFunction> フック関数。フックがコールバックを使用する場合、コールバック関数は第二引数として渡されます。デフォルト: 何もしない関数。
  • options <Object> フックの構成オプション。以下のプロパティがサポートされています。
    • signal <AbortSignal> 実行中のフックの中断を許可します。
    • timeout <number> フックが失敗するまでのミリ秒数。指定しない場合、サブテストは親からこの値を継承します。デフォルト: Infinity

この関数は、スイートを実行した後に実行されるフックを作成します。

js
describe('tests', async () => {
  after(() => console.log('finished running tests'))
  it('is a subtest', () => {
    assert.ok('some relevant assertion here')
  })
})

注記: スイート内のテストが失敗した場合でも、afterフックは確実に実行されます。

beforeEach([fn][, options])

追加: v18.8.0, v16.18.0

  • fn <Function> | <AsyncFunction> フック関数。フックがコールバックを使用する場合、コールバック関数は第 2 引数として渡されます。デフォルト: 何もしない関数。
  • options <Object> フックの構成オプション。以下のプロパティがサポートされています。
    • signal <AbortSignal> 実行中のフックの中断を許可します。
    • timeout <number> フックが失敗するまでのミリ秒数。指定しない場合、サブテストは親からこの値を継承します。デフォルト: Infinity

この関数は、現在のスイート内の各テストの前に実行されるフックを作成します。

js
describe('tests', async () => {
  beforeEach(() => console.log('about to run a test'))
  it('is a subtest', () => {
    assert.ok('some relevant assertion here')
  })
})

afterEach([fn][, options])

追加: v18.8.0, v16.18.0

  • fn <Function> | <AsyncFunction> フック関数。フックがコールバックを使用する場合、コールバック関数は第 2 引数として渡されます。デフォルト: 何もしない関数。
  • options <Object> フックの構成オプション。以下のプロパティがサポートされています。
    • signal <AbortSignal> 実行中のフックの中断を許可します。
    • timeout <number> フックが失敗するまでのミリ秒数。指定しない場合、サブテストは親からこの値を継承します。デフォルト: Infinity

この関数は、現在のスイート内の各テストの後で実行されるフックを作成します。afterEach()フックは、テストが失敗した場合でも実行されます。

js
describe('tests', async () => {
  afterEach(() => console.log('finished running a test'))
  it('is a subtest', () => {
    assert.ok('some relevant assertion here')
  })
})

snapshot

追加バージョン: v22.3.0

[安定版: 1 - 試験版]

安定版: 1 安定性: 1.0 - 開発初期段階

現在のプロセスにおけるデフォルトのスナップショット設定を構成するために使用されるメソッドを持つオブジェクトです。共通の構成コードを--requireまたは--importでプリロードされたモジュールに配置することで、すべてのファイルに同じ構成を適用できます。

snapshot.setDefaultSnapshotSerializers(serializers)

追加バージョン: v22.3.0

[安定版: 1 - 試験版]

安定版: 1 安定性: 1.0 - 開発初期段階

  • serializers <Array> スナップショットテストのデフォルトのシリアライザとして使用される同期関数の配列。

この関数は、テストランナーで使用されるデフォルトのシリアライゼーションメカニズムをカスタマイズするために使用されます。デフォルトでは、テストランナーは提供された値に対してJSON.stringify(value, null, 2)を呼び出すことでシリアライゼーションを実行します。JSON.stringify()には、循環構造とサポートされるデータ型に関する制限があります。より堅牢なシリアライゼーションメカニズムが必要な場合は、この関数を使用する必要があります。

snapshot.setResolveSnapshotPath(fn)

追加バージョン: v22.3.0

[安定版: 1 - 試験版]

安定版: 1 安定性: 1.0 - 開発初期段階

  • fn <Function> スナップショットファイルの場所を計算するために使用される関数。この関数は、テストファイルのパスを唯一の引数として受け取ります。テストがファイルに関連付けられていない場合(REPL など)、入力は未定義です。fn()は、スナップショットファイルの場所を指定する文字列を返す必要があります。

この関数は、スナップショットテストに使用されるスナップショットファイルの場所をカスタマイズするために使用されます。デフォルトでは、スナップショットファイル名は、エントリポイントファイル名と同じで、.snapshotファイル拡張子が付きます。

クラス: MockFunctionContext

追加: v19.1.0, v18.13.0

MockFunctionContextクラスは、MockTracker API を介して作成されたモックの動作を検査または操作するために使用されます。

ctx.calls

追加: v19.1.0, v18.13.0

モックへの呼び出しを追跡するために使用される内部配列のコピーを返すゲッターです。配列内の各エントリは、次のプロパティを持つオブジェクトです。

  • arguments <Array> モック関数に渡された引数の配列。
  • error <any> モック関数がスローされた場合、このプロパティにはスローされた値が含まれます。デフォルト: undefined
  • result <any> モック関数によって返された値。
  • stack <Error> モック関数の呼び出し元を特定するために使用できるスタックを持つErrorオブジェクト。
  • target <Function> | <undefined> モック関数がコンストラクタである場合、このフィールドには構築されているクラスが含まれます。それ以外の場合はundefinedになります。
  • this <any> モック関数のthis値。

ctx.callCount()

追加: v19.1.0, v18.13.0

  • 戻り値: <integer> このモックが呼び出された回数。

この関数は、このモックが呼び出された回数を返します。ctx.callsは内部の呼び出し追跡配列のコピーを作成するゲッターであるため、ctx.calls.lengthをチェックするよりも、この関数は効率的です。

ctx.mockImplementation(implementation)

追加日時: v19.1.0, v18.13.0

この関数は、既存のモックの動作を変更するために使用されます。

次の例では、t.mock.fn()を使用してモック関数を生成し、モック関数を呼び出し、その後モックの実装を別の関数に変更します。

js
test('changes a mock behavior', t => {
  let cnt = 0

  function addOne() {
    cnt++
    return cnt
  }

  function addTwo() {
    cnt += 2
    return cnt
  }

  const fn = t.mock.fn(addOne)

  assert.strictEqual(fn(), 1)
  fn.mock.mockImplementation(addTwo)
  assert.strictEqual(fn(), 3)
  assert.strictEqual(fn(), 5)
})

ctx.mockImplementationOnce(implementation[, onCall])

追加日時: v19.1.0, v18.13.0

  • implementation <Function> | <AsyncFunction> onCallで指定された呼び出し回数に対してモックの実装として使用される関数。
  • onCall <integer> implementationを使用する呼び出し回数。指定された呼び出しが既に発生している場合、例外がスローされます。デフォルト: 次の呼び出しの数。

この関数は、単一の呼び出しに対して既存のモックの動作を変更するために使用されます。呼び出しonCallが発生すると、モックはmockImplementationOnce()が呼び出されなかった場合に使用していた動作に戻ります。

次の例では、t.mock.fn()を使用してモック関数を生成し、モック関数を呼び出し、次の呼び出しに対してモックの実装を別の関数に変更し、その後以前の動作を再開します。

js
test('changes a mock behavior once', t => {
  let cnt = 0

  function addOne() {
    cnt++
    return cnt
  }

  function addTwo() {
    cnt += 2
    return cnt
  }

  const fn = t.mock.fn(addOne)

  assert.strictEqual(fn(), 1)
  fn.mock.mockImplementationOnce(addTwo)
  assert.strictEqual(fn(), 3)
  assert.strictEqual(fn(), 4)
})

ctx.resetCalls()

追加: v19.3.0, v18.13.0

モック関数の呼び出し履歴をリセットします。

ctx.restore()

追加: v19.1.0, v18.13.0

モック関数の動作を元の動作にリセットします。この関数を呼び出した後も、モックは使用できます。

クラス: MockModuleContext

追加: v22.3.0, v20.18.0

[安定版: 1 - 試験段階]

安定版: 1 安定性: 1.0 - 開発初期段階

MockModuleContextクラスは、MockTracker API を介して作成されたモジュールモックの動作を操作するために使用されます。

ctx.restore()

追加: v22.3.0, v20.18.0

モックモジュールの動作をリセットします。

クラス: MockTracker

追加: v19.1.0, v18.13.0

MockTrackerクラスは、モック機能の管理に使用されます。テストランナーモジュールは、MockTrackerインスタンスであるトップレベルのmockエクスポートを提供します。各テストは、テストコンテキストのmockプロパティを介して独自のMockTrackerインスタンスも提供します。

mock.fn([original[, implementation]][, options])

追加: v19.1.0, v18.13.0

  • original <Function> | <AsyncFunction> モックを作成するオプションの関数。デフォルト: 何もしない関数。

  • implementation <Function> | <AsyncFunction> originalのモック実装として使用されるオプションの関数。これは、特定の回数呼び出された場合に 1 つの動作を示し、その後originalの動作を復元するモックを作成する場合に役立ちます。デフォルト: originalで指定された関数。

  • options <Object> モック関数のオプションの構成オプション。次のプロパティがサポートされています。

    • times <integer> モックがimplementationの動作を使用する回数。モック関数がtimes回呼び出されると、自動的にoriginalの動作が復元されます。この値は 0 より大きい整数である必要があります。デフォルト: Infinity
  • 戻り値: <Proxy> モック関数。モック関数には特別なmockプロパティが含まれており、これはMockFunctionContextのインスタンスであり、モック関数の動作の検査と変更に使用できます。

この関数は、モック関数を作成するために使用されます。

次の例では、各呼び出しでカウンタを 1 ずつインクリメントするモック関数を作成します。timesオプションを使用して、最初の 2 回の呼び出しではカウンタに 1 ではなく 2 を追加するようにモックの動作を変更します。

js
test('mocks a counting function', t => {
  let cnt = 0

  function addOne() {
    cnt++
    return cnt
  }

  function addTwo() {
    cnt += 2
    return cnt
  }

  const fn = t.mock.fn(addOne, addTwo, { times: 2 })

  assert.strictEqual(fn(), 2)
  assert.strictEqual(fn(), 4)
  assert.strictEqual(fn(), 5)
  assert.strictEqual(fn(), 6)
})

mock.getter(object, methodName[, implementation][, options])

追加: v19.3.0, v18.13.0

この関数は、options.gettertrueに設定したMockTracker.methodのシンタックスシュガーです。

mock.method(object, methodName[, implementation][, options])

追加: v19.1.0, v18.13.0

  • object <Object> モック対象となるメソッドを持つオブジェクト。

  • methodName <string> | <symbol> モックするobject上のメソッドの識別子。object[methodName]が関数でない場合、エラーがスローされます。

  • implementation <Function> | <AsyncFunction> object[methodName]のモック実装として使用されるオプションの関数。デフォルト: object[methodName]で指定された元のメソッド。

  • options <Object> モックメソッドのオプションの構成オプション。以下のプロパティがサポートされています。

    • getter <boolean> trueの場合、object[methodName]はゲッターとして扱われます。このオプションはsetterオプションと併用できません。デフォルト: false。
    • setter <boolean> trueの場合、object[methodName]はセッターとして扱われます。このオプションはgetterオプションと併用できません。デフォルト: false。
    • times <integer> モックがimplementationの動作を使用する回数。モックメソッドがtimes回呼び出されると、元の動作が自動的に復元されます。この値は 0 より大きい整数である必要があります。デフォルト: Infinity
  • 戻り値: <Proxy> モックされたメソッド。モックされたメソッドには特別なmockプロパティが含まれており、これはMockFunctionContextのインスタンスであり、モックメソッドの動作の検査と変更に使用できます。

この関数は、既存のオブジェクトメソッドにモックを作成するために使用されます。次の例は、既存のオブジェクトメソッドにモックを作成する方法を示しています。

js
test('spies on an object method', t => {
  const number = {
    value: 5,
    subtract(a) {
      return this.value - a
    },
  }

  t.mock.method(number, 'subtract')
  assert.strictEqual(number.subtract.mock.callCount(), 0)
  assert.strictEqual(number.subtract(3), 2)
  assert.strictEqual(number.subtract.mock.callCount(), 1)

  const call = number.subtract.mock.calls[0]

  assert.deepStrictEqual(call.arguments, [3])
  assert.strictEqual(call.result, 2)
  assert.strictEqual(call.error, undefined)
  assert.strictEqual(call.target, undefined)
  assert.strictEqual(call.this, number)
})

mock.module(specifier[, options])

追加: v22.3.0, v20.18.0

[安定版: 1 - 実験的]

安定版: 1 安定性: 1.0 - 開発初期段階

  • specifier <string> | <URL> モック対象のモジュールを識別する文字列。

  • options <Object> モックモジュールのオプション設定。以下のプロパティがサポートされています。

    • cache <boolean> false の場合、require() または import() を呼び出すたびに新しいモックモジュールが生成されます。true の場合、後続の呼び出しでは同じモックモジュールが返され、モックモジュールは CommonJS キャッシュに挿入されます。デフォルト: false。
    • defaultExport <any> モックモジュールのデフォルトエクスポートとして使用されるオプションの値。この値が提供されない場合、ESM モックにはデフォルトエクスポートが含まれません。モックが CommonJS モジュールまたはビルトインモジュールの場合は、この設定が module.exports の値として使用されます。この値が提供されない場合、CJS とビルトインモックは module.exports の値として空のオブジェクトを使用します。
    • namedExports <Object> キーと値を使用してモックモジュールの名前付きエクスポートを作成するオプションのオブジェクト。モックが CommonJS モジュールまたはビルトインモジュールの場合は、これらの値が module.exports にコピーされます。したがって、名前付きエクスポートとオブジェクト以外のデフォルトエクスポートの両方を使用してモックが作成された場合、CJS またはビルトインモジュールとして使用されると、モックは例外をスローします。
  • 戻り値: <MockModuleContext> モックを操作するために使用できるオブジェクト。

この関数は、ECMAScript モジュール、CommonJS モジュール、および Node.js ビルトインモジュールのエクスポートをモックするために使用されます。モックする前に元のモジュールへの参照は影響を受けません。モジュールモックを有効にするには、--experimental-test-module-mocks コマンドラインフラグを使用して Node.js を起動する必要があります。

次の例は、モックがどのようにモジュールに対して作成されるかを示しています。

js
test('mocks a builtin module in both module systems', async t => {
  // 'node:readline' のモックを、名前付きエクスポート 'fn' を使用して作成します。
  // 'fn' は元の 'node:readline' モジュールには存在しません。
  const mock = t.mock.module('node:readline', {
    namedExports: {
      fn() {
        return 42
      },
    },
  })

  let esmImpl = await import('node:readline')
  let cjsImpl = require('node:readline')

  // cursorTo() は元の 'node:readline' モジュールのエクスポートです。
  assert.strictEqual(esmImpl.cursorTo, undefined)
  assert.strictEqual(cjsImpl.cursorTo, undefined)
  assert.strictEqual(esmImpl.fn(), 42)
  assert.strictEqual(cjsImpl.fn(), 42)

  mock.restore()

  // モックが復元され、元のビルトインモジュールが返されます。
  esmImpl = await import('node:readline')
  cjsImpl = require('node:readline')

  assert.strictEqual(typeof esmImpl.cursorTo, 'function')
  assert.strictEqual(typeof cjsImpl.cursorTo, 'function')
  assert.strictEqual(esmImpl.fn, undefined)
  assert.strictEqual(cjsImpl.fn, undefined)
})

mock.reset()

追加バージョン: v19.1.0, v18.13.0

この関数は、このMockTrackerによって以前に作成されたすべてのモックのデフォルトの動作を復元し、モックとMockTrackerインスタンスの関連付けを解除します。関連付けが解除された後もモックは使用できますが、MockTrackerインスタンスを使用してそれらの動作をリセットしたり、それらとやり取りしたりすることはできなくなります。

各テストの完了後、この関数はテストコンテキストのMockTrackerで呼び出されます。グローバルMockTrackerを広く使用している場合は、この関数を手動で呼び出すことをお勧めします。

mock.restoreAll()

追加バージョン: v19.1.0, v18.13.0

この関数は、このMockTrackerによって以前に作成されたすべてのモックのデフォルトの動作を復元します。mock.reset()とは異なり、mock.restoreAll()はモックとMockTrackerインスタンスの関連付けを解除しません。

mock.setter(object, methodName[, implementation][, options])

追加バージョン: v19.3.0, v18.13.0

この関数は、options.settertrueに設定したMockTracker.methodのシンタックスシュガーです。

クラス: MockTimers

[履歴]

バージョン変更
v23.1.0Mock Timers が安定版になりました。
v20.4.0, v18.19.0追加バージョン: v20.4.0, v18.19.0

[安定版: 2 - 安定版]

安定版: 2 安定性: 2 - 安定版

タイマーのモック化は、ソフトウェアテストで一般的に使用される手法であり、setIntervalsetTimeoutなどのタイマーの動作を、指定された時間間隔を実際に待たずにシミュレートして制御します。

MockTimers はDateオブジェクトのモック化も可能です。

MockTrackerは、MockTimersインスタンスであるトップレベルのtimersエクスポートを提供します。

timers.enable([enableOptions])

[履歴]

バージョン変更
v21.2.0, v20.11.0利用可能な API とデフォルトの初期エポックを含むオプションオブジェクトにパラメーターが更新されました。
v20.4.0, v18.19.0追加バージョン: v20.4.0, v18.19.0

指定されたタイマーに対してタイマーモックを有効にします。

  • enableOptions <オブジェクト> タイマーモックを有効にするためのオプションの構成オプション。次のプロパティがサポートされています。
    • apis <配列> モックするタイマーを含むオプションの配列。現在サポートされているタイマーの値は'setInterval''setTimeout''setImmediate''Date'です。デフォルト: ['setInterval', 'setTimeout', 'setImmediate', 'Date']。配列が提供されない場合、時間関連のすべての API('setInterval''clearInterval''setTimeout''clearTimeout''setImmediate''clearImmediate''Date')がデフォルトでモックされます。
    • now <数値> | <Date> Date.now()の値として使用する初期時間(ミリ秒単位)を表すオプションの数値または Date オブジェクト。デフォルト: 0

注意: 特定のタイマーのモックを有効にすると、関連付けられたクリア関数も暗黙的にモックされます。

注意: Dateをモックすると、同じ内部クロックを使用するため、モックされたタイマーの動作に影響します。

初期時間を設定しない場合の使用例:

js
import { mock } from 'node:test'
mock.timers.enable({ apis: ['setInterval'] })
js
const { mock } = require('node:test')
mock.timers.enable({ apis: ['setInterval'] })

上記の例では、setIntervalタイマーのモックを有効にし、clearInterval関数を暗黙的にモックします。node:timersnode:timers/promises、およびglobalThissetIntervalおよびclearInterval関数のみがモックされます。

初期時間を設定した場合の使用例:

js
import { mock } from 'node:test'
mock.timers.enable({ apis: ['Date'], now: 1000 })
js
const { mock } = require('node:test')
mock.timers.enable({ apis: ['Date'], now: 1000 })

初期 Date オブジェクトを時間として設定した場合の使用例:

js
import { mock } from 'node:test'
mock.timers.enable({ apis: ['Date'], now: new Date() })
js
const { mock } = require('node:test')
mock.timers.enable({ apis: ['Date'], now: new Date() })

あるいは、パラメーターなしでmock.timers.enable()を呼び出すと:

すべてのタイマー('setInterval''clearInterval''setTimeout''clearTimeout''setImmediate''clearImmediate')がモックされます。node:timersnode:timers/promises、およびglobalThissetIntervalclearIntervalsetTimeoutclearTimeoutsetImmediate、およびclearImmediate関数がモックされます。グローバルDateオブジェクトも同様にモックされます。

timers.reset()

追加: v20.4.0, v18.19.0

この関数は、このMockTimersインスタンスによって以前に作成されたすべてのモックのデフォルトの動作を復元し、MockTrackerインスタンスからモックを関連付け解除します。

注記: 各テストの完了後、この関数はテストコンテキストのMockTrackerで呼び出されます。

js
import { mock } from 'node:test'
mock.timers.reset()
js
const { mock } = require('node:test')
mock.timers.reset()

timers[Symbol.dispose]()

timers.reset()を呼び出します。

timers.tick([milliseconds])

追加: v20.4.0, v18.19.0

すべてのモックされたタイマーに対して時間を進めます。

  • milliseconds <number> タイマーを進める時間(ミリ秒単位)。デフォルト: 1

注記: これは Node.js のsetTimeoutの動作とは異なり、正の数のみを受け入れます。Node.js では、負の数のsetTimeoutは Web との互換性のためにのみサポートされています。

次の例では、setTimeout関数をモックし、.tickを使用して時間を進めて、保留中のすべてのタイマーをトリガーします。

js
import assert from 'node:assert'
import { test } from 'node:test'

test('mocks setTimeout to be executed synchronously without having to actually wait for it', context => {
  const fn = context.mock.fn()

  context.mock.timers.enable({ apis: ['setTimeout'] })

  setTimeout(fn, 9999)

  assert.strictEqual(fn.mock.callCount(), 0)

  // 時間を進める
  context.mock.timers.tick(9999)

  assert.strictEqual(fn.mock.callCount(), 1)
})
js
const assert = require('node:assert')
const { test } = require('node:test')

test('mocks setTimeout to be executed synchronously without having to actually wait for it', context => {
  const fn = context.mock.fn()
  context.mock.timers.enable({ apis: ['setTimeout'] })

  setTimeout(fn, 9999)
  assert.strictEqual(fn.mock.callCount(), 0)

  // 時間を進める
  context.mock.timers.tick(9999)

  assert.strictEqual(fn.mock.callCount(), 1)
})

あるいは、.tick関数を複数回呼び出すこともできます。

js
import assert from 'node:assert'
import { test } from 'node:test'

test('mocks setTimeout to be executed synchronously without having to actually wait for it', context => {
  const fn = context.mock.fn()
  context.mock.timers.enable({ apis: ['setTimeout'] })
  const nineSecs = 9000
  setTimeout(fn, nineSecs)

  const threeSeconds = 3000
  context.mock.timers.tick(threeSeconds)
  context.mock.timers.tick(threeSeconds)
  context.mock.timers.tick(threeSeconds)

  assert.strictEqual(fn.mock.callCount(), 1)
})
js
const assert = require('node:assert')
const { test } = require('node:test')

test('mocks setTimeout to be executed synchronously without having to actually wait for it', context => {
  const fn = context.mock.fn()
  context.mock.timers.enable({ apis: ['setTimeout'] })
  const nineSecs = 9000
  setTimeout(fn, nineSecs)

  const threeSeconds = 3000
  context.mock.timers.tick(threeSeconds)
  context.mock.timers.tick(threeSeconds)
  context.mock.timers.tick(threeSeconds)

  assert.strictEqual(fn.mock.callCount(), 1)
})

.tickを使用して時間を進めると、モックが有効になってから作成されたDateオブジェクトの時間も進みます(Dateもモックするように設定されている場合)。

js
import assert from 'node:assert'
import { test } from 'node:test'

test('mocks setTimeout to be executed synchronously without having to actually wait for it', context => {
  const fn = context.mock.fn()

  context.mock.timers.enable({ apis: ['setTimeout', 'Date'] })
  setTimeout(fn, 9999)

  assert.strictEqual(fn.mock.callCount(), 0)
  assert.strictEqual(Date.now(), 0)

  // 時間を進める
  context.mock.timers.tick(9999)
  assert.strictEqual(fn.mock.callCount(), 1)
  assert.strictEqual(Date.now(), 9999)
})
js
const assert = require('node:assert')
const { test } = require('node:test')

test('mocks setTimeout to be executed synchronously without having to actually wait for it', context => {
  const fn = context.mock.fn()
  context.mock.timers.enable({ apis: ['setTimeout', 'Date'] })

  setTimeout(fn, 9999)
  assert.strictEqual(fn.mock.callCount(), 0)
  assert.strictEqual(Date.now(), 0)

  // 時間を進める
  context.mock.timers.tick(9999)
  assert.strictEqual(fn.mock.callCount(), 1)
  assert.strictEqual(Date.now(), 9999)
})

明確な関数の使用

前述のように、タイマーのすべてのクリア関数(clearTimeoutclearIntervalclearImmediate)は暗黙的にモックされます。setTimeoutを使用した次の例を見てください。

js
import assert from 'node:assert'
import { test } from 'node:test'

test('mocks setTimeout to be executed synchronously without having to actually wait for it', context => {
  const fn = context.mock.fn()

  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['setTimeout'] })
  const id = setTimeout(fn, 9999)

  // 暗黙的にモックされる
  clearTimeout(id)
  context.mock.timers.tick(9999)

  // setTimeoutがクリアされたため、モック関数は呼び出されない
  assert.strictEqual(fn.mock.callCount(), 0)
})
js
const assert = require('node:assert')
const { test } = require('node:test')

test('mocks setTimeout to be executed synchronously without having to actually wait for it', context => {
  const fn = context.mock.fn()

  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['setTimeout'] })
  const id = setTimeout(fn, 9999)

  // 暗黙的にモックされる
  clearTimeout(id)
  context.mock.timers.tick(9999)

  // setTimeoutがクリアされたため、モック関数は呼び出されない
  assert.strictEqual(fn.mock.callCount(), 0)
})

Node.js タイマーモジュールの使用

タイマーのモックを有効にすると、node:timersnode:timers/promisesモジュール、および Node.js グローバルコンテキストからのタイマーが有効になります。

注記: import { setTimeout } from 'node:timers'のようなデストラクチャリング関数は、現在この API ではサポートされていません。

js
import assert from 'node:assert'
import { test } from 'node:test'
import nodeTimers from 'node:timers'
import nodeTimersPromises from 'node:timers/promises'

test('mocks setTimeout to be executed synchronously without having to actually wait for it', async context => {
  const globalTimeoutObjectSpy = context.mock.fn()
  const nodeTimerSpy = context.mock.fn()
  const nodeTimerPromiseSpy = context.mock.fn()

  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['setTimeout'] })
  setTimeout(globalTimeoutObjectSpy, 9999)
  nodeTimers.setTimeout(nodeTimerSpy, 9999)

  const promise = nodeTimersPromises.setTimeout(9999).then(nodeTimerPromiseSpy)

  // 時間を進める
  context.mock.timers.tick(9999)
  assert.strictEqual(globalTimeoutObjectSpy.mock.callCount(), 1)
  assert.strictEqual(nodeTimerSpy.mock.callCount(), 1)
  await promise
  assert.strictEqual(nodeTimerPromiseSpy.mock.callCount(), 1)
})
js
const assert = require('node:assert')
const { test } = require('node:test')
const nodeTimers = require('node:timers')
const nodeTimersPromises = require('node:timers/promises')

test('mocks setTimeout to be executed synchronously without having to actually wait for it', async context => {
  const globalTimeoutObjectSpy = context.mock.fn()
  const nodeTimerSpy = context.mock.fn()
  const nodeTimerPromiseSpy = context.mock.fn()

  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['setTimeout'] })
  setTimeout(globalTimeoutObjectSpy, 9999)
  nodeTimers.setTimeout(nodeTimerSpy, 9999)

  const promise = nodeTimersPromises.setTimeout(9999).then(nodeTimerPromiseSpy)

  // 時間を進める
  context.mock.timers.tick(9999)
  assert.strictEqual(globalTimeoutObjectSpy.mock.callCount(), 1)
  assert.strictEqual(nodeTimerSpy.mock.callCount(), 1)
  await promise
  assert.strictEqual(nodeTimerPromiseSpy.mock.callCount(), 1)
})

Node.js では、node:timers/promisessetIntervalAsyncGeneratorであり、この API でもサポートされています。

js
import assert from 'node:assert'
import { test } from 'node:test'
import nodeTimersPromises from 'node:timers/promises'
test('should tick five times testing a real use case', async context => {
  context.mock.timers.enable({ apis: ['setInterval'] })

  const expectedIterations = 3
  const interval = 1000
  const startedAt = Date.now()
  async function run() {
    const times = []
    for await (const time of nodeTimersPromises.setInterval(interval, startedAt)) {
      times.push(time)
      if (times.length === expectedIterations) break
    }
    return times
  }

  const r = run()
  context.mock.timers.tick(interval)
  context.mock.timers.tick(interval)
  context.mock.timers.tick(interval)

  const timeResults = await r
  assert.strictEqual(timeResults.length, expectedIterations)
  for (let it = 1; it < expectedIterations; it++) {
    assert.strictEqual(timeResults[it - 1], startedAt + interval * it)
  }
})
js
const assert = require('node:assert')
const { test } = require('node:test')
const nodeTimersPromises = require('node:timers/promises')
test('should tick five times testing a real use case', async context => {
  context.mock.timers.enable({ apis: ['setInterval'] })

  const expectedIterations = 3
  const interval = 1000
  const startedAt = Date.now()
  async function run() {
    const times = []
    for await (const time of nodeTimersPromises.setInterval(interval, startedAt)) {
      times.push(time)
      if (times.length === expectedIterations) break
    }
    return times
  }

  const r = run()
  context.mock.timers.tick(interval)
  context.mock.timers.tick(interval)
  context.mock.timers.tick(interval)

  const timeResults = await r
  assert.strictEqual(timeResults.length, expectedIterations)
  for (let it = 1; it < expectedIterations; it++) {
    assert.strictEqual(timeResults[it - 1], startedAt + interval * it)
  }
})

timers.runAll()

追加: v20.4.0, v18.19.0

保留中の全てのモックタイマーを即座にトリガーします。Dateオブジェクトもモックされている場合、Dateオブジェクトを最も遠いタイマーの時間に進めます。

以下の例では、保留中の全てのタイマーを即座にトリガーし、遅延なく実行します。

js
import assert from 'node:assert'
import { test } from 'node:test'

test('runAll functions following the given order', context => {
  context.mock.timers.enable({ apis: ['setTimeout', 'Date'] })
  const results = []
  setTimeout(() => results.push(1), 9999)

  // Notice that if both timers have the same timeout,
  // the order of execution is guaranteed
  setTimeout(() => results.push(3), 8888)
  setTimeout(() => results.push(2), 8888)

  assert.deepStrictEqual(results, [])

  context.mock.timers.runAll()
  assert.deepStrictEqual(results, [3, 2, 1])
  // The Date object is also advanced to the furthest timer's time
  assert.strictEqual(Date.now(), 9999)
})
js
const assert = require('node:assert')
const { test } = require('node:test')

test('runAll functions following the given order', context => {
  context.mock.timers.enable({ apis: ['setTimeout', 'Date'] })
  const results = []
  setTimeout(() => results.push(1), 9999)

  // Notice that if both timers have the same timeout,
  // the order of execution is guaranteed
  setTimeout(() => results.push(3), 8888)
  setTimeout(() => results.push(2), 8888)

  assert.deepStrictEqual(results, [])

  context.mock.timers.runAll()
  assert.deepStrictEqual(results, [3, 2, 1])
  // The Date object is also advanced to the furthest timer's time
  assert.strictEqual(Date.now(), 9999)
})

注記: runAll()関数は、タイマーモックのコンテキストでタイマーをトリガーするために特別に設計されています。モック環境外のリアルタイムシステムクロックや実際のタイマーには影響しません。

timers.setTime(milliseconds)

追加: v21.2.0, v20.11.0

モックされたDateオブジェクトの参照として使用される現在の Unix タイムスタンプを設定します。

js
import assert from 'node:assert'
import { test } from 'node:test'

test('runAll functions following the given order', context => {
  const now = Date.now()
  const setTime = 1000
  // Date.now is not mocked
  assert.deepStrictEqual(Date.now(), now)

  context.mock.timers.enable({ apis: ['Date'] })
  context.mock.timers.setTime(setTime)
  // Date.now is now 1000
  assert.strictEqual(Date.now(), setTime)
})
js
const assert = require('node:assert')
const { test } = require('node:test')

test('setTime replaces current time', context => {
  const now = Date.now()
  const setTime = 1000
  // Date.now is not mocked
  assert.deepStrictEqual(Date.now(), now)

  context.mock.timers.enable({ apis: ['Date'] })
  context.mock.timers.setTime(setTime)
  // Date.now is now 1000
  assert.strictEqual(Date.now(), setTime)
})

日付とタイマーの連携

日付オブジェクトとタイマーオブジェクトは互いに依存しています。setTime() を使用してモックされた Date オブジェクトに現在時刻を渡した場合、setTimeoutsetInterval で設定されたタイマーは影響を受けません

しかし、tick メソッドはモックされた Date オブジェクトを進めます

js
import assert from 'node:assert'
import { test } from 'node:test'

test('runAll関数は指定された順序に従って実行される', context => {
  context.mock.timers.enable({ apis: ['setTimeout', 'Date'] })
  const results = []
  setTimeout(() => results.push(1), 9999)

  assert.deepStrictEqual(results, [])
  context.mock.timers.setTime(12000)
  assert.deepStrictEqual(results, [])
  // 日付は進みますが、タイマーは動作しません
  assert.strictEqual(Date.now(), 12000)
})
js
const assert = require('node:assert')
const { test } = require('node:test')

test('runAll関数は指定された順序に従って実行される', context => {
  context.mock.timers.enable({ apis: ['setTimeout', 'Date'] })
  const results = []
  setTimeout(() => results.push(1), 9999)

  assert.deepStrictEqual(results, [])
  context.mock.timers.setTime(12000)
  assert.deepStrictEqual(results, [])
  // 日付は進みますが、タイマーは動作しません
  assert.strictEqual(Date.now(), 12000)
})

クラス: TestsStream

[履歴]

バージョン変更内容
v20.0.0, v19.9.0, v18.17.0テストがスイートの場合の test:pass および test:fail イベントに型を追加
v18.9.0, v16.19.0追加日: v18.9.0, v16.19.0

run()メソッドへの呼び出しが成功すると、新しい<TestsStream>オブジェクトが返され、テストの実行を表す一連のイベントがストリームされます。TestsStreamは、テストの定義順にイベントを発行します。

一部のイベントは、テストが定義されたのと同じ順序で発行されることが保証されていますが、他のイベントはテストが実行された順序で発行されます。

イベント: 'test:coverage'

  • data <Object>

    • summary <Object> カバレッジレポートを含むオブジェクト。

    • files <Array> 個々のファイルのコードカバレッジレポートの配列。各レポートは次のスキーマを持つオブジェクトです。

    • path <string> ファイルの絶対パス。

    • totalLineCount <number> 行の総数。

    • totalBranchCount <number> ブランチの総数。

    • totalFunctionCount <number> 関数の総数。

    • coveredLineCount <number> カバレッジのある行数。

    • coveredBranchCount <number> カバレッジのあるブランチ数。

    • coveredFunctionCount <number> カバレッジのある関数数。

    • coveredLinePercent <number> 行カバレッジの割合。

    • coveredBranchPercent <number> ブランチカバレッジの割合。

    • coveredFunctionPercent <number> 関数カバレッジの割合。

    • functions <Array> 関数カバレッジを表す関数の配列。

    • name <string> 関数の名前。

    • line <number> 関数が定義されている行番号。

    • count <number> 関数が呼び出された回数。

    • branches <Array> ブランチカバレッジを表すブランチの配列。

    • line <number> ブランチが定義されている行番号。

    • count <number> ブランチが実行された回数。

    • lines <Array> 行番号とカバレッジ回数を表す行の配列。

    • line <number> 行番号。

    • count <number> 行がカバレッジされた回数。

    • thresholds <Object> 各カバレッジの種類に対するカバレッジの可否を含むオブジェクト。

    • function <number> 関数カバレッジの閾値。

    • branch <number> ブランチカバレッジの閾値。

    • line <number> 行カバレッジの閾値。

    • totals <Object> すべてのファイルのカバレッジのサマリーを含むオブジェクト。

    • totalLineCount <number> 行の総数。

    • totalBranchCount <number> ブランチの総数。

    • totalFunctionCount <number> 関数の総数。

    • coveredLineCount <number> カバレッジのある行数。

    • coveredBranchCount <number> カバレッジのあるブランチ数。

    • coveredFunctionCount <number> カバレッジのある関数数。

    • coveredLinePercent <number> 行カバレッジの割合。

    • coveredBranchPercent <number> ブランチカバレッジの割合。

    • coveredFunctionPercent <number> 関数カバレッジの割合。

    • workingDirectory <string> コードカバレッジが開始された時の作業ディレクトリ。テストによって Node.js プロセスの作業ディレクトリが変更された場合に、相対パス名を表示するのに役立ちます。

    • nesting <number> テストのネストレベル。

コードカバレッジが有効になり、すべてのテストが完了したときに送出されます。

イベント: 'test:complete'

  • data <Object>
    • column <number> | <undefined> テストが定義されている列番号、または REPL でテストが実行された場合はundefined
    • details <Object> 追加の実行メタデータ。
    • passed <boolean> テストがパスしたかどうか。
    • duration_ms <number> テストのミリ秒単位の期間。
    • error <Error> | <undefined> テストがパスしなかった場合、テストによってスローされたエラーをラップするエラー。
    • cause <Error> テストによって実際にスローされたエラー。
    • type <string> | <undefined> テストの種類。これがスイートかどうかを示すために使用されます。
    • file <string> | <undefined> テストファイルのパス。テストが REPL で実行された場合はundefined
    • line <number> | <undefined> テストが定義されている行番号、または REPL でテストが実行された場合はundefined
    • name <string> テスト名。
    • nesting <number> テストのネストレベル。
    • testNumber <number> テストの序数。
    • todo <string> | <boolean> | <undefined> context.todo が呼び出された場合に存在します。
    • skip <string> | <boolean> | <undefined> context.skip が呼び出された場合に存在します。

テストの実行が完了すると発生します。このイベントは、テストが定義された順序と同じ順序で発生するとは限りません。対応する宣言順序イベントは'test:pass''test:fail'です。

イベント: 'test:dequeue'

  • data <Object>
    • column <number> | <undefined> テストが定義されている列番号、または REPL でテストが実行された場合はundefined
    • file <string> | <undefined> テストファイルのパス、REPL でテストが実行された場合はundefined
    • line <number> | <undefined> テストが定義されている行番号、または REPL でテストが実行された場合はundefined
    • name <string> テスト名。
    • nesting <number> テストのネストレベル。

テストが実行される直前に、キューからテストが取り出されたときに発生します。このイベントは、テストが定義された順序と同じ順序で発生するとは限りません。対応する宣言順序イベントは'test:start'です。

イベント: 'test:diagnostic'

  • data <Object>
    • column <number> | <undefined> テストが定義されている列番号、または REPL でテストが実行された場合はundefined
    • file <string> | <undefined> テストファイルのパス、REPL でテストが実行された場合はundefined
    • line <number> | <undefined> テストが定義されている行番号、または REPL でテストが実行された場合はundefined
    • message <string> 診断メッセージ。
    • nesting <number> テストのネストレベル。

context.diagnosticが呼び出されたときに発生します。このイベントは、テストが定義された順序と同じ順序で発生することが保証されています。

Event: 'test:enqueue'

  • data <Object>
    • column <number> | <undefined> テストが定義されている列番号、または REPL でテストが実行された場合はundefined
    • file <string> | <undefined> テストファイルのパス、テストが REPL で実行された場合はundefined
    • line <number> | <undefined> テストが定義されている行番号、または REPL でテストが実行された場合はundefined
    • name <string> テスト名。
    • nesting <number> テストのネストレベル。

テストが実行のためにキューに追加されたときに送出されます。

Event: 'test:fail'

  • data <Object>
    • column <number> | <undefined> テストが定義されている列番号、または REPL でテストが実行された場合はundefined
    • details <Object> 追加の実行メタデータ。
    • duration_ms <number> テストのミリ秒単位の期間。
    • error <Error> テストによってスローされたエラーをラップするエラー。
    • cause <Error> テストによって実際にスローされたエラー。
    • type <string> | <undefined> テストの種類。これはスイートであるかどうかを示すために使用されます。
    • file <string> | <undefined> テストファイルのパス、テストが REPL で実行された場合はundefined
    • line <number> | <undefined> テストが定義されている行番号、または REPL でテストが実行された場合はundefined
    • name <string> テスト名。
    • nesting <number> テストのネストレベル。
    • testNumber <number> テストの序数。
    • todo <string> | <boolean> | <undefined> context.todo が呼び出された場合に存在します。
    • skip <string> | <boolean> | <undefined> context.skip が呼び出された場合に存在します。

テストが失敗したときに送出されます。このイベントは、テストが定義されているのと同じ順序で送出されることが保証されています。対応する実行順序イベントは'test:complete'です。

イベント: 'test:pass'

テストがパスした場合に送出されます。このイベントは、テストが定義された順序と同じ順序で送出されることが保証されています。対応する実行順序イベントは'test:complete'です。

イベント: 'test:plan'

  • data <Object>
    • column <number> | <undefined> テストが定義されている列番号、または REPL でテストが実行された場合はundefined
    • file <string> | <undefined> テストファイルのパス、REPL でテストが実行された場合はundefined
    • line <number> | <undefined> テストが定義されている行番号、または REPL でテストが実行された場合はundefined
    • nesting <number> テストのネストレベル。
    • count <number> 実行されたサブテストの数。

与えられたテストについて、すべてのサブテストが完了したときに発生します。このイベントは、テストが定義されたのと同じ順序で発生することが保証されています。

イベント: 'test:start'

  • data <Object>
    • column <number> | <undefined> テストが定義されている列番号、または REPL でテストが実行された場合はundefined
    • file <string> | <undefined> テストファイルのパス、REPL でテストが実行された場合はundefined
    • line <number> | <undefined> テストが定義されている行番号、または REPL でテストが実行された場合はundefined
    • name <string> テスト名。
    • nesting <number> テストのネストレベル。

テストが自身の状態とサブテストの状態を報告し始めるときに発生します。このイベントは、テストが定義されたのと同じ順序で発生することが保証されています。対応する実行順序イベントは'test:dequeue'です。

イベント: 'test:stderr'

実行中のテストがstderrに出力した際に発行されます。このイベントは--testフラグが渡された場合にのみ発行されます。このイベントは、テストが定義された順序で発行されるとは限りません。

イベント: 'test:stdout'

実行中のテストがstdoutに出力した際に発行されます。このイベントは--testフラグが渡された場合にのみ発行されます。このイベントは、テストが定義された順序で発行されるとは限りません。

イベント: 'test:summary'

  • data <Object>

    • counts <Object> さまざまなテスト結果の数を格納したオブジェクト。

    • cancelled <number> キャンセルされたテストの総数。

    • failed <number> 失敗したテストの総数。

    • passed <number> 成功したテストの総数。

    • skipped <number> スキップされたテストの総数。

    • suites <number> 実行されたスイートの総数。

    • tests <number> スイートを除く、実行されたテストの総数。

    • todo <number> TODO テストの総数。

    • topLevel <number> トップレベルのテストとスイートの総数。

    • duration_ms <number> テスト実行時間(ミリ秒)。

    • file <string> | <undefined> サマリーを生成したテストファイルのパス。サマリーが複数のファイルに対応する場合はundefined

    • success <boolean> テスト実行が成功したかどうかを示します。失敗したテストや満たされていないカバレッジしきい値など、エラー状態が発生した場合はfalseに設定されます。

テスト実行が完了したときに発行されます。このイベントには、完了したテスト実行に関するメトリクスが含まれており、テスト実行が成功したか失敗したかを判断するのに役立ちます。プロセスレベルのテスト分離を使用する場合、最終的な累積サマリーに加えて、各テストファイルごとに'test:summary'イベントが生成されます。

イベント: 'test:watch:drained'

ウォッチモードで実行待ちのテストがなくなったときに送出されます。

クラス: TestContext

[履歴]

バージョン変更点
v20.1.0, v18.17.0before関数がTestContextに追加されました。
v18.0.0, v16.17.0追加: v18.0.0, v16.17.0

TestContextのインスタンスは、テストランナーとやり取りするために各テスト関数に渡されます。ただし、TestContextコンストラクタは API の一部として公開されていません。

context.before([fn][, options])

追加: v20.1.0, v18.17.0

  • fn <Function> | <AsyncFunction> フック関数。この関数の最初の引数はTestContextオブジェクトです。フックがコールバックを使用する場合、コールバック関数は 2 番目の引数として渡されます。デフォルト: 何もしない関数。
  • options <Object> フックの構成オプション。以下のプロパティがサポートされています:
    • signal <AbortSignal> 進行中のフックの中断を許可します。
    • timeout <number> フックが失敗するまでのミリ秒数。指定しない場合、サブテストは親からこの値を継承します。デフォルト: Infinity

この関数は、現在のテストのサブテストの前に実行されるフックを作成するために使用されます。

context.beforeEach([fn][, options])

追加: v18.8.0, v16.18.0

  • fn <Function> | <AsyncFunction> フック関数。この関数の最初の引数はTestContextオブジェクトです。フックがコールバックを使用する場合、コールバック関数は 2 番目の引数として渡されます。デフォルト: 何もしない関数。
  • options <Object> フックの構成オプション。以下のプロパティがサポートされています:
    • signal <AbortSignal> 進行中のフックの中断を許可します。
    • timeout <number> フックが失敗するまでのミリ秒数。指定しない場合、サブテストは親からこの値を継承します。デフォルト: Infinity

この関数は、現在のテストの各サブテストの前に実行されるフックを作成するために使用されます。

js
test('トップレベルテスト', async t => {
  t.beforeEach(t => t.diagnostic(`about to run ${t.name}`))
  await t.test('これはサブテストです', t => {
    assert.ok('some relevant assertion here')
  })
})

context.after([fn][, options])

追加: v19.3.0, v18.13.0

  • fn <Function> | <AsyncFunction> フック関数。この関数の最初の引数はTestContextオブジェクトです。フックがコールバックを使用する場合、コールバック関数が 2 番目の引数として渡されます。デフォルト: 何もしない関数。
  • options <Object> フックの構成オプション。以下のプロパティがサポートされています。
    • signal <AbortSignal> 実行中のフックの中断を許可します。
    • timeout <number> フックが失敗するまでのミリ秒数。指定しない場合、サブテストは親からこの値を継承します。デフォルト: Infinity

この関数は、現在のテストが終了した後に実行されるフックを作成するために使用されます。

js
test('top level test', async t => {
  t.after(t => t.diagnostic(`finished running ${t.name}`))
  assert.ok('some relevant assertion here')
})

context.afterEach([fn][, options])

追加: v18.8.0, v16.18.0

  • fn <Function> | <AsyncFunction> フック関数。この関数の最初の引数はTestContextオブジェクトです。フックがコールバックを使用する場合、コールバック関数が 2 番目の引数として渡されます。デフォルト: 何もしない関数。
  • options <Object> フックの構成オプション。以下のプロパティがサポートされています。
    • signal <AbortSignal> 実行中のフックの中断を許可します。
    • timeout <number> フックが失敗するまでのミリ秒数。指定しない場合、サブテストは親からこの値を継承します。デフォルト: Infinity

この関数は、現在のテストの各サブテストの後で実行されるフックを作成するために使用されます。

js
test('top level test', async t => {
  t.afterEach(t => t.diagnostic(`finished running ${t.name}`))
  await t.test('This is a subtest', t => {
    assert.ok('some relevant assertion here')
  })
})

context.assert

追加日: v22.2.0, v20.15.0

contextにバインドされたアサーションメソッドを含むオブジェクト。node:assertモジュールのトップレベル関数は、テストプランを作成するためにここで公開されています。

js
test('test', t => {
  t.plan(1)
  t.assert.strictEqual(true, true)
})

context.assert.snapshot(value[, options])

追加日: v22.3.0

[安定版: 1 - 実験的]

安定版: 1 安定性: 1.0 - 開発初期段階

  • value <any> 文字列にシリアル化する値。Node.js が--test-update-snapshotsフラグで起動された場合、シリアル化された値はスナップショットファイルに書き込まれます。それ以外の場合は、シリアル化された値は既存のスナップショットファイル内の対応する値と比較されます。
  • options <Object> オプションの構成オプション。次のプロパティがサポートされています。
    • serializers <Array> valueを文字列にシリアル化するのに使用される同期関数の配列。valueは最初のシリアライザ関数への唯一の引数として渡されます。各シリアライザの戻り値は、次のシリアライザへの入力として渡されます。すべてのシリアライザが実行されると、結果の値は文字列に変換されます。デフォルト: シリアライザが提供されない場合、テストランナーのデフォルトのシリアライザが使用されます。

この関数は、スナップショットテストのアサーションを実装します。

js
test('snapshot test with default serialization', t => {
  t.assert.snapshot({ value1: 1, value2: 2 })
})

test('snapshot test with custom serialization', t => {
  t.assert.snapshot(
    { value3: 3, value4: 4 },
    {
      serializers: [value => JSON.stringify(value)],
    }
  )
})

context.diagnostic(message)

追加されたバージョン: v18.0.0, v16.17.0

  • message <string> 報告するメッセージ。

この関数は、診断情報を出力に書き込むために使用されます。診断情報は、テスト結果の最後に含まれます。この関数は値を返しません。

js
test('トップレベルテスト', t => {
  t.diagnostic('診断メッセージ')
})

context.filePath

追加されたバージョン: v22.6.0, v20.16.0

現在のテストを作成したテストファイルの絶対パス。テストファイルがテストを生成する追加のモジュールをインポートする場合、インポートされたテストはルートテストファイルのパスを返します。

context.fullName

追加されたバージョン: v22.3.0

テストとその祖先の名前を>で区切ったもの。

context.name

追加されたバージョン: v18.8.0, v16.18.0

テストの名前。

context.plan(count)

[履歴]

バージョン変更
v23.4.0この関数は実験的ではなくなりました。
v22.2.0, v20.15.0追加されたバージョン: v22.2.0, v20.15.0
  • count <number> 実行されるアサーションとサブテストの予想数。

この関数は、テスト内で実行されるアサーションとサブテストの数を設定するために使用されます。実行されるアサーションとサブテストの数が予想数と一致しない場合、テストは失敗します。

js
test('トップレベルテスト', t => {
  t.plan(2)
  t.assert.ok('some relevant assertion here')
  t.test('サブテスト', () => {})
})

非同期コードを使用する場合、plan関数は、正しい数の assertion が実行されることを保証するために使用できます。

js
test('ストリームを使った計画', (t, done) => {
  function* generate() {
    yield 'a'
    yield 'b'
    yield 'c'
  }
  const expected = ['a', 'b', 'c']
  t.plan(expected.length)
  const stream = Readable.from(generate())
  stream.on('data', chunk => {
    t.assert.strictEqual(chunk, expected.shift())
  })

  stream.on('end', () => {
    done()
  })
})

context.runOnly(shouldRunOnlyTests)

追加: v18.0.0, v16.17.0

  • shouldRunOnlyTests <boolean> only オプション付きのテストを実行するかどうか。

shouldRunOnlyTests が真の場合、テストコンテキストは only オプションが設定されているテストのみを実行します。それ以外の場合は、すべてのテストが実行されます。Node.js が --test-only コマンドラインオプションで起動されていない場合、この関数は何もしません。

js
test('トップレベルテスト', t => {
  // テストコンテキストは、'only' オプションを使用してサブテストを実行するように設定できます。
  t.runOnly(true)
  return Promise.all([
    t.test('このサブテストはスキップされます'),
    t.test('このサブテストは実行されます', { only: true }),
  ])
})

context.signal

追加: v18.7.0, v16.17.0

テストが中断されたときに、テストのサブタスクの中断に使用できます。

js
test('トップレベルテスト', async t => {
  await fetch('some/uri', { signal: t.signal })
})

context.skip([message])

追加: v18.0.0, v16.17.0

  • message <string> オプションのスキップメッセージ。

この関数は、テストの出力をスキップされたテストとして示します。message が指定されている場合、出力に含まれます。skip() を呼び出しても、テスト関数の実行は終了しません。この関数は値を返しません。

js
test('トップレベルテスト', t => {
  // テストに追加のロジックが含まれている場合も、ここで返すようにしてください。
  t.skip('これはスキップされます')
})

context.todo([message])

追加: v18.0.0, v16.17.0

  • message <string> オプションの TODO メッセージ。

この関数は、テストの出力に TODO ディレクティブを追加します。message が指定されている場合、出力に含まれます。todo() を呼び出しても、テスト関数の実行は終了しません。この関数は値を返しません。

js
test('トップレベルテスト', t => {
  // このテストは `TODO` としてマークされています
  t.todo('これはTODOです')
})

context.test([name][, options][, fn])

[履歴]

バージョン変更内容
v18.8.0, v16.18.0signal オプションを追加
v18.7.0, v16.17.0timeout オプションを追加
v18.0.0, v16.17.0追加: v18.0.0, v16.17.0
  • name <string> サブテストの名前。テスト結果のレポートに表示されます。デフォルト: fnnameプロパティ、またはfnに名前がない場合は'<anonymous>'

  • options <Object> サブテストの構成オプション。以下のプロパティがサポートされています。

    • concurrency <number> | <boolean> | <null> 数値を指定すると、その数のテストがアプリケーションスレッド内で並列に実行されます。trueの場合、すべてのサブテストが並列に実行されます。falseの場合、一度に 1 つのテストしか実行されません。指定しない場合、サブテストは親からこの値を継承します。デフォルト: null
    • only <boolean> 真理値の場合、テストコンテキストがonlyテストを実行するように構成されていると、このテストが実行されます。それ以外の場合は、テストはスキップされます。デフォルト: false
    • signal <AbortSignal> 実行中のテストの中断を許可します。
    • skip <boolean> | <string> 真理値の場合、テストはスキップされます。文字列を指定すると、その文字列がテスト結果にテストスキップの理由として表示されます。デフォルト: false
    • todo <boolean> | <string> 真理値の場合、テストはTODOとしてマークされます。文字列を指定すると、その文字列がテスト結果にテストがTODOである理由として表示されます。デフォルト: false
    • timeout <number> テストが失敗するまでのミリ秒数。指定しない場合、サブテストは親からこの値を継承します。デフォルト: Infinity
    • plan <number> テストで実行されるアサーションとサブテストの予想数。テストで実行されるアサーション数がプランで指定された数と一致しない場合、テストは失敗します。デフォルト: undefined
  • fn <Function> | <AsyncFunction> テスト対象の関数。この関数の最初の引数はTestContextオブジェクトです。テストがコールバックを使用する場合、コールバック関数は 2 番目の引数として渡されます。デフォルト: 何もしない関数。

  • 戻り値: <Promise> テストが完了するとundefinedで解決されます。

この関数は、現在のテストの下にサブテストを作成するために使用されます。この関数は、最上位レベルのtest()関数と同じように動作します。

js
test('トップレベルテスト', async t => {
  await t.test('これはサブテストです', { only: false, skip: false, concurrency: 1, todo: false, plan: 1 }, t => {
    t.assert.ok('ここに関連するアサーションがあります')
  })
})

クラス: SuiteContext

追加: v18.7.0, v16.17.0

SuiteContextのインスタンスは、テストランナーとやり取りするために各スイート関数に渡されます。ただし、SuiteContextコンストラクタは API の一部として公開されていません。

context.filePath

追加: v22.6.0

現在のスイートを作成したテストファイルの絶対パス。テストファイルがスイートを生成する追加のモジュールをインポートする場合、インポートされたスイートはルートテストファイルのパスを返します。

context.name

追加: v18.8.0, v16.18.0

スイートの名前。

context.signal

追加: v18.7.0, v16.17.0

テストが中断されたときに、テストのサブタスクの中断に使用できます。