Spec-Zone.ru › Node.js

Запуск тестов

История
Версия Изменения
v20.0.0

Запуск тестов теперь стабилен.

v18.0.0, v16.17.0

Добавлен в: v18.0.0, v16.17.0

Уровень стабильности: 2 - Стабильно

Исходный код: lib/test.js

Модуль node:test облегчает создание тестов JavaScript. Для доступа к нему:

Модули MJS

import test from 'node:test';

Модули CJS

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

Этот модуль доступен только по схеме node:. Следующее не сработает:

Модули MJS

import test from 'test';

Модули CJS

const test = require('test');

Тесты, созданные с помощью модуля test, состоят из одной функции, которая обрабатывается одним из трех способов:

  1. Синхронная функция, которая считается неудачной, если выбрасывает исключение, и успешной в противном случае.
  2. Функция, которая возвращает Promise, которая считается неудачной, если Promise отклоняется, и успешной, если Promise выполняется.
  3. Функция, которая получает функцию обратного вызова. Если функция обратного вызова получает любое истинное значение в качестве своего первого аргумента, тест считается неудачным. Если в качестве первого аргумента функции обратного вызова передается ложное значение, тест считается успешным. Если функция теста получает функцию обратного вызова и также возвращает 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'));
  });
}); copy

Если какие-либо тесты завершаются неудачей, код завершения процесса устанавливается в 1.

Подтесты

Метод test() контекста теста позволяет создавать подтесты. Это позволяет структурировать тесты иерархическим образом, создавая вложенные тесты внутри более крупного теста. Этот метод ведет себя идентично функции test() верхнего уровня. Следующий пример демонстрирует создание теста верхнего уровня с двумя подтестами.

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

Примечание: хуки beforeEach и afterEach срабатывают между каждым выполнением подтеста.

В этом примере используется await, чтобы гарантировать завершение обоих подтестов. Это необходимо, потому что тесты не ожидают завершения своих подтестов, в отличие от тестов, созданных в рамках наборов. Любые подтесты, которые все еще активны, когда заканчивается их родительский тест, отменяются и считаются неудачными. Любая неудача подтеста приводит к неудаче родительского теста.

Пропуск тестов

Отдельные тесты могут быть пропущены, передав опцию 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');
}); copy

Тесты TODO

Отдельные тесты могут быть помечены как нестабильные или неполные, передав опцию todo тесту или вызвав метод todo() контекста теста, как показано в следующем примере. Эти тесты представляют ожидаемую реализацию или ошибку, которую нужно исправить. Тесты TODO выполняются, но не обрабатываются как неудачные, и, следовательно, не влияют на код выхода процесса. Если тест помечен как TODO и пропущен, опция TODO игнорируется.

// The todo option is used, but no message is provided.
test('todo option', { todo: true }, (t) => {
  // This code is executed, but not treated as a failure.
  throw new Error('this does not fail the test');
});

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

test('todo() method', (t) => {
  t.todo();
});

test('todo() method with message', (t) => {
  t.todo('this is a todo test and is not treated as a failure');
  throw new Error('this does not fail the test');
}); copy

describe() и it() псевдонимы

Наборы и тесты также можно писать, используя функции describe() и it(). describe() является псевдонимом для suite(), а it() — псевдонимом для test().

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

describe() и it() импортируются из модуля node:test.

Модули MJS

import { describe, it } from 'node:test';

Модули CJS

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

only тесты

Если Node.js запускается с параметром командной строки --test-only, можно пропустить все тесты, кроме выбранного подмножества, передав опцию only тестам, которые должны выполняться. Когда для теста установлена опция only, выполняются также все подтесты. Если для набора установлен параметр only, выполняются все тесты в рамках набора, если только он не имеет потомков с параметром only установленным, в этом случае выполняются только эти тесты.

При использовании подтестов в рамках test()/it(), необходимо пометить все родительские тесты параметром only для запуска только выбранного подмножества тестов.

Метод runOnly() контекста теста можно использовать для реализации аналогичного поведения на уровне подтеста. Тесты, которые не выполняются, исключаются из вывода запуска тестов.

// Assume Node.js is run with the --test-only command-line option.
// The suite's 'only' option is set, so these tests are 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');
});

describe('a suite', () => {
  // The 'only' option is set, so this test is run.
  it('this test is run', { only: true }, () => {
    // This code is run.
  });

  it('this test is not run', () => {
    // This code is not run.
    throw new Error('fail');
  });
});

describe.only('a suite', () => {
  // The 'only' option is set, so this test is run.
  it('this test is run', () => {
    // This code is run.
  });

  it('this test is run', () => {
    // This code is run.
  });
}); copy

Фильтрация тестов по имени

Параметр командной строки --test-name-pattern может быть использован для запуска только тех тестов, имена которых соответствуют заданному шаблону, а параметр --test-skip-pattern — для пропуска тестов, имена которых соответствуют заданному шаблону. Шаблоны имён тестов интерпретируются как JavaScript регулярные выражения. Параметры --test-name-pattern и --test-skip-pattern можно указывать несколько раз для запуска вложенных тестов. Для каждого исполняемого теста также выполняются соответствующие хуки тестов, такие как beforeEach(). Тесты, которые не выполняются, исключаются из вывода запуска тестов.

Учитывая следующий файл с тестами, запуск Node.js с параметром --test-name-pattern="test [1-3]" заставит запустить test 1, test 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');
}); copy

Шаблоны имён тестов также можно задавать с использованием литералов регулярных выражений. Это позволяет использовать флаги регулярных выражений. В предыдущем примере запуск Node.js с --test-name-pattern="/test [4-5]/i" (или --test-skip-pattern="/test [4-5]/i") совпадёт с Test 4 и Test 5, поскольку шаблон нечувствителен к регистру.

Для сопоставления одного теста с шаблоном вы можете префиксровать его всеми именами предковых тестов, разделенных пробелами, чтобы убедиться, что он уникален. Например, учитывая следующий файл с тестами:

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

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

Запуск Node.js с --test-name-pattern="test 1 some test" совпадёт только с some test в test 1.

Шаблоны имён тестов не изменяют набор файлов, которые выполняет запускатель тестов.

Если и --test-name-pattern и --test-skip-pattern указаны, тесты должны удовлетворять обеим требованиям, чтобы выполняться.

Внезапная асинхронная активность

После завершения выполнения функции теста результаты сообщаются как можно быстрее, сохраняя порядок тестов. Однако возможно, что функция теста генерирует асинхронную активность, которая существует дольше, чем сам тест. Запускатель тестов обрабатывает этот тип активности, но не задерживает отчет о результатах тестов для его учета.

В следующем примере тест завершается, а две операции setImmediate() всё ещё активны. Первый setImmediate() пытается создать новый подтест. Так как родительский тест уже завершился и вывел свои результаты, новый подтест сразу же помечается как неудачный и сообщается позже в <Поток тестов>.

Второй setImmediate() создаёт событие uncaughtException. События uncaughtException и unhandledRejection, исходящие из завершённого теста, помечаются как неудачные модулем test и сообщаются как диагностические предупреждения на верхнем уровне потоком <Поток тестов>.

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

Режим наблюдения

Добавлен в: v19.2.0, v18.13.0
Уровень стабильности: 1 - Экспериментальный

Запускатель тестов Node.js поддерживает режим наблюдения, передавая флаг --watch:

node --test --watch copy

В режиме наблюдения запускатель тестов будет следить за изменениями файлов тестов и их зависимостей. При обнаружении изменения запускатель тестов повторно выполнит тесты, затронутые изменением. Запускатель тестов будет продолжать работу до завершения процесса.

Запуск тестов из командной строки

Запуск исполнителя тестов Node.js из командной строки можно осуществить, передав флаг --test:

node --test copy

По умолчанию 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

В качестве альтернативы можно передать один или несколько шаблонов glob в качестве последних аргументов командной строки Node.js, как показано ниже. Шаблоны glob следуют поведению glob(7). Шаблоны glob должны быть заключены в двойные кавычки в командной строке, чтобы предотвратить расширение оболочки, что может снизить переносимость между системами.

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

Соответствующие файлы выполняются как файлы тестов. Более подробную информацию о выполнении файлов тестов можно найти в разделе модель выполнения исполнителя тестов.

Модель выполнения исполнителя тестов

Каждый соответствующий файл теста выполняется в отдельном дочернем процессе. Максимальное количество дочерних процессов, работающих одновременно, контролируется флагом --test-concurrency. Если дочерний процесс завершается с кодом выхода 0, тест считается пройденным. В противном случае тест считается неудачным. Файлы тестов должны быть исполняемыми для Node.js, но не обязаны использовать модуль node:test во внутренней работе.

Каждый файл теста выполняется так, как если бы это был обычный скрипт. То есть, если сам файл теста использует node:test для определения тестов, все эти тесты будут выполняться в одном потоке приложения, независимо от значения опции concurrency объекта test().

Сбор покрытия кода

Стабильность: 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 */ copy

Покрытие кода также можно отключить для определённого числа строк. После указанного количества строк покрытие будет автоматически включено. Если количество строк не указано явно, игнорируется одна строка.

/* 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');
} copy

Отчетчики покрытия

Отчетчики tap и spec будут выводить сводку статистики покрытия. Также есть отчетчик lcov, который сгенерирует файл lcov, который можно использовать для подробного отчёта о покрытии.

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

Ограничения

Функциональность покрытия кода исполнителя тестов не поддерживает исключение определённых файлов или каталогов из отчёта о покрытии.

Мокирование

Модуль node:test поддерживает мокирование во время тестирования через глобальный объект mock. Следующий пример создаёт шпион (spy) для функции, складывающей два числа. Затем шпион используется для проверки того, что функция была вызвана ожидаемым образом.

Модули MJS

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

Модули CJS

'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 каждого теста. В следующем примере создаётся шпион для метода объекта, используя API, доступный в TestContext. Преимущество мокирования через контекст теста заключается в том, что исполнитель тестов автоматически восстановит всю смокированную функциональность после завершения теста.

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

Таймеры

Мокирование таймеров — это техника, часто используемая при тестировании ПО, для моделирования и контроля поведения таймеров, таких как setInterval и setTimeout, без реального ожидания указанных интервалов времени.

Обратитесь к классу MockTimers для полного списка методов и функций.

Это позволяет разработчикам писать более надёжные и предсказуемые тесты для функциональности, зависящей от времени.

Пример ниже демонстрирует как смокировать setTimeout. Используя .enable({ apis: ['setTimeout'] }); это смокирует функции setTimeout в модулях node:timers и node:timers/promises, а также из глобального контекста Node.js.

Примечание: Деструктуризация функций, таких как import { setTimeout } from 'node:timers', в данный момент не поддерживается данным API.

Модули MJS

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

Модули CJS

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

Такая же функциональность мокирования также доступна в свойстве mock объекта TestContext каждого теста. Преимущество мокирования через контекст теста заключается в том, что исполнитель тестов автоматически восстановит всю смокированную функциональность таймеров после завершения теста.

Модули MJS

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

Модули CJS

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

Модули MJS

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

Модули CJS

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

Если начальная эпоха не задана, начальная дата будет основана на 0 в Unix-эпохе. Это 1 января 1970 года, 00:00:00 UTC. Вы можете задать начальную дату, передав свойство now методу .enable(). Это значение будет использовано в качестве начальной даты для смокированного объекта Date. Это может быть положительное целое число или другой объект Date.

Модули MJS

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

Модули CJS

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() для ручного перемещения смокированной даты в другое время. Этот метод принимает только положительное целое число.

Примечание: Этот метод выполнит все смокированные таймеры, которые находятся в прошлом от нового времени.

В примере ниже мы устанавливаем новое время для смокированной даты.

Модули MJS

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

Модули CJS

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(). Это полезно, если вы хотите протестировать функциональность, зависящую от времени, которая уже в прошлом.

Модули MJS

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

Модули CJS

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() выполнит все таймеры, которые находятся в очереди. Это также продвинет смокированную дату к времени последнего выполненного таймера, как будто время прошло.

Модули MJS

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

Модули CJS

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.0 - Ранняя разработка

Тесты снимков позволяют произвольным значениям сериализоваться в строковые значения и сравниваться с набором известных хороших значений. Известные хорошие значения называются снимками и хранятся в файле снимка. Файлы снимков управляются исполнителем тестов, но предназначены для удобства чтения человеком для отладки. Лучшая практика — включать файлы снимков в систему управления версиями вместе с файлами тестов. Для активации тестирования снимков Node.js должен быть запущен с флагом командной строки --experimental-test-snapshots.

Файлы снимков создаются путём запуска Node.js с флагом командной строки --test-update-snapshots. Для каждого файла теста генерируется отдельный файл снимка. По умолчанию файл снимка имеет то же имя, что и process.argv[1], с расширением .snapshot. Это поведение можно настроить с помощью функции snapshot.setResolveSnapshotPath() . Каждый ассершен снимка соответствует экспорту в файле снимка.

Ниже показан пример теста снимка. В первый раз при выполнении этого теста он потерпит неудачу, потому что соответствующий файл снимка не существует.

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

Сгенерируйте файл снимка, запустив файл теста с флагом --test-update-snapshots. Тест должен пройти успешно, и файл с именем test.js.snapshot будет создан в той же директории, что и файл теста. Содержимое файла снимка показано ниже. Каждый снимок идентифицируется полным именем теста и счётчиком для различения снимков в одном тесте.

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

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

После создания файла снимка запустите тесты снова без флага --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 для запуска тестов с использованием определённого отчётчика.

Поддерживаются следующие встроенные отчётчики:

  • tap Отчётчик tap выводит результаты тестов в формате TAP.

  • spec Отчётчик spec выводит результаты тестов в удобочитаемом формате.

  • dot Отчётчик dot выводит результаты тестов в компактном формате, где каждый пройденный тест представлен ., а каждый неудачный тест — X.

  • junit Отчётчик junit выводит результаты тестов в формате XML jUnit.

  • lcov Отчётчик lcov выводит покрытие кода при использовании флага --experimental-test-coverage.

Если stdout является TTY, то по умолчанию используется отчётчик spec . В противном случае по умолчанию используется отчётчик tap.

Точный вывод этих отчётчиков может изменяться между версиями Node.js и не должен использоваться в программах. Если требуется программно получить вывод запуска тестов, используйте события, испускаемые <TestsStream>.

Отчётчики доступны через модуль node:test/reporters:

Модули MJS

import { tap, spec, dot, junit, lcov } from 'node:test/reporters';

Модули CJS

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

Настраиваемые отчётчики

--test-reporter можно использовать для указания пути к настраиваемому отчётчику. Настраиваемый отчётчик — это модуль, который экспортирует значение, принимаемое stream.compose. Отчётчики должны преобразовывать события, испускаемые <TestsStream>.

Пример настраиваемого отчётчика с использованием <stream.Transform>:

Модули MJS

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;

Модули CJS

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;

Пример настраиваемого отчётчика с использованием генераторной функции:

Модули MJS

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

Модули CJS

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 должно быть строкой, подобной используемой в import() в коде JavaScript, или значением, предоставленным для --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 copy

Когда указан единственный отчётчик, назначение по умолчанию будет stdout, если явно не указано другое.

run([options])

История
Версия Изменения
v22.0.0

Добавлен параметр forceExit.

v20.1.0, v18.17.0

Добавлен параметр testNamePatterns.

v18.9.0, v16.19.0

Добавлен в: v18.9.0, v16.19.0

  • options <Объект> Параметры конфигурации для запуска тестов. Поддерживаются следующие свойства:
    • concurrency <число> | <логическое значение> Если задано число, то столько процессов будет запущено параллельно для каждого файла тестов. Если true, то os.availableParallelism() - 1 файлы тестов будут запущены параллельно. Если false, то будет запущен только один файл тестов за раз. По умолчанию: false.
    • files: <Массив> Массив, содержащий список файлов для запуска. По умолчанию соответствуют файлам из модели исполнения запуска тестов.
    • forceExit: <логическое значение> Настраивает запуск тестов на выход из процесса после завершения всех известных тестов, даже если цикл событий остаётся активным. По умолчанию: false.
    • inspectPort <число> | <Функция> Устанавливает порт инспектора для дочернего процесса тестирования. Это может быть число или функция, которая не принимает аргументов и возвращает число. Если задано нулевое значение, каждый процесс получает свой порт, инкрементированный от порта основного процесса process.debugPort. По умолчанию: undefined.
    • only: <логическое значение> Если истинно, контекст тестирования будет запускать только тесты, для которых установлен параметр only.
    • setup <Функция> Функция, которая принимает экземпляр TestsStream и может использоваться для настройки слушателей до запуска любых тестов. По умолчанию: undefined.
    • signal <AbortSignal> Разрешает прерывание процесса выполнения тестов.
    • testNamePatterns <строка> | <RegExp> | <Массив> Строка, RegExp или массив RegExp, который можно использовать для запуска только тестов, чьё имя соответствует указанному шаблону. Шаблоны имён тестов интерпретируются как JavaScript регулярные выражения. Для каждого исполняемого теста также выполняются соответствующие хуки тестов, например, beforeEach(). По умолчанию: undefined.
    • timeout <число> Количество миллисекунд, по истечении которых выполнение теста завершится с ошибкой. Если не указано, подтесты наследуют это значение от родительского теста. По умолчанию: Infinity.
    • watch <логическое значение> Запускать ли в режиме просмотра. По умолчанию: false.
    • shard <Объект> Запуск тестов в определённом фрагменте. По умолчанию: undefined.
      • index <число> — положительное целое число от 1 до <total>, которое указывает индекс фрагмента для запуска. Этот параметр обязателен.
      • total <число> — положительное целое число, которое указывает общее количество фрагментов для разделения файлов тестов. Этот параметр обязателен.
  • Возвращает: <TestsStream>

Примечание: shard используется для горизонтального распараллеливания запуска тестов на различных машинах или процессах, идеально подходит для масштабных выполнений в различных средах. Несовместим с режимом watch , предназначенным для быстрой итерации кода путём автоматического повторного запуска тестов при изменениях файлов.

Модули MJS

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

Модули CJS

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
  • name <строка> Название набора тестов, отображаемое при сообщении о результатах. По умолчанию: свойство name объекта fn, или '<anonymous>', если у fn нет имени.
  • options <Объект> Необязательные параметры конфигурации набора. Поддерживает те же параметры, что и test([name][, options][, fn]).
  • fn <Функция> | <Асинхронная функция> Функция набора, объявляющая вложенные тесты и наборы. Первым аргументом этой функции является объект SuiteContext. По умолчанию: функция без действий.
  • Возвращает: <Обещание> Немедленно выполняется с undefined.

Функция suite() импортирована из модуля node:test.

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

Добавлена в: v22.0.0

Сокращенная запись для пропуска набора. Это то же самое, что и suite([name], { skip: true }[, fn]).

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

Добавлена в: v22.0.0

Сокращенная запись для обозначения набора как TODO. Это то же самое, что и suite([name], { todo: true }[, fn]).

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

Добавлена в: v22.0.0

Сокращенная запись для обозначения набора как only. Это то же самое, что и suite([name], { only: true }[, fn]).

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

История
Версия Изменения
v20.2.0, v18.17.0

Добавлены сокращения skip, todo, и only.

v18.8.0, v16.18.0

Добавлен параметр signal.

v18.7.0, v16.17.0

Добавлен параметр timeout.

v18.0.0, v16.17.0

Добавлена в: v18.0.0, v16.17.0

  • name <строка> Название теста, отображаемое при сообщении о результатах. По умолчанию: свойство name объекта fn, или '<anonymous>', если у fn нет имени.
  • options <Объект> Параметры конфигурации для теста. Поддерживаются следующие свойства:
    • concurrency <число> | <логическое значение> Если указано число, столько тестов будет выполняться параллельно в потоке приложения. Если true, все запланированные асинхронные тесты выполняются одновременно в потоке. Если false, только один тест выполняется за раз. Если не указано, подтесты наследуют это значение от родительского теста. По умолчанию: false.
    • only <логическое значение> Если истинно, и контекст теста настроен на выполнение only тестов, то этот тест будет выполнен. В противном случае тест пропускается. По умолчанию: false.
    • signal <AbortSignal> Разрешает прерывание текущего теста.
    • skip <логическое значение> | <строка> Если истинно, тест пропускается. Если указана строка, эта строка отображается в результатах теста как причина пропуска. По умолчанию: false.
    • todo <логическое значение> | <строка> Если истинно, тест помечен как TODO. Если указана строка, эта строка отображается в результатах теста как причина, по которой тест TODO. По умолчанию: false.
    • timeout <число> Количество миллисекунд, через которое тест будет считаться проваленным. Если не указано, подтесты наследуют это значение от родительского теста. По умолчанию: Infinity.
    • plan <число> Количество ожидаемых утверждений и подтестов, которые будут выполнены в тесте. Если количество выполненных утверждений в тесте не соответствует указанному в плане, тест будет считаться проваленным. По умолчанию: undefined.
  • fn <Функция> | <Асинхронная функция> Функция, подлежащая тестированию. Первым аргументом этой функции является объект TestContext. Если тест использует обратные вызовы, функция обратного вызова передаётся в качестве второго аргумента. По умолчанию: функция без действий.
  • Возвращает: <Обещание> Выполняется, когда тест завершается, или немедленно, если тест выполняется внутри набора.

Функция test() - это значение, импортированное из модуля test. Каждый вызов этой функции приводит к сообщению о тесте в <ПотокТестов>.

Объект TestContext, переданный в аргумент fn, может быть использован для выполнения действий, связанных с текущим тестом. Примеры включают пропуск теста, добавление дополнительной диагностической информации или создание подтестов.

test() возвращает Promise, который выполняется, когда тест завершается. Если test() вызывается внутри набора, он выполняется немедленно. Значение возврата обычно можно игнорировать для тестов верхнего уровня. Однако значение возврата из подтестов необходимо использовать, чтобы предотвратить завершение родительского теста раньше и отмену подтеста, как показано в следующем примере.

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

Параметр 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.0

Вызов it() теперь эквивалентен вызову 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 <Функция> | <Асинхронная функция> Функция-обработчик. Если обработчик использует колбэки, функция колбэка передается в качестве второго аргумента. По умолчанию: функция-пустышка.
  • options <Объект> Параметры конфигурации для обработчика. Поддерживаются следующие свойства:
    • signal <AbortSignal> Разрешает прерывание выполнения обработчика.
    • timeout <число> Количество миллисекунд, после которого обработчик завершится с ошибкой. Если не указано, подтесты наследуют это значение от родительского теста. По умолчанию: Infinity.

Эта функция создает обработчик, который выполняется перед выполнением набора тестов.

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

after([fn][, options])

Добавлен в: v18.8.0, v16.18.0
  • fn <Функция> | <Асинхронная функция> Функция-обработчик. Если обработчик использует колбэки, функция колбэка передается в качестве второго аргумента. По умолчанию: функция-пустышка.
  • options <Объект> Параметры конфигурации для обработчика. Поддерживаются следующие свойства:
    • signal <AbortSignal> Разрешает прерывание выполнения обработчика.
    • timeout <число> Количество миллисекунд, после которого обработчик завершится с ошибкой. Если не указано, подтесты наследуют это значение от родительского теста. По умолчанию: Infinity.

Эта функция создает обработчик, который выполняется после выполнения набора тестов.

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

Примечание: Обработчик after гарантированно выполняется, даже если тесты в наборе завершаются с ошибкой.

beforeEach([fn][, options])

Добавлен в: v18.8.0, v16.18.0
  • fn <Функция> | <Асинхронная функция> Функция-обработчик. Если обработчик использует колбэки, функция колбэка передается в качестве второго аргумента. По умолчанию: функция-пустышка.
  • options <Объект> Параметры конфигурации для обработчика. Поддерживаются следующие свойства:
    • signal <AbortSignal> Разрешает прерывание выполнения обработчика.
    • timeout <число> Количество миллисекунд, после которого обработчик завершится с ошибкой. Если не указано, подтесты наследуют это значение от родительского теста. По умолчанию: Infinity.

Эта функция создаёт обработчик, который выполняется перед каждым тестом в текущем наборе.

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

afterEach([fn][, options])

Добавлен в: v18.8.0, v16.18.0
  • fn <Функция> | <Асинхронная функция> Функция-обработчик. Если обработчик использует колбэки, функция колбэка передается в качестве второго аргумента. По умолчанию: функция-пустышка.
  • options <Объект> Параметры конфигурации для обработчика. Поддерживаются следующие свойства:
    • signal <AbortSignal> Разрешает прерывание выполнения обработчика.
    • timeout <число> Количество миллисекунд, после которого обработчик завершится с ошибкой. Если не указано, подтесты наследуют это значение от родительского теста. По умолчанию: Infinity.

Эта функция создаёт обработчик, который выполняется после каждого теста в текущем наборе. Обработчик afterEach() выполняется даже если тест завершается с ошибкой.

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

snapshot

Добавлен в: v22.3.0
Стабильность: 1.0 — Ранняя разработка

Объект, методы которого используются для настройки параметров снимков по умолчанию в текущем процессе. Можно применить ту же конфигурацию ко всем файлам, поместив код конфигурации в модуль, предварительно загруженный с помощью --require или --import.

snapshot.setDefaultSnapshotSerializers(serializers)

Добавлен в: v22.3.0
Стабильность: 1.0 — Ранняя разработка
  • serializers <Массив> Массив синхронных функций, используемых в качестве стандартных сериализаторов для тестов с сохранением снимков.

Эта функция используется для настройки механизма сериализации по умолчанию, используемого исполнителем тестов. По умолчанию, исполнитель тестов выполняет сериализацию, вызывая JSON.stringify(value, null, 2) для предоставленного значения. JSON.stringify() имеет ограничения относительно циклических структур и поддерживаемых типов данных. Если требуется более надёжный механизм сериализации, следует использовать эту функцию.

snapshot.setResolveSnapshotPath(fn)

Добавлен в: v22.3.0
Стабильность: 1.0 — Ранняя разработка
  • fn <Функция> Функция, используемая для вычисления расположения файла снимка. Функция получает в качестве единственного аргумента путь к файлу теста. Если process.argv[1] не связан с файлом (например, в REPL), входные данные undefined. fn() должна вернуть строку, указывающую расположение файла снимка.

Эта функция используется для настройки расположения файла снимка, используемого для тестирования сохранением снимков. По умолчанию имя файла снимка совпадает с именем файла точки входа с расширением .snapshot.

END_OF_DOCUMENT_MARKER

Класс: MockFunctionContext

Добавлена в: v19.1.0, v18.13.0

Класс MockFunctionContext используется для проверки или изменения поведения моков, созданных с помощью API MockTracker.

ctx.calls

Добавлена в: v19.1.0, v18.13.0
  • <Массив>

Метод-геттер, возвращающий копию внутреннего массива, используемого для отслеживания вызовов мока. Каждый элемент массива — объект со следующими свойствами.

  • arguments <Массив> Массив аргументов, переданных в функцию мока.
  • error <любой> Если функция мока выбросила исключение, то это свойство содержит выброшенное значение. По умолчанию: undefined.
  • result <любой> Значение, возвращенное функцией мока.
  • stack <Ошибка> Объект Error с помощью стека которого можно определить место вызова функции мока.
  • target <Функция> | <неопределено> Если функция мока — конструктор, в этом поле содержится класс, который создается. В противном случае это будет undefined.
  • this <любой> Значение this функции мока.

ctx.callCount()

Добавлена в: v19.1.0, v18.13.0
  • Возвращает: <целое число> Количество вызовов этого мока.

Функция возвращает количество вызовов данного мока. Эта функция более эффективна, чем проверка ctx.calls.length, потому что ctx.calls — геттер, создающий копию внутреннего массива отслеживания вызовов.

ctx.mockImplementation(implementation)

Добавлена в: v19.1.0, v18.13.0
  • 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);
}); copy

ctx.mockImplementationOnce(implementation[, onCall])

Добавлена в: v19.1.0, v18.13.0
  • implementation <Функция> | <Асинхронная функция> Функция, которая будет использоваться в качестве реализации мока для вызова с номером, указанным в onCall.
  • onCall <целое число> Номер вызова, который будет использовать implementation. Если указанный вызов уже произошёл, то будет выброшено исключение. По умолчанию: Номер следующего вызова.

Эта функция используется для изменения поведения существующего мока для одного вызова. После того, как произойдёт вызов 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);
}); copy

ctx.resetCalls()

Добавлена в: v19.3.0, v18.13.0

Сбрасывает историю вызовов функции мока.

ctx.restore()

Добавлена в: v19.1.0, v18.13.0

Сбрасывает реализацию функции мока до её исходного поведения. После вызова этой функции мок всё ещё может использоваться.

Класс: MockModuleContext

Добавлена в: v22.3.0
Уровень стабильности: 1.0 — На ранней стадии разработки

Класс MockModuleContext используется для управления поведением модульных моков, созданных с помощью API MockTracker.

ctx.restore()

Добавлена в: v22.3.0

Сбрасывает реализацию модульного мока.

Класс: MockTracker

Добавлен в: v19.1.0, v18.13.0

Класс MockTracker используется для управления функциональностью подмены. Модуль тестового запуска предоставляет экспорт верхнего уровня mock, который является экземпляром MockTracker. Каждый тест также предоставляет свой экземпляр MockTracker через свойство контекста теста mock.

Опции реализации подмены функции

Добавлен в: v19.1.0, v18.13.0
  • Опциональный метод для создания подмены. По умолчанию: функция без действий.<Function> | <AsyncFunction>
  • Опциональный метод, используемый как реализация подмены для original. Это полезно для создания подмен, которые демонстрируют одно поведение для определенного числа вызовов, а затем восстанавливают поведение original. По умолчанию: метод, указанный в original.<Function> | <AsyncFunction>
  • Дополнительные параметры конфигурации для подмены функции. Поддерживаются следующие свойства:<Object>
    • Количество раз, когда подмена будет использовать поведение implementation. После того, как функция подмены будет вызвана times раз, она автоматически восстановит поведение original. Это значение должно быть целым числом, большим нуля. По умолчанию: Infinity.<integer>
  • Возвращает: <Proxy> Подменённую функцию. Подменённая функция содержит специальное свойство mock, которое является экземпляром MockFunctionContext и может использоваться для проверки и изменения поведения подменённой функции.

Эта функция используется для создания подменённой функции.

Следующий пример создаёт подменённую функцию, которая инкрементирует счётчик на единицу при каждом вызове. Параметр times используется для изменения поведения подмены таким образом, что первые два вызова добавляют два к счётчику вместо одного.

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

Опции реализации подмены свойства-геттера

Добавлен в: v19.3.0, v18.13.0

Эта функция является синтаксическим сахаром для MockTracker.method с options.getter установленным в true.

Опции реализации подмены метода

Добавлен в: v19.1.0, v18.13.0
  • Объект, метод которого подменяется.<Object>
  • Идентификатор метода на object для подмены. Если object[methodName] не является функцией, выбрасывается ошибка.<string> | <symbol>
  • Опциональный метод, используемый как реализация подмены для object[methodName]. По умолчанию: исходный метод, указанный в object[methodName].<Function> | <AsyncFunction>
  • Дополнительные параметры конфигурации для подмены метода. Поддерживаются следующие свойства:<Object>
    • Если true, object[methodName] обрабатывается как геттер. Этот параметр нельзя использовать с параметром setter.<boolean> По умолчанию: false.
    • Если true, object[methodName] обрабатывается как сеттер. Этот параметр нельзя использовать с параметром getter.<boolean> По умолчанию: false.
    • Количество раз, когда подмена будет использовать поведение implementation. После того, как подменённый метод был вызван times раз, он автоматически восстановит исходное поведение. Это значение должно быть целым числом, большим нуля. По умолчанию: Infinity.<integer>
  • Возвращает: <Proxy> Подменённый метод. Подменённый метод содержит специальное свойство mock, которое является экземпляром MockFunctionContext и может использоваться для проверки и изменения поведения подменённого метода.

Эта функция используется для создания подмены на существующем методе объекта. Следующий пример демонстрирует, как создается подмена на существующем методе объекта.

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

Опции подмены модуля

Добавлен в: v22.3.0
Уровень стабильности: 1.0 - Ранняя разработка
  • Идентификатор модуля, который нужно подменить.<string>
  • Дополнительные параметры конфигурации для подмены модуля. Поддерживаются следующие свойства:<Object>
    • Если false, каждый вызов require() или import() генерирует новый модуль подмены. Если true, последующие вызовы вернут один и тот же модуль подмены, и модуль подмены будет добавлен в кэш CommonJS.<boolean> По умолчанию: false.
    • Опциональное значение, используемое в качестве значения экспорта по умолчанию подменённого модуля. Если это значение не указано, подмены ESM не включают экспорт по умолчанию. Если подмена является модулем CommonJS или встроенным модулем, это значение используется как значение module.exports. Если это значение не указано, подмены CJS и встроенные подмены используют пустой объект в качестве значения module.exports.<any>
    • Опциональный объект, ключи и значения которого используются для создания именованных экспортов подменённого модуля. Если подмена является модулем CommonJS или встроенным модулем, эти значения копируются в module.exports . Поэтому, если подмена создается с именованными экспортами и экспортом по умолчанию, отличным от объекта, подмена выбросит исключение при использовании как модуль CJS или встроенный модуль.<Object>
  • Возвращает: <MockModuleContext> Объект, который можно использовать для управления подменой.

Эта функция используется для подмены экспортов модулей ECMAScript, модулей CommonJS и встроенных модулей Node.js. Любые ссылки на исходный модуль до подмены не затрагиваются. Следующий пример демонстрирует, как создается подмена для модуля.

test('mocks a builtin module in both module systems', async (t) => {
  // Create a mock of 'node:readline' with a named export named 'fn', which
  // does not exist in the original 'node:readline' module.
  const mock = t.mock.module('node:readline', {
    namedExports: { fn() { return 42; } },
  });

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

  // cursorTo() is an export of the original 'node:readline' module.
  assert.strictEqual(esmImpl.cursorTo, undefined);
  assert.strictEqual(cjsImpl.cursorTo, undefined);
  assert.strictEqual(esmImpl.fn(), 42);
  assert.strictEqual(cjsImpl.fn(), 42);

  mock.restore();

  // The mock is restored, so the original builtin module is returned.
  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);
}); copy

Сброс подмен

Добавлен в: v19.1.0, v18.13.0

Эта функция восстанавливает исходное поведение всех подмен, которые были ранее созданы этим MockTracker, и отсоединяет подмены от экземпляра MockTracker. После отсоединения подмены всё ещё можно использовать, но экземпляр MockTracker больше не может быть использован для сброса их поведения или взаимодействия с ними.

После завершения каждого теста эта функция вызывается на контексте теста MockTracker. Если глобальный MockTracker используется часто, рекомендуется вызывать эту функцию вручную.

Восстановление всех подмен

Добавлен в: v19.1.0, v18.13.0

Эта функция восстанавливает исходное поведение всех подмен, которые были ранее созданы этим MockTracker. В отличие от mock.reset(), mock.restoreAll() не отсоединяет подмены от экземпляра MockTracker.

Опции реализации подмены свойства-сеттера

Добавлен в: v19.3.0, v18.13.0

Эта функция является синтаксическим сахаром для MockTracker.method с options.setter установленным в true.

Класс: MockTimers

Добавлен в: v20.4.0, v18.19.0
Устойчивость: 1 - Экспериментальная

Имитация таймеров — это техника, часто используемая в тестировании программного обеспечения для имитации и управления поведением таймеров, таких как setInterval и setTimeout, без фактического ожидания указанных интервалов времени.

MockTimers также может имитировать объект Date.

Класс MockTracker предоставляет экспорт верхнего уровня timers, который является экземпляром MockTimers.

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(). По умолчанию: 0.

Примечание: При включении имитации для конкретного таймера его связанная функция clear также будет неявно имитироваться.

Примечание: Имитация Date повлияет на поведение имитируемых таймеров, так как они используют один и тот же внутренний таймер.

Пример использования без установки начального времени:

Модули MJS

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

Модули CJS

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

В приведенном выше примере включена имитация таймера setInterval и неявно имитируется функция clearInterval. Будут имитироваться только функции setInterval и clearInterval из node:timers, node:timers/promises и globalThis.

Пример использования с установленным начальным временем

Модули MJS

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

Модули CJS

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

Пример использования с установленным в качестве начального времени объектом Date

Модули MJS

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

Модули CJS

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

В качестве альтернативы, если вы вызываете mock.timers.enable() без параметров:

Все таймеры ('setInterval', 'clearInterval', 'setTimeout', 'clearTimeout', 'setImmediate', и 'clearImmediate' ) будут имитироваться. Будут имитироваться функции setInterval, clearInterval, setTimeout, clearTimeout, setImmediate, и clearImmediate из node:timers, node:timers/promises, и globalThis. А также глобальный объект Date.

timers.reset()

Добавлен в: v20.4.0, v18.19.0

Эта функция восстанавливает стандартное поведение всех ранее созданных имитаций данным экземпляром MockTimers и отсоединяет имитации от экземпляра MockTracker.

Примечание: После завершения каждого теста эта функция вызывается для MockTracker контекста теста.

Модули MJS

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

Модули CJS

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

timers[Symbol.dispose]()

Вызывает timers.reset().

timers.tick([milliseconds])

Добавлен в: v20.4.0, v18.19.0

Передвигает время для всех имитированных таймеров.

  • milliseconds <число> Количество времени в миллисекундах для продвижения таймеров. По умолчанию: 1.

Примечание: Это отличается от поведения setTimeout в Node.js и принимает только положительные числа. В Node.js, setTimeout с отрицательными числами поддерживается только для совместимости с веб-платформами.

Следующий пример имитирует функцию setTimeout и с помощью .tick переводит время, вызывая все ожидающие таймеры.

Модули MJS

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

Модули CJS

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 может быть вызвана многократно

Модули MJS

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

Модули CJS

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 также был установлен для имитации).

Модули MJS

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

Модули CJS

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);
});
Использование функций clear

Как уже упоминалось, все функции clear из таймеров (clearTimeout, clearInterval, и clearImmediate) неявно имитируются. Посмотрите на этот пример с использованием setTimeout:

Модули MJS

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

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

Модули CJS

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

  // Implicitly 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:timers, node:timers/promises и таймеры из глобального контекста Node.js будут включены:

Примечание: Распаковка функций, таких как import { setTimeout } from 'node:timers', в настоящее время не поддерживается этим API.

Модули MJS

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

Модули CJS

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, setInterval из node:timers/promises является AsyncGenerator, и также поддерживается этим API:

Модули MJS

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

Модули CJS

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 до времени самого позднего таймера.

В приведенном ниже примере все ожидающие таймеры запускаются немедленно, заставляя их выполняться без задержки.

Модули MJS

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

Модули CJS

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

Устанавливает текущую метку времени Unix, которая будет использоваться в качестве ссылки для любых имитированных объектов Date.

Модули MJS

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

Модули CJS

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.

Модули MJS

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

Модули CJS

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

История
Версия Изменения
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

  • Расширяет <Readable>

Успешное вызов метода run() вернёт новый объект <TestsStream>, стримингующий серию событий, представляющих выполнение тестов. TestsStream будут испускать события в порядке определения тестов.

Некоторые события гарантированно испускаются в том же порядке, что и определение тестов, в то время как другие испускаются в порядке их выполнения.

Событие: 'test:coverage'

  • data <Объект>
    • summary <Объект> Объект, содержащий отчёт о покрытии кода.
      • files <Массив> Массив отчётов о покрытии для отдельных файлов. Каждый отчёт — это объект со следующей схемой:
        • path <строка> Абсолютный путь к файлу.
        • totalLineCount <число> Общее количество строк.
        • totalBranchCount <число> Общее количество ветвей.
        • totalFunctionCount <число> Общее количество функций.
        • coveredLineCount <число> Количество покрытых строк.
        • coveredBranchCount <число> Количество покрытых ветвей.
        • coveredFunctionCount <число> Количество покрытых функций.
        • coveredLinePercent <число> Процент покрытых строк.
        • coveredBranchPercent <число> Процент покрытых ветвей.
        • coveredFunctionPercent <число> Процент покрытых функций.
        • functions <Массив> Массив функций, представляющих покрытие функций.
          • name <строка> Название функции.
          • line <число> Номер строки, где определена функция.
          • count <число> Количество вызовов функции.
        • branches <Массив> Массив ветвей, представляющих покрытие ветвей.
          • line <число> Номер строки, где определена ветвь.
          • count <число> Количество пройденных ветвей.
        • lines <Массив> Массив строк, представляющих номера строк и количество раз, когда они были покрыты.
          • line <число> Номер строки.
          • count <число> Количество покрытий строки.
      • totals <Объект> Объект, содержащий сводку по покрытию всех файлов.
        • totalLineCount <число> Общее количество строк.
        • totalBranchCount <число> Общее количество ветвей.
        • totalFunctionCount <число> Общее количество функций.
        • coveredLineCount <число> Количество покрытых строк.
        • coveredBranchCount <число> Количество покрытых ветвей.
        • coveredFunctionCount <число> Количество покрытых функций.
        • coveredLinePercent <число> Процент покрытых строк.
        • coveredBranchPercent <число> Процент покрытых ветвей.
        • coveredFunctionPercent <число> Процент покрытых функций.
      • workingDirectory <строка> Рабочая директория, когда началось измерение покрытия кода. Это полезно для отображения относительных путей в случае, если тесты изменили рабочую директорию процесса Node.js.
    • nesting <число> Уровень вложенности теста.

Выпущено, когда включено покрытие кода и все тесты завершены.

Событие: 'test:complete'

  • data <Object>
    • column <number> | <undefined> Номер столбца, в котором определён тест, или undefined , если тест был запущен через REPL.
    • details <Object> Дополнительные метаданные выполнения.
      • passed <boolean> Прошёл ли тест успешно.
      • duration_ms <number> Длительность теста в миллисекундах.
      • error <Error> | <undefined> Ошибка, содержащая ошибку, выброшенную тестом, если он не прошёл.
        • cause <Error> Фактическая ошибка, выброшенная тестом.
      • type <string> | <undefined> Тип теста, используемый для обозначения является ли это набором тестов.
    • file <string> | <undefined> Путь к файлу с тестом, undefined если тест был запущен через REPL.
    • line <number> | <undefined> Номер строки, в которой определён тест, или undefined , если тест был запущен через REPL.
    • name <string> Название теста.
    • nesting <number> Уровень вложенности теста.
    • testNumber <number> Порядковый номер теста.
    • todo <string> | <boolean> | <undefined> Присутствует, если вызвана функция context.todo
    • skip <string> | <boolean> | <undefined> Присутствует, если вызвана функция context.skip
  • 'test:pass'
  • 'test:fail'

Выводится, когда тест завершает своё выполнение. Это событие не выводится в том же порядке, что и определение тестов. Соответствующие события в порядке объявления 'test:pass' и 'test:fail'.

Событие: 'test:dequeue'

  • data <Object>
    • column <number> | <undefined> Номер столбца, в котором определён тест, или undefined , если тест был запущен через REPL.
    • file <string> | <undefined> Путь к файлу с тестом, undefined , если тест был запущен через REPL.
    • line <number> | <undefined> Номер строки, в которой определён тест, или undefined , если тест был запущен через REPL.
    • name <string> Название теста.
    • nesting <number> Уровень вложенности теста.

Выводится, когда тест из очереди, непосредственно перед его выполнением. Это событие не гарантируется в том же порядке, что и порядок определения тестов. Соответствующее событие в порядке объявления 'test:start'.

Событие: 'test:diagnostic'

  • data <Object>
    • column <number> | <undefined> Номер столбца, в котором определён тест, или undefined , если тест был запущен через REPL.
    • file <string> | <undefined> Путь к файлу с тестом, undefined , если тест был запущен через REPL.
    • line <number> | <undefined> Номер строки, в которой определён тест, или undefined , если тест был запущен через REPL.
    • message <string> Сообщение диагностики.
    • nesting <number> Уровень вложенности теста.

Выводится, когда вызывается context.diagnostic. Это событие гарантированно выводится в том же порядке, что и определение тестов.

Событие: 'test:enqueue'

  • data <Object>
    • column <number> | <undefined> Номер столбца, в котором определён тест, или undefined , если тест был запущен через REPL.
    • file <string> | <undefined> Путь к файлу с тестом, undefined , если тест был запущен через REPL.
    • line <number> | <undefined> Номер строки, в которой определён тест, или undefined , если тест был запущен через REPL.
    • name <string> Название теста.
    • nesting <number> Уровень вложенности теста.

Выводится, когда тест помещён в очередь для выполнения.

Событие: 'test:fail'

  • data <Объект>
    • column <число> | <неопределено> Номер столбца, в котором определён тест, или undefined , если тест был запущен через REPL.
    • details <Объект> Дополнительные метаданные выполнения.
      • duration_ms <число> Длительность теста в миллисекундах.
      • error <Ошибка> Ошибка, обертывающая ошибку, брошенную тестом.
        • cause <Ошибка> Фактическая ошибка, брошенная тестом.
      • type <строка> | <неопределено> Тип теста, используемый для обозначения является ли это набором тестов.
    • file <строка> | <неопределено> Путь к файлу теста, undefined если тест был запущен через REPL.
    • line <число> | <неопределено> Номер строки, в которой определён тест, или undefined , если тест был запущен через REPL.
    • name <строка> Название теста.
    • nesting <число> Уровень вложенности теста.
    • testNumber <число> Порядковый номер теста.
    • todo <строка> | <булево> | <неопределено> Присутствует, если вызван context.todo
    • skip <строка> | <булево> | <неопределено> Присутствует, если вызван context.skip

Выводится, когда тест завершается неудачно. Этот событие гарантированно будет выведено в том же порядке, что и определение тестов. Соответствующее событие, упорядоченное по выполнению, является 'test:complete'.

Событие: 'test:pass'

  • data <Объект>
    • column <число> | <неопределено> Номер столбца, в котором определён тест, или undefined , если тест был запущен через REPL.
    • details <Объект> Дополнительные метаданные выполнения.
      • duration_ms <число> Длительность теста в миллисекундах.
      • type <строка> | <неопределено> Тип теста, используемый для обозначения является ли это набором тестов.
    • file <строка> | <неопределено> Путь к файлу теста, undefined если тест был запущен через REPL.
    • line <число> | <неопределено> Номер строки, в которой определён тест, или undefined , если тест был запущен через REPL.
    • name <строка> Название теста.
    • nesting <число> Уровень вложенности теста.
    • testNumber <число> Порядковый номер теста.
    • todo <строка> | <булево> | <неопределено> Присутствует, если вызван context.todo
    • skip <строка> | <булево> | <неопределено> Присутствует, если вызван context.skip

Выводится, когда тест завершается успешно. Это событие гарантированно будет выведено в том же порядке, что и определение тестов. Соответствующее событие, упорядоченное по выполнению, является 'test:complete'.

Событие: 'test:plan'

  • data <Объект>
    • column <число> | <неопределено> Номер столбца, в котором определён тест, или undefined , если тест был запущен через REPL.
    • file <строка> | <неопределено> Путь к файлу теста, undefined если тест был запущен через REPL.
    • line <число> | <неопределено> Номер строки, в которой определён тест, или undefined , если тест был запущен через REPL.
    • nesting <число> Уровень вложенности теста.
    • count <число> Количество подтестов, которые были выполнены.

Выводится, когда все подтесты завершены для данного теста. Это событие гарантированно будет выведено в том же порядке, что и определение тестов.

Событие: 'test:start'

  • data <Объект>
    • column <число> | <неопределено> Номер столбца, в котором определён тест, или undefined если тест был запущен через REPL.
    • file <строка> | <неопределено> Путь к файлу с тестом, undefined если тест был запущен через REPL.
    • line <число> | <неопределено> Номер строки, в которой определён тест, или undefined если тест был запущен через REPL.
    • name <строка> Название теста.
    • nesting <число> Уровень вложенности теста.

Вызывается, когда тест начинает сообщать о своём статусе и статусе своих подтестов. Этот событие гарантированно вызывается в том же порядке, что и определение тестов. Соответствующее событие последовательности выполнения — 'test:dequeue'.

Событие: 'test:stderr'

  • data <Объект>
    • file <строка> Путь к файлу с тестом.
    • message <строка> Сообщение, выведенное в stderr.

Вызывается, когда выполняющийся тест записывает в stderr. Это событие вызывается только если передан флаг --test. Это событие не гарантированно вызывается в том же порядке, что и определение тестов.

Событие: 'test:stdout'

  • data <Объект>
    • file <строка> Путь к файлу с тестом.
    • message <строка> Сообщение, выведенное в stdout.

Вызывается, когда выполняющийся тест записывает в stdout. Это событие вызывается только если передан флаг --test. Это событие не гарантированно вызывается в том же порядке, что и определение тестов.

Событие: 'test:watch:drained'

Вызывается, когда в режиме наблюдения больше нет тестов в очереди на выполнение.

Класс: TestContext

История
Версия Изменения
v20.1.0, v18.17.0

Функция before была добавлена в 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 <Функция> | <Асинхронная функция> Функция-обработчик. Первым аргументом этой функции является объект TestContext. Если обработчик использует колбэки, функция колбэка передается в качестве второго аргумента. По умолчанию: функция-пустышка.
  • options <Объект> Параметры конфигурации для обработчика. Поддерживаются следующие свойства:
    • signal <AbortSignal> Позволяет прервать выполнение обработчика.
    • timeout <число> Количество миллисекунд, после которого обработчик завершится с ошибкой. Если не указано, подтесты наследуют это значение от родительского теста. По умолчанию: Infinity.

Эта функция используется для создания обработчика, выполняющегося перед подтестом текущего теста.

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

Добавлена в: v18.8.0, v16.18.0
  • fn <Функция> | <Асинхронная функция> Функция-обработчик. Первым аргументом этой функции является объект TestContext. Если обработчик использует колбэки, функция колбэка передается в качестве второго аргумента. По умолчанию: функция-пустышка.
  • options <Объект> Параметры конфигурации для обработчика. Поддерживаются следующие свойства:
    • signal <AbortSignal> Позволяет прервать выполнение обработчика.
    • timeout <число> Количество миллисекунд, после которого обработчик завершится с ошибкой. Если не указано, подтесты наследуют это значение от родительского теста. По умолчанию: 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');
    },
  );
}); copy

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

Добавлена в: v19.3.0, v18.13.0
  • fn <Функция> | <Асинхронная функция> Функция-обработчик. Первым аргументом этой функции является объект TestContext. Если обработчик использует колбэки, функция колбэка передается в качестве второго аргумента. По умолчанию: функция-пустышка.
  • options <Объект> Параметры конфигурации для обработчика. Поддерживаются следующие свойства:
    • signal <AbortSignal> Позволяет прервать выполнение обработчика.
    • timeout <число> Количество миллисекунд, после которого обработчик завершится с ошибкой. Если не указано, подтесты наследуют это значение от родительского теста. По умолчанию: Infinity.

Эта функция используется для создания обработчика, выполняющегося после завершения текущего теста.

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

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

Добавлена в: v18.8.0, v16.18.0
  • fn <Функция> | <Асинхронная функция> Функция-обработчик. Первым аргументом этой функции является объект TestContext. Если обработчик использует колбэки, функция колбэка передается в качестве второго аргумента. По умолчанию: функция-пустышка.
  • options <Объект> Параметры конфигурации для обработчика. Поддерживаются следующие свойства:
    • signal <AbortSignal> Позволяет прервать выполнение обработчика.
    • timeout <число> Количество миллисекунд, после которого обработчик завершится с ошибкой. Если не указано, подтесты наследуют это значение от родительского теста. По умолчанию: 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');
    },
  );
}); copy

context.assert

Добавлена в: v22.2.0

Объект, содержащий методы проверки, привязанные к context. Здесь доступны функции верхнего уровня из модуля node:assert для создания планов тестов.

test('test', (t) => {
  t.plan(1);
  t.assert.strictEqual(true, true);
}); copy
context.assert.snapshot(value[, options])
Добавлена в: v22.3.0
Уровень стабильности: 1.0 - На ранней стадии разработки
  • value <любое> Значение, которое необходимо сериализовать в строку. Если Node.js был запущен со флагом --test-update-snapshots, сериализованное значение записывается в файл снимков. В противном случае сериализованное значение сравнивается с соответствующим значением в существующем файле снимков.
  • options <Объект> Необязательные параметры конфигурации. Поддерживаются следующие свойства:
    • serializers <Массив> Массив синхронных функций, используемых для сериализации value в строку. value передается в качестве единственного аргумента первой функции сериализации. Возвращаемое значение каждой функции сериализации передается в качестве входных данных следующей функции сериализации. После выполнения всех функций сериализации полученное значение приводится к строковому типу. По умолчанию: Если сериализаторы не предоставлены, используются стандартные сериализаторы тестового загрузчика.

Эта функция реализует проверки для тестирования снимков.

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

context.diagnostic(message)

Добавлена в: v18.0.0, v16.17.0
  • message <строка> Сообщение, которое необходимо сообщить.

Эта функция используется для записи диагностической информации в вывод. Любая диагностическая информация включается в конце результатов теста. Эта функция не возвращает значение.

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

context.fullName

Добавлена в: v22.3.0

Имя теста и каждого из его предков, разделенные >.

context.name

Добавлена в: v18.8.0, v16.18.0

Имя теста.

context.plan(count)

Добавлена в: v22.2.0
Уровень стабильности: 1 - Экспериментальная
  • count <число> Количество ожидаемых проверок и подтестов.

Эта функция используется для задания количества ожидаемых проверок и подтестов, которые должны быть выполнены в рамках теста. Если фактическое количество проверок и подтестов не совпадает с ожидаемым значением, тест завершится с ошибкой.

Примечание: Для отслеживания проверок необходимо использовать функцию t.assert, а не assert напрямую.

test('top level test', (t) => {
  t.plan(2);
  t.assert.ok('some relevant assertion here');
  t.test('subtest', () => {});
}); copy

При работе с асинхронным кодом функция plan может быть использована для обеспечения правильного выполнения необходимого количества проверок.

test('planning with streams', (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();
  });
}); copy

context.runOnly(shouldRunOnlyTests)

Добавлена в: v18.0.0, v16.17.0
  • shouldRunOnlyTests <логическое значение> Указывает, нужно ли запускать 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 }),
  ]);
}); copy

context.signal

Добавлена в: v18.7.0, v16.17.0
  • Тип: <AbortSignal>

Может использоваться для прерывания подзадач теста, когда тест был прерван.

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

context.skip([message])

Added in: v18.0.0, v16.17.0
  • 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');
}); copy

context.todo([message])

Added in: v18.0.0, v16.17.0
  • message <string> Дополнительное TODO сообщение.

Эта функция добавляет TODO директиву в вывод теста. Если message предоставлено, оно включается в вывод. Вызов todo() не завершает выполнение функции теста. Эта функция не возвращает значение.

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

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

История
Версия Изменения
v18.8.0, v16.18.0

Добавлен параметр signal.

v18.7.0, v16.17.0

Добавлен параметр timeout.

v18.0.0, v16.17.0

Добавлен в: v18.0.0, v16.17.0

  • name <string> Имя подтеста, отображаемое при сообщении о результатах теста. По умолчанию: свойство name объекта fn, или '<anonymous>', если у fn нет имени.
  • options <Object> Параметры конфигурации подтеста. Поддерживаются следующие свойства:
    • concurrency <number> | <boolean> | <null> Если указано число, столько тестов будет выполняться параллельно в потоке приложения. Если true, все подтесты будут выполняться параллельно. Если false, будет выполняться только один тест за раз. Если не указано, подтесты наследуют это значение от родительского теста. По умолчанию: 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. Если тест использует обратные вызовы, функция обратного вызова передается в качестве второго аргумента. По умолчанию: функция-пустышка.
  • Возвращает: <Promise> Успешно выполняется undefined по завершении теста.

Эта функция используется для создания подтестов в рамках текущего теста. Эта функция работает так же, как и функция верхнего уровня test().

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

Класс: SuiteContext

Added in: v18.7.0, v16.17.0

Экземпляр SuiteContext передается каждой функции набора, чтобы взаимодействовать с запуском теста. Однако конструктор SuiteContext не доступен как часть API.

context.name

Added in: v18.8.0, v16.18.0

Имя набора.

context.signal

Added in: v18.7.0, v16.17.0
  • Тип: <AbortSignal>

Может использоваться для прерывания подзадач теста, когда тест был прерван.

© Joyent, Inc. and other Node contributors
Licensed under the MIT License.
Node.js is a trademark of Joyent, Inc. and is used with its permission.
We are not endorsed by or affiliated with Joyent.
https://nodejs.org/api/test.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API