テストランナー#

安定度: 2 - 安定

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

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

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

このモジュールは、node: スキームでのみ使用できます。以下は動作しません

import test from 'test';const test = require('test');

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

  1. 例外をスローした場合に失敗とみなされ、そうでない場合は成功とみなされる同期関数。
  2. Promise を返す関数。Promise が拒否された場合に失敗とみなされ、Promise が履行された場合に成功とみなされます。
  3. コールバック関数を受け取る関数。コールバックが最初の引数として truthy 値を受け取った場合、テストは失敗とみなされます。コールバックの最初の引数として falsy 値が渡された場合、テストは成功とみなされます。テスト関数がコールバック関数を受け取り、かつ Promise を返す場合、テストは失敗します。

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

test('synchronous passing test', (t) => {
  // This test passes because it does not throw an exception.
  assert.strictEqual(1, 1);
});

test('synchronous failing test', (t) => {
  // This test fails because it throws an exception.
  assert.strictEqual(1, 2);
});

test('asynchronous passing test', async (t) => {
  // This test passes because the Promise returned by the async
  // function is settled and not rejected.
  assert.strictEqual(1, 1);
});

test('asynchronous failing test', async (t) => {
  // This test fails because the Promise returned by the async
  // function is rejected.
  assert.strictEqual(1, 2);
});

test('failing test using Promises', (t) => {
  // Promises can be used directly as well.
  return new Promise((resolve, reject) => {
    setImmediate(() => {
      reject(new Error('this will cause the test to fail'));
    });
  });
});

test('callback passing test', (t, done) => {
  // done() is the callback function. When the setImmediate() runs, it invokes
  // done() with no arguments.
  setImmediate(done);
});

test('callback failing test', (t, done) => {
  // When the setImmediate() runs, done() is invoked with an Error object and
  // the test fails.
  setImmediate(() => {
    done(new Error('callback failure'));
  });
}); 

テストが失敗した場合、プロセス終了コードは 1 に設定されます。

サブテスト#

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

test('top level test', async (t) => {
  await t.test('subtest 1', (t) => {
    assert.strictEqual(1, 1);
  });

  await t.test('subtest 2', (t) => {
    assert.strictEqual(2, 2);
  });
}); 

注: beforeEach および afterEach フックは、各サブテストの実行の間にトリガーされます。

この例では、await を使用して両方のサブテストが完了したことを確認しています。これは、`describe` と `it` 構文で作成されたテストとは異なり、親テストはサブテストの完了を待機しないためです。親が終了したときに未処理のサブテストはキャンセルされ、失敗として扱われます。サブテストが失敗すると、親テストも失敗します。

テストのスキップ#

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

// The skip option is used, but no message is provided.
test('skip option', { skip: true }, (t) => {
  // This code is never executed.
});

// The skip option is used, and a message is provided.
test('skip option with message', { skip: 'this is skipped' }, (t) => {
  // This code is never executed.
});

test('skip() method', (t) => {
  // Make sure to return here as well if the test contains additional logic.
  t.skip();
});

test('skip() method with message', (t) => {
  // Make sure to return here as well if the test contains additional logic.
  t.skip('this is skipped');
}); 

describe/it 構文#

テストの実行は、スイートを宣言する describe とテストを宣言する it を使用しても実行できます。スイートは、関連するテストをまとめて整理およびグループ化するために使用されます。 ittest() の省略形です。

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);
    });
  });
}); 

describeit は、node:test モジュールからインポートされます。

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

only テスト#

Node.js が --test-only コマンドラインオプションで起動された場合、実行する必要があるテストに only オプションを渡すことで、選択したサブセットを除くすべてのトップレベルテストをスキップできます。 only オプションが設定されたテストが実行されると、すべてのサブテストも実行されます。テストコンテキストの runOnly() メソッドを使用して、サブテストレベルで同じ動作を実装できます。

// Assume Node.js is run with the --test-only command-line option.
// The 'only' option is set, so this test is run.
test('this test is run', { only: true }, async (t) => {
  // Within this test, all subtests are run by default.
  await t.test('running subtest');

  // The test context can be updated to run subtests with the 'only' option.
  t.runOnly(true);
  await t.test('this subtest is now skipped');
  await t.test('this subtest is run', { only: true });

  // Switch the context back to execute all tests.
  t.runOnly(false);
  await t.test('this subtest is now run');

  // Explicitly do not run these tests.
  await t.test('skipped subtest 3', { only: false });
  await t.test('skipped subtest 4', { skip: true });
});

// The 'only' option is not set, so this test is skipped.
test('this test is not run', () => {
  // This code is not run.
  throw new Error('fail');
}); 

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

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

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

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" で Node.js を起動すると、パターンは大文字と小文字を区別しないため、Test 4Test 5 が一致します。

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

外部非同期アクティビティ#

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

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

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

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.
}); 

ウォッチモード#

安定度: 1 - 実験的

Node.js テストランナーは、--watch フラグを渡すことによって、ウォッチモードでの実行をサポートしています。

node --test --watch 

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

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

Node.js テストランナーは、--test フラグを渡すことでコマンドラインから起動できます。

node --test 

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

  • **/*.test.?(c|m)js
  • **/*-test.?(c|m)js
  • **/*_test.?(c|m)js
  • **/test-*.?(c|m)js
  • **/test.?(c|m)js
  • **/test/**/*.?(c|m)js

または、以下に示すように、Node.js コマンドの最後の引数として、1 つ以上の glob パターンを指定できます。glob パターンは、glob(7) の動作に従います。

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

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

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

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

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

コードカバレッジの収集#

安定度: 1 - 実験的

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

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

/* node:coverage disable */
if (anAlwaysFalseCondition) {
  // Code in this branch will never be executed, but the lines are ignored for
  // coverage purposes. All lines following the 'disable' comment are ignored
  // until a corresponding 'enable' comment is encountered.
  console.log('this is never executed');
}
/* node:coverage enable */ 

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

/* node:coverage ignore next */
if (anAlwaysFalseCondition) { console.log('this is never executed'); }

/* node:coverage ignore next 3 */
if (anAlwaysFalseCondition) {
  console.log('this is never executed');
} 

カバレッジレポーター#

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

node --test --experimental-test-coverage --test-reporter=lcov --test-reporter-destination=lcov.info 

制限事項#

テストランナーのコードカバレッジ機能には、次の制限事項があります。これらは、将来の Node.js リリースで対処されます。

  • ソースマップはサポートされていません。
  • カバレッジレポートから特定のファイルまたはディレクトリを除外することはサポートされていません。

モッキング#

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

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.calls.length, 0);
  assert.strictEqual(sum(3, 4), 7);
  assert.strictEqual(sum.mock.calls.length, 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();
});'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.calls.length, 0);
  assert.strictEqual(sum(3, 4), 7);
  assert.strictEqual(sum.mock.calls.length, 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 を使用して、オブジェクトメソッドにスパイを作成します。テストコンテキストを介してモッキングする利点は、テストランナーがテストの終了後にすべてのモックされた機能を自動的に復元することです。

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.calls.length, 0);
  assert.strictEqual(number.add(3), 8);
  assert.strictEqual(number.add.mock.calls.length, 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);
}); 

タイマー#

タイマーのモッキングは、ソフトウェアテストで一般的に使用される手法であり、 `setInterval` や `setTimeout` などのタイマーの動作を、指定された時間間隔を実際に待たずにシミュレートおよび制御するために使用されます。

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

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

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

**注意:** `import { setTimeout } from 'node:timers'` などの関数の分割代入は、現在この API ではサポートされていません。

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();
}); 
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'll also reset timers instance
  mock.reset();
}); 

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

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);
}); 
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 クラスの一部です。メソッドと機能の完全なリストについては、こちらを参照してください。

**注意:** 日付とタイマーは、一緒にモックされると依存関係があります。これは、`Date` と `setTimeout` の両方がモックされている場合、時間が進むとモックされた日付も進むことを意味します。これは、単一の内部クロックをシミュレートするためです。

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

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);
});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 オブジェクトを指定できます。

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);
});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()` メソッドを使用して、モックされた日付を別の時間に手動で移動できます。このメソッドは、正の整数のみを受け入れます。

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

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

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);
});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()` メソッドが呼び出されたかのように実行されます。これは、既に過去の時間依存の機能をテストする場合に役立ちます。

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);
});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()` を使用すると、現在キューにあるすべてのタイマーが実行されます。これにより、時間が経過したかのように、モックされた日付も最後に実行されたタイマーの時間まで進みます。

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);
});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);
});

テストレポーター#

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

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

  • tap tap レポーターは、テスト結果を TAP 形式で出力します。

  • spec spec レポーターは、テスト結果を読者の理解しやすい形式で出力します。

  • dot dot レポーターは、テスト結果をコンパクトな形式で出力します。合格した各テストは `.` で表され、失敗した各テストは `X` で表されます。

  • junit junit レポーターは、テスト結果を jUnit XML 形式で出力します。

  • lcov lcov レポーターは、--experimental-test-coverage フラグと共に使用された場合、テストカバレッジを出力します。

stdoutTTY の場合、デフォルトで spec レポーターが使用されます。それ以外の場合は、デフォルトで `tap` レポーターが使用されます。

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

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

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

カスタムレポーター#

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

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

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;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;

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

export default async function * customReporter(source) {
  for await (const event of source) {
    switch (event.type) {
      case 'test:dequeue':
        yield `test ${event.data.name} dequeued`;
        break;
      case 'test:enqueue':
        yield `test ${event.data.name} enqueued`;
        break;
      case 'test:watch:drained':
        yield 'test watch queue drained';
        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';
        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;
      }
    }
  }
}module.exports = async function * customReporter(source) {
  for await (const event of source) {
    switch (event.type) {
      case 'test:dequeue':
        yield `test ${event.data.name} dequeued`;
        break;
      case 'test:enqueue':
        yield `test ${event.data.name} enqueued`;
        break;
      case 'test:watch:drained':
        yield 'test watch queue drained';
        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 を使用して各レポーターの出力先を指定する必要があります。出力先は、`stdout`、`stderr`、またはファイルパスにすることができます。レポーターと出力先は、指定された順序でペアになります。

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

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

レポーターが1つだけ指定されている場合、出力先は明示的に指定されない限り、デフォルトでstdoutになります。

run([options])#

  • options <Object> テスト実行のための設定オプション。以下のプロパティがサポートされています。
    • concurrency <number> | <boolean> 数値が指定された場合、その数だけテストプロセスが並列に実行されます。各プロセスは1つのテストファイルに対応します。 trueの場合、os.availableParallelism() - 1個のテストファイルを並列実行します。 falseの場合、一度に1つのテストファイルのみを実行します。 デフォルト: false
    • files: <Array> 実行するファイルのリストを含む配列。 デフォルトテストランナー実行モデルから一致するファイル。
    • inspectPort <number> | <Function> テスト子プロセスのインスペクターポートを設定します。これは数値、または引数を取らずに数値を返す関数です。 nullish 値が指定された場合、各プロセスはプライマリの process.debugPort からインクリメントされた独自のポートを取得します。 デフォルト: undefined
    • only: <boolean> 真の場合、テストコンテキストはonlyオプションが設定されているテストのみを実行します。
    • setup <Function> TestsStreamインスタンスを受け取る関数で、テストが実行される前にリスナーを設定するために使用できます。 デフォルト: undefined
    • signal <AbortSignal> 実行中のテストを中止できます。
    • testNamePatterns <string> | <RegExp> | <Array> 指定されたパターンと一致する名前のテストのみを実行するために使用できる文字列、正規表現、または正規表現の配列。テスト名パターンはJavaScriptの正規表現として解釈されます。実行される各テストについて、beforeEach()などの対応するテストフックも実行されます。 デフォルト: undefined
    • timeout <number> テスト実行が失敗するまでのミリ秒数。指定しない場合、サブテストはこの値を親から継承します。 デフォルト: Infinity
    • watch <boolean> ウォッチモードで実行するかどうか。 デフォルト: false
    • shard <Object> 特定のシャードでテストを実行します。 デフォルト: undefined
      • index <number> は、実行するシャードのインデックスを指定する1から<total>までの正の整数です。このオプションは*必須*です。
      • total <number> は、テストファイルを分割するシャードの総数を指定する正の整数です。このオプションは*必須*です。
  • 戻り値: <TestsStream>

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

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);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);

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

  • 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
  • fn <Function> | <AsyncFunction> テスト対象の関数。この関数の最初の引数はTestContextオブジェクトです。テストがコールバックを使用する場合、コールバック関数は2番目の引数として渡されます。 デフォルト: 何もしない関数。
  • 戻り値: <Promise> テストの完了後にundefinedで履行されます。テストがdescribe()内で実行される場合はすぐに履行されます。

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

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

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

test('top level test', async (t) => {
  // The setTimeout() in the following subtest would cause it to outlive its
  // parent test if 'await' is removed on the next line. Once the parent test
  // completes, it will cancel any outstanding subtests.
  await t.test('longer running subtest', 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])#

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

describe()関数は、node:testモジュールからインポートされます。この関数を呼び出すたびに、サブテストが作成されます。トップレベルのdescribe関数を呼び出した後、すべてのトップレベルのテストとスイートが実行されます。

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

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

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

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

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

before([fn][, options])#

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

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

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

after([fn][, options])#

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

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

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

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

beforeEach([fn][, options])#

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

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

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

afterEach([fn][, options])#

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

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

注意: afterEach フックは、テストが失敗した場合でも、すべてのテストの後に必ず実行されます。

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

クラス: MockFunctionContext#

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

ctx.calls#

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

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

ctx.callCount()#

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

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

ctx.mockImplementation(implementation)#

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

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

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

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

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

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

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

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

ctx.restore()#

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

クラス: MockTracker#

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

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

  • original <Function> | <AsyncFunction> モックを作成するオプションの関数。 デフォルト: 何もしない関数。
  • implementation <Function> | <AsyncFunction> original のモック実装として使用されるオプションの関数。これは、指定された回数の呼び出しに対して1つの動作を示し、次に original の動作を復元するモックを作成するのに役立ちます。 デフォルト: original で指定された関数。
  • options <Object> モック関数のオプションの設定オプション。以下のプロパティがサポートされています。
    • times <integer> モックが implementation の動作を使用する回数。モック関数が times 回呼び出されると、自動的に original の動作が復元されます。この値は、ゼロより大きい整数である必要があります。 デフォルト: Infinity
  • 戻り値: <Proxy> モック関数。モック関数には、MockFunctionContext のインスタンスである特別な mock プロパティが含まれており、モック関数の動作を検査および変更するために使用できます。

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

次の例では、呼び出しごとにカウンターを1ずつ増やすモック関数を作成します。 times オプションは、最初の2回の呼び出しでカウンターに1ではなく2を追加するようにモックの動作を変更するために使用されます。

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

この関数は、options.gettertrue に設定された MockTracker.method の糖衣構文です。

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

  • 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 回呼び出されると、自動的に元の動作に戻ります。この値はゼロより大きい整数でなければなりません。 **デフォルト:** Infinity(無限)。
  • 戻り値: <Proxy> モックされたメソッド。モックされたメソッドには、MockFunctionContext のインスタンスである特別な mock プロパティが含まれており、モックされたメソッドの動作を検査および変更するために使用できます。

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

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.calls.length, 0);
  assert.strictEqual(number.subtract(3), 2);
  assert.strictEqual(number.subtract.mock.calls.length, 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.reset()#

この関数は、この MockTracker によって以前に作成されたすべてのモックのデフォルトの動作を復元し、モックを MockTracker インスタンスから切り離します。切り離された後もモックは使用できますが、MockTracker インスタンスを使用して動作をリセットしたり、他の方法で操作することはできなくなります。

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

mock.restoreAll()#

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

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

この関数は、options.settertrue に設定された MockTracker.method の糖衣構文です。

クラス: MockTimers#

安定度: 1 - 実験的

タイマーのモッキングは、ソフトウェアテストで一般的に使用される手法であり、 `setInterval` や `setTimeout` などのタイマーの動作を、指定された時間間隔を実際に待たずにシミュレートおよび制御するために使用されます。

MockTimers は Date オブジェクトもモックできます。

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

timers.enable([enableOptions])#

指定されたタイマーのタイマーモッキングを有効にします。

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

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

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

初期時刻を設定しない使用例

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

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

初期時刻を設定した使用例

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

初期時刻として Date オブジェクトを設定した使用例

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

または、パラメータなしで mock.timers.enable() を呼び出すと

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

timers.reset()#

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

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

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

timers[Symbol.dispose]()#

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

timers.tick(milliseconds)#

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

  • milliseconds <number> タイマーを進める時間(ミリ秒単位)。

**注:** これは、Node.js の setTimeout の動作とは異なり、正の数値のみを受け入れます。 Node.js では、負の数値を使用した `setTimeout` は、Web 互換性の理由からのみサポートされています。

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

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);

  // Advance in time
  context.mock.timers.tick(9999);

  assert.strictEqual(fn.mock.callCount(), 1);
});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);

  // Advance in time
  context.mock.timers.tick(9999);

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

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

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 twoSeconds = 3000;
  context.mock.timers.tick(twoSeconds);
  context.mock.timers.tick(twoSeconds);
  context.mock.timers.tick(twoSeconds);

  assert.strictEqual(fn.mock.callCount(), 1);
});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 twoSeconds = 3000;
  context.mock.timers.tick(twoSeconds);
  context.mock.timers.tick(twoSeconds);
  context.mock.timers.tick(twoSeconds);

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

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

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);

  // Advance in time
  context.mock.timers.tick(9999);
  assert.strictEqual(fn.mock.callCount(), 1);
  assert.strictEqual(Date.now(), 9999);
});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);

  // Advance in time
  context.mock.timers.tick(9999);
  assert.strictEqual(fn.mock.callCount(), 1);
  assert.strictEqual(Date.now(), 9999);
});
クリア関数の使用#

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

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);

  // Implicity mocked as well
  clearTimeout(id);
  context.mock.timers.tick(9999);

  // As that setTimeout was cleared the mock function will never be called
  assert.strictEqual(fn.mock.callCount(), 0);
});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);

  // Implicity mocked as well
  clearTimeout(id);
  context.mock.timers.tick(9999);

  // As that setTimeout was cleared the mock function will never be called
  assert.strictEqual(fn.mock.callCount(), 0);
});
Node.js タイマーモジュールでの作業#

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

**注意:** `import { setTimeout } from 'node:timers'` などの関数の分割代入は、現在この API ではサポートされていません。

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);

  // Advance in time
  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);
});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);

  // Advance in time
  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 でもサポートされています。

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));
  }
});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()#

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

以下の例では、保留中のすべてのタイマーをすぐにトリガーし、遅延なしに実行させます。

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);
});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)#

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

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);
});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 オブジェクトに渡すと、setTimeout および setInterval で設定されたタイマーは**影響を受けません**。

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

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);

  assert.deepStrictEqual(results, []);
  context.mock.timers.setTime(12000);
  assert.deepStrictEqual(results, []);
  // The date is advanced but the timers don't tick
  assert.strictEqual(Date.now(), 12000);
});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);

  assert.deepStrictEqual(results, []);
  context.mock.timers.setTime(12000);
  assert.deepStrictEqual(results, []);
  // The date is advanced but the timers don't tick
  assert.strictEqual(Date.now(), 12000);
});

クラス: TestsStream#

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> 行がカバレッジされた回数。
      • 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:dequeue'#

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

テストがキューから削除され、実行される直前に発行されます。

イベント: '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 が呼び出されたときに発行されます。

イベント: 'test:enqueue'#

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

テストが実行のためにキューに入れられたときに発行されます。

イベント: `'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:pass'#

テストが成功したときに発行されます。

イベント: '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:stderr'#

  • data <Object>
    • column <number> | <undefined> テストが定義されている列番号。REPLでテストが実行された場合は`undefined`。
    • file <string> テストファイルのパス。
    • line <number> | <undefined> テストが定義されている行番号。REPLでテストが実行された場合は`undefined`。
    • message <string> `stderr` に書き込まれたメッセージ。

実行中のテストが `stderr` に書き込んだときに発行されます。このイベントは、`--test` フラグが渡された場合にのみ発行されます。

イベント: 'test:stdout'#

  • data <Object>
    • column <number> | <undefined> テストが定義されている列番号。REPLでテストが実行された場合は`undefined`。
    • file <string> テストファイルのパス。
    • line <number> | <undefined> テストが定義されている行番号。REPLでテストが実行された場合は`undefined`。
    • message <string> `stdout` に書き込まれたメッセージ。

実行中のテストが `stdout` に書き込んだときに発行されます。このイベントは、`--test` フラグが渡された場合にのみ発行されます。

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

ウォッチモードで実行のためにキューに入れられたテストがなくなったときに発行されます。

クラス: TestContext#

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

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

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

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

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

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

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

test('top level test', async (t) => {
  t.beforeEach((t) => t.diagnostic(`about to run ${t.name}`));
  await t.test(
    'This is a subtest',
    (t) => {
      assert.ok('some relevant assertion here');
    },
  );
}); 

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

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

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

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

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

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

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.diagnostic(message)#

  • message <string> レポートされるメッセージ。

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

test('top level test', (t) => {
  t.diagnostic('A diagnostic message');
}); 

`context.name` #

テストの名前。

`context.runOnly(shouldRunOnlyTests)` #

  • `shouldRunOnlyTests` <boolean> `only` オプションが設定されたテストのみを実行するかどうか。

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

test('top level test', (t) => {
  // The test context can be set to run subtests with the 'only' option.
  t.runOnly(true);
  return Promise.all([
    t.test('this subtest is now skipped'),
    t.test('this subtest is run', { only: true }),
  ]);
}); 

`context.signal` #

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

test('top level test', async (t) => {
  await fetch('some/uri', { signal: t.signal });
}); 

`context.skip([message])` #

  • `message` <string> 省略可能なスキップメッセージ。

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

test('top level test', (t) => {
  // Make sure to return here as well if the test contains additional logic.
  t.skip('this is skipped');
}); 

`context.todo([message])` #

  • `message` <string> 省略可能な `TODO` メッセージ。

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

test('top level test', (t) => {
  // This test is marked as `TODO`
  t.todo('this is a todo');
}); 

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

  • `name` <string> サブテストの名前。テスト結果の報告時に表示されます。 **デフォルト:** `fn` の `name` プロパティ、または `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
  • fn <Function> | <AsyncFunction> テスト対象の関数。この関数の最初の引数はTestContextオブジェクトです。テストがコールバックを使用する場合、コールバック関数は2番目の引数として渡されます。 デフォルト: 何もしない関数。
  • 戻り値: <Promise> テストが完了すると `undefined` で履行されます。

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

test('top level test', async (t) => {
  await t.test(
    'This is a subtest',
    { only: false, skip: false, concurrency: 1, todo: false },
    (t) => {
      assert.ok('some relevant assertion here');
    },
  );
}); 

クラス: `SuiteContext` #

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

`context.name` #

スイートの名前。

`context.signal` #

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