Spec-Zone.ru › Node.js 22 LTS

Средство запуска тестов

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

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

v18.0.0, v16.17.0

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

Стабильность: 2 - Стабильный

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

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

Модули JavaScript
import test from 'node:test';
CommonJS
const test = require('node:test');

Этот модуль доступен только при использовании схемы node:.

Тесты, созданные с помощью модуля 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.

Модули JavaScript
import { describe, it } from 'node:test';
CommonJS
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() пытается создать новый вложенный тест. Поскольку родительский тест уже завершился и его результаты выведены, новый вложенный тест сразу помечается как не пройденный, а затем передается в <TestsStream>.

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

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

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

  // The test finishes after this line.
}); copy

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

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

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

node --test --watch copy

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

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

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

node --test copy

По умолчанию Node.js запускает все файлы, соответствующие следующим шаблонам:

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

Если не указан параметр --no-experimental-strip-types, также учитываются следующие дополнительные шаблоны:

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

Кроме того, в качестве последних аргументов команды Node.js можно указать один или несколько шаблонов glob, как показано ниже. Шаблоны 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-include. Если сбор данных о покрытии включен, отчет о покрытии передается всем форматировщикам результатов тестов через событие '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 верхнего уровня. В следующем примере создается шпион для функции, складывающей два числа. Затем шпион используется для проверки того, что функция была вызвана ожидаемым образом.

Модули JavaScript
import assert from 'node:assert';
import { mock, test } from 'node:test';

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

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

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

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

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

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

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

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

Та же функциональность имитации объектов также доступна через объект TestContext каждого теста. В следующем примере с помощью 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.callCount(), 0);
  assert.strictEqual(number.add(3), 8);
  assert.strictEqual(number.add.mock.callCount(), 1);

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

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

Таймеры

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

Полный список методов и возможностей см. в описании класса MockTimers.

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

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

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

Модули JavaScript
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();
});
CommonJS
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 каждого теста. Преимущество имитации объектов через контекст теста заключается в том, что средство запуска тестов автоматически восстановит все имитированные таймеры после завершения теста.

Модули JavaScript
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);
});
CommonJS
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().

Модули JavaScript
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);
});
CommonJS
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.

Модули JavaScript
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);
});
CommonJS
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(). Этот метод принимает только положительное целое число.

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

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

Модули JavaScript
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);
});
CommonJS
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(). Это полезно для тестирования функциональности, зависящей от времени, которая уже относится к прошлому.

Модули JavaScript
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);
});
CommonJS
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() выполнит все таймеры, находящиеся в очереди в данный момент. При этом имитированная дата также будет перемещена на время последнего выполненного таймера, как если бы это время уже прошло.

Модули JavaScript
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);
});
CommonJS
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);
});

Тестирование с помощью снимков

История
Версия Изменения
v23.4.0

Тестирование с помощью снимков больше не является экспериментальным.

v22.3.0

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

Тесты со снимками позволяют сериализовать произвольные значения в строки и сравнивать их с набором заведомо корректных значений. Эти заведомо корректные значения называются снимками и хранятся в файле снимков. Файлами снимков управляет средство запуска тестов, но они предназначены для чтения человеком, чтобы упростить отладку. Рекомендуется добавлять файлы снимков в систему контроля версий вместе с файлами тестов.

Файлы снимков создаются при запуске Node.js с флагом командной строки --test-update-snapshots. Для каждого файла тестов создается отдельный файл снимков. По умолчанию файл снимков имеет то же имя, что и файл тестов, но с расширением файла .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 выводит результаты тестов в формате jUnit XML.

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

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

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

Форматировщики доступны через модуль node:test/reporters:

Модули JavaScript
import { tap, spec, dot, junit, lcov } from 'node:test/reporters';
CommonJS
const { tap, spec, dot, junit, lcov } = require('node:test/reporters');

Пользовательские форматировщики

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

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

Модули JavaScript
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;
CommonJS
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;

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

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

Значение, передаваемое в --test-reporter, должно быть строкой, похожей на строку, используемую в 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.10.0

Добавлены параметры сбора покрытия.

v22.8.0

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

v22.6.0

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

v22.0.0

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

v20.1.0, v18.17.0

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

v18.9.0, v16.19.0

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

  • options <Object> Параметры конфигурации для запуска тестов. Поддерживаются следующие свойства:
    • concurrency <number> | <boolean> Если указано число, параллельно будет запущено соответствующее количество тестовых процессов, каждый из которых обрабатывает один файл с тестами. Если true, параллельно будут запущены os.availableParallelism() - 1 файлов с тестами. Если false, одновременно будет выполняться только один файл с тестами. По умолчанию: false.
    • files: <Array> Массив со списком файлов для запуска. По умолчанию: то же, что и при запуске тестов из командной строки.
    • forceExit: <boolean> Настраивает средство запуска тестов так, чтобы завершать процесс после выполнения всех известных тестов, даже если в противном случае цикл событий оставался бы активным. По умолчанию: false.
    • globPatterns <Array> Массив шаблонов glob для сопоставления с файлами тестов. Этот параметр нельзя использовать вместе с files. По умолчанию: то же, что и при запуске тестов из командной строки.
    • inspectPort <number> | <Function> Задает порт инспектора дочернего процесса теста. Это может быть число или функция без аргументов, возвращающая число. Если указано nullish-значение, каждый процесс получает собственный порт, начиная с process.debugPort основного процесса и увеличивая его. Этот параметр игнорируется, если параметру isolation присвоено значение 'none', поскольку дочерние процессы не создаются. По умолчанию: undefined.
    • isolation <string> Настраивает тип изоляции тестов. Если задано значение 'process', каждый файл с тестами запускается в отдельном дочернем процессе. Если задано значение 'none', все файлы с тестами запускаются в текущем процессе. По умолчанию: 'process'.
    • only <boolean> Если значение истинно, контекст тестирования будет запускать только тесты, для которых задан параметр only
    • setup <Function> Функция, принимающая экземпляр TestsStream и позволяющая настроить прослушиватели до запуска любых тестов. По умолчанию: undefined.
    • execArgv <Array> Массив флагов CLI, передаваемых исполняемому файлу node при создании подпроцессов. Этот параметр не действует, если isolation имеет значение 'none'. По умолчанию: []
    • argv <Array> Массив флагов CLI, передаваемых каждому файлу с тестами при создании подпроцессов. Этот параметр не действует, если isolation имеет значение 'none'. По умолчанию: [].
    • signal <AbortSignal> Позволяет прервать выполняющийся тест.
    • testNamePatterns <string> | <RegExp> | <Array> Строка, RegExp или массив RegExp, позволяющие запускать только тесты, имена которых соответствуют заданному шаблону. Шаблоны имен тестов интерпретируются как регулярные выражения JavaScript. Для каждого выполняемого теста также запускаются соответствующие хуки тестов, например beforeEach(). По умолчанию: undefined.
    • testSkipPatterns <string> | <RegExp> | <Array> Строка, RegExp или массив RegExp, позволяющие исключить из запуска тесты, имена которых соответствуют заданному шаблону. Шаблоны имен тестов интерпретируются как регулярные выражения JavaScript. Для каждого выполняемого теста также запускаются соответствующие хуки тестов, например beforeEach(). По умолчанию: undefined.
    • timeout <number> Количество миллисекунд, по истечении которых выполнение теста завершится ошибкой. Если значение не указано, вложенные тесты наследуют его от родительского теста. По умолчанию: Infinity.
    • watch <boolean> Следует ли запускать тесты в режиме наблюдения. По умолчанию: false.
    • shard <Object> Запуск тестов в определенном сегменте. По умолчанию: undefined.
      • index <number> — положительное целое число от 1 до <total>, задающее индекс запускаемого сегмента. Этот параметр обязателен.
      • total <number> — положительное целое число, задающее общее количество сегментов, на которые нужно разделить файлы с тестами. Этот параметр обязателен.
    • coverage <boolean> Включает сбор данных о покрытии кода. По умолчанию: false.
    • coverageExcludeGlobs <string> | <Array> Исключает определенные файлы из анализа покрытия кода с помощью шаблона glob, которому могут соответствовать как абсолютные, так и относительные пути к файлам. Это свойство применимо только в том случае, если для coverage задано значение true. Если заданы и coverageExcludeGlobs, и coverageIncludeGlobs, файлы должны соответствовать обоим критериям, чтобы попасть в отчет о покрытии. По умолчанию: undefined.
    • coverageIncludeGlobs <string> | <Array> Включает определенные файлы в анализ покрытия кода с помощью шаблона glob, которому могут соответствовать как абсолютные, так и относительные пути к файлам. Это свойство применимо только в том случае, если для coverage задано значение true. Если заданы и coverageExcludeGlobs, и coverageIncludeGlobs, файлы должны соответствовать обоим критериям, чтобы попасть в отчет о покрытии. По умолчанию: undefined.
    • lineCoverage <number> Задает минимальный процент покрытых строк. Если покрытие кода не достигает указанного порогового значения, процесс завершается с кодом 1. По умолчанию: 0.
    • branchCoverage <number> Задает минимальный процент покрытых ветвей. Если покрытие кода не достигает указанного порогового значения, процесс завершается с кодом 1. По умолчанию: 0.
    • functionCoverage <number> Задает минимальный процент покрытых функций. Если покрытие кода не достигает указанного порогового значения, процесс завершается с кодом 1. По умолчанию: 0.
  • Возвращает: <TestsStream>

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

Модули JavaScript
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);
CommonJS
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 <string> Имя набора тестов, отображаемое в отчетах о результатах тестирования. По умолчанию: свойство name объекта fn или '<anonymous>', если у fn нет имени.
  • options <Object> Необязательные параметры конфигурации набора тестов. Поддерживаются те же параметры, что и в test([name][, options][, fn]).
  • fn <Function> | <AsyncFunction> Функция набора тестов, объявляющая вложенные тесты и наборы. Первый аргумент этой функции — объект SuiteContext. По умолчанию: пустая функция.
  • Возвращает: <Promise> Немедленно выполняется со значением 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 <string> Имя теста, отображаемое в отчетах о результатах тестирования. По умолчанию: свойство name объекта fn или '<anonymous>', если у fn нет имени.
  • options <Object> Параметры конфигурации теста. Поддерживаются следующие свойства:
    • concurrency <number> | <boolean> Если указано число, в потоке приложения будет параллельно выполняться соответствующее количество тестов. Если true, все запланированные асинхронные тесты выполняются одновременно в потоке. Если false, одновременно выполняется только один тест. Если значение не указано, вложенные тесты наследуют его от родительского теста. По умолчанию: false.
    • only <boolean> Если значение истинно и контекст тестирования настроен на запуск тестов only, этот тест будет запущен. В противном случае тест пропускается. По умолчанию: false.
    • signal <AbortSignal> Позволяет прервать выполняющийся тест.
    • skip <boolean> | <string> Если значение истинно, тест пропускается. Если указана строка, она отображается в результатах тестирования как причина пропуска теста. По умолчанию: false.
    • todo <boolean> | <string> Если значение истинно, тест помечается как TODO. Если указана строка, она отображается в результатах тестирования как причина, по которой тест помечен как TODO. По умолчанию: false.
    • timeout <number> Количество миллисекунд, по истечении которых выполнение теста завершится ошибкой. Если значение не указано, вложенные тесты наследуют его от родительского теста. По умолчанию: Infinity.
    • plan <number> Ожидаемое количество проверок и вложенных тестов в тесте. Если фактическое количество проверок не совпадает с указанным в плане, тест завершится ошибкой. По умолчанию: undefined.
  • fn <Function> | <AsyncFunction> Функция, проверяемая тестом. Первый аргумент этой функции — объект TestContext. Если тест использует обратные вызовы, функция обратного вызова передается в качестве второго аргумента. По умолчанию: пустая функция.
  • Возвращает: <Promise> Выполняется со значением undefined после завершения теста или немедленно, если тест выполняется в наборе тестов.

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

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

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

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

after([fn][, options])

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

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

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

Примечание: Гарантируется выполнение хука after, даже если тесты в наборе завершились с ошибкой.

beforeEach([fn][, options])

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

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

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

afterEach([fn][, options])

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

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

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

assert

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

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

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

assert.register(name, fn)

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

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

snapshot

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

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

snapshot.setDefaultSnapshotSerializers(serializers)

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

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

snapshot.setResolveSnapshotPath(fn)

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

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

Класс: MockFunctionContext

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

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

ctx.calls

Добавлено в: v19.1.0, v18.13.0
  • Тип: <Array>

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

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

ctx.callCount()

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

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

ctx.mockImplementation(implementation)

Добавлено в: v19.1.0, v18.13.0
  • implementation <Function> | <AsyncFunction> Функция, которая будет использоваться в качестве новой реализации заглушки.

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

В следующем примере создается функция-заглушка с помощью 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 <Function> | <AsyncFunction> Функция, которая будет использоваться в качестве реализации заглушки для вызова с номером, указанным в onCall.
  • onCall <integer> Номер вызова, для которого будет использоваться 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

Восстанавливает реализацию заглушки модуля.

Класс: MockPropertyContext

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

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

ctx.accesses

  • <Array>

Геттер, возвращающий копию внутреннего массива, используемого для отслеживания обращений (get/set) к заглушенному свойству. Каждая запись в массиве — это объект со следующими свойствами:

  • type <string> Либо 'get', либо 'set', указывающее тип обращения.
  • value <any> Прочитанное значение (для 'get') или записанное значение (для 'set').
  • stack <Error> Объект Error, стек которого можно использовать для определения места вызова функции-заглушки.

ctx.accessCount()

  • Возвращает: <integer> Количество обращений к свойству (чтений или записей).

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

ctx.mockImplementation(value)

  • value <any> Новое значение, которое будет задано в качестве значения заглушенного свойства.

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

ctx.mockImplementationOnce(value[, onAccess])

  • value <any> Значение, которое будет использоваться в качестве реализации заглушки для обращения с номером, указанным в onAccess.
  • onAccess <integer> Номер обращения, для которого будет использоваться value. Если указанное обращение уже состоялось, будет выброшено исключение. По умолчанию: номер следующего обращения.

Эта функция используется для изменения поведения существующей заглушки при одном обращении. После обращения onAccess заглушка вернется к поведению, которое она использовала бы, если бы mockImplementationOnce() не вызывалась.

В следующем примере создается функция-заглушка с помощью t.mock.property(), выполняется обращение к заглушенному свойству, реализация заглушки заменяется другим значением для следующего обращения, после чего восстанавливается предыдущее поведение.

test('changes a mock behavior once', (t) => {
  const obj = { foo: 1 };

  const prop = t.mock.property(obj, 'foo', 5);

  assert.strictEqual(obj.foo, 5);
  prop.mock.mockImplementationOnce(25);
  assert.strictEqual(obj.foo, 25);
  assert.strictEqual(obj.foo, 5);
}); copy
Примечание

Для согласованности с остальными API заглушек эта функция считает обращениями как чтение, так и запись свойства. Если запись свойства происходит на том же индексе обращения, значение «once» будет использовано при операции записи, а значение заглушенного свойства изменится на значение «once». Это может привести к неожиданному поведению, если вы рассчитываете, что значение «once» будет использоваться только при чтении.

ctx.resetAccesses()

Сбрасывает историю обращений к заглушенному свойству.

ctx.restore()

Восстанавливает исходное поведение заглушенного свойства. Заглушку по-прежнему можно использовать после вызова этой функции.

Класс: MockTracker

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

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

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

Добавлено в: v19.1.0, v18.13.0
  • original <Function> | <AsyncFunction> Необязательная функция, для которой создается заглушка. По умолчанию: функция, ничего не выполняющая.
  • implementation <Function> | <AsyncFunction> Необязательная функция, используемая в качестве реализации заглушки для original. Это полезно для создания заглушек, которые демонстрируют одно поведение заданное количество вызовов, а затем восстанавливают поведение original. По умолчанию: функция, указанная в original.
  • options <Object> Необязательные параметры конфигурации функции-заглушки. Поддерживаются следующие свойства:
    • times <integer> Количество вызовов, в течение которых заглушка будет использовать поведение implementation. После того как функция-заглушка будет вызвана times раз, она автоматически восстановит поведение original. Значение должно быть целым числом больше нуля. По умолчанию: Infinity.
  • Возвращает: <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

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

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

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

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

Добавлено в: v19.1.0, v18.13.0
  • object <Object> Объект, метод которого заглушается.
  • methodName <string> | <symbol> Идентификатор метода объекта object, который нужно заглушить. Если object[methodName] не является функцией, выбрасывается ошибка.
  • implementation <Function> | <AsyncFunction> Необязательная функция, используемая в качестве реализации заглушки для object[methodName]. По умолчанию: исходный метод, указанный в object[methodName].
  • options <Object> Необязательные параметры конфигурации метода-заглушки. Поддерживаются следующие свойства:
    • getter <boolean> Если true, object[methodName] рассматривается как геттер. Этот параметр нельзя использовать вместе с параметром setter. По умолчанию: false.
    • setter <boolean> Если true, object[methodName] рассматривается как сеттер. Этот параметр нельзя использовать вместе с параметром getter. По умолчанию: false.
    • times <integer> Количество вызовов, в течение которых заглушка будет использовать поведение implementation. После того как метод-заглушка будет вызван times раз, исходное поведение будет автоматически восстановлено. Значение должно быть целым числом больше нуля. По умолчанию: Infinity.
  • Возвращает: <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.callCount(), 0);
  assert.strictEqual(number.subtract(3), 2);
  assert.strictEqual(number.subtract.mock.callCount(), 1);

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

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

mock.module(specifier[, options])

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

Добавлена поддержка модулей JSON.

v22.3.0

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

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

Эта функция используется для создания заглушек экспортов модулей ECMAScript, модулей CommonJS, модулей JSON и встроенных модулей Node.js. Ссылки на исходный модуль, полученные до создания заглушки, не изменяются. Чтобы включить создание заглушек модулей, Node.js необходимо запустить с флагом командной строки --experimental-test-module-mocks.

В следующем примере показано, как создать заглушку модуля.

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

mock.property(object, propertyName[, value])

Добавлено в: v22.20.0
  • object <Object> Объект, значение которого заглушается.
  • propertyName <string> | <symbol> Идентификатор свойства объекта object, которое нужно заглушить.
  • value <any> Необязательное значение, используемое в качестве значения заглушки для object[propertyName]. По умолчанию: исходное значение свойства.
  • Возвращает: <Proxy> Прокси заглушенного объекта. Заглушенный объект содержит специальное свойство mock, являющееся экземпляром MockPropertyContext и предназначенное для проверки поведения заглушенного свойства и управления им.

Создает заглушку для значения свойства объекта. Это позволяет отслеживать обращения к определенному свойству и управлять ими, в том числе контролировать количество его чтений (геттер) или записей (сеттер), а также восстанавливать исходное значение после создания заглушки.

test('mocks a property value', (t) => {
  const obj = { foo: 42 };
  const prop = t.mock.property(obj, 'foo', 100);

  assert.strictEqual(obj.foo, 100);
  assert.strictEqual(prop.mock.accessCount(), 1);
  assert.strictEqual(prop.mock.accesses[0].type, 'get');
  assert.strictEqual(prop.mock.accesses[0].value, 100);

  obj.foo = 200;
  assert.strictEqual(prop.mock.accessCount(), 2);
  assert.strictEqual(prop.mock.accesses[1].type, 'set');
  assert.strictEqual(prop.mock.accesses[1].value, 200);

  prop.mock.restore();
  assert.strictEqual(obj.foo, 42);
}); copy

mock.reset()

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

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

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

mock.restoreAll()

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

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

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

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

Эта функция является синтаксическим сокращением для 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 <Object> Необязательные параметры конфигурации для включения имитации таймеров. Поддерживаются следующие свойства:
    • apis <Array> Необязательный массив, содержащий таймеры для имитации. В настоящее время поддерживаются следующие значения таймеров: 'setInterval', 'setTimeout', 'setImmediate' и 'Date'. По умолчанию: ['setInterval', 'setTimeout', 'setImmediate', 'Date']. Если массив не указан, по умолчанию будут имитироваться все API, связанные со временем ('setInterval', 'clearInterval', 'setTimeout', 'clearTimeout', 'setImmediate', 'clearImmediate' и 'Date').
    • now <number> | <Date> Необязательное число или объект Date, представляющий начальное время (в миллисекундах), которое будет использоваться в качестве значения для Date.now(). По умолчанию: 0.

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

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

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

Модули JavaScript
import { mock } from 'node:test';
mock.timers.enable({ apis: ['setInterval'] });
CommonJS
const { mock } = require('node:test');
mock.timers.enable({ apis: ['setInterval'] });

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

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

Модули JavaScript
import { mock } from 'node:test';
mock.timers.enable({ apis: ['Date'], now: 1000 });
CommonJS
const { mock } = require('node:test');
mock.timers.enable({ apis: ['Date'], now: 1000 });

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

Модули JavaScript
import { mock } from 'node:test';
mock.timers.enable({ apis: ['Date'], now: new Date() });
CommonJS
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 контекста теста.

Модули JavaScript
import { mock } from 'node:test';
mock.timers.reset();
CommonJS
const { mock } = require('node:test');
mock.timers.reset();

timers[Symbol.dispose]()

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

timers.tick([milliseconds])

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

Перемещает время вперед для всех имитируемых таймеров.

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

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

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

Модули JavaScript
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);
});
CommonJS
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 можно вызывать много раз

Модули JavaScript
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);
});
CommonJS
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 также была включена имитация).

Модули JavaScript
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);
});
CommonJS
const assert = require('node:assert');
const { test } = require('node:test');

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

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

  // Advance in time
  context.mock.timers.tick(9999);
  assert.strictEqual(fn.mock.callCount(), 1);
  assert.strictEqual(Date.now(), 9999);
});
Использование функций очистки

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

Модули JavaScript
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);
});
CommonJS
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:

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

Модули JavaScript
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);
});
CommonJS
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:

Модули JavaScript
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));
  }
});
CommonJS
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 будет перемещен вперед до времени самого позднего таймера.

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

Модули JavaScript
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);
});
CommonJS
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.

Модули JavaScript
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);
});
CommonJS
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.

Модули JavaScript
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);
});
CommonJS
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 <Object>
    • summary <Object> Объект, содержащий отчет о покрытии кода.
      • files <Array> Массив отчетов о покрытии для отдельных файлов. Каждый отчет — это объект следующей структуры:
        • path <string> Абсолютный путь к файлу.
        • totalLineCount <number> Общее количество строк.
        • totalBranchCount <number> Общее количество ветвей.
        • totalFunctionCount <number> Общее количество функций.
        • coveredLineCount <number> Количество покрытых строк.
        • coveredBranchCount <number> Количество покрытых ветвей.
        • coveredFunctionCount <number> Количество покрытых функций.
        • coveredLinePercent <number> Процент покрытых строк.
        • coveredBranchPercent <number> Процент покрытых ветвей.
        • coveredFunctionPercent <number> Процент покрытых функций.
        • functions <Array> Массив функций, представляющий покрытие функций.
          • name <string> Имя функции.
          • line <number> Номер строки, в которой определена функция.
          • count <number> Количество вызовов функции.
        • branches <Array> Массив ветвей, представляющий покрытие ветвей.
          • line <number> Номер строки, в которой определена ветвь.
          • count <number> Количество прохождений по ветви.
        • lines <Array> Массив строк, представляющий номера строк и количество случаев их покрытия.
          • line <number> Номер строки.
          • count <number> Количество случаев покрытия строки.
      • thresholds <Object> Объект, содержащий информацию о том, достигнуты ли пороговые значения для каждого типа покрытия.
        • function <number> Пороговое значение покрытия функций.
        • branch <number> Пороговое значение покрытия ветвей.
        • line <number> Пороговое значение покрытия строк.
      • totals <Object> Объект, содержащий сводку покрытия для всех файлов.
        • totalLineCount <number> Общее количество строк.
        • totalBranchCount <number> Общее количество ветвей.
        • totalFunctionCount <number> Общее количество функций.
        • coveredLineCount <number> Количество покрытых строк.
        • coveredBranchCount <number> Количество покрытых ветвей.
        • coveredFunctionCount <number> Количество покрытых функций.
        • coveredLinePercent <number> Процент покрытых строк.
        • coveredBranchPercent <number> Процент покрытых ветвей.
        • coveredFunctionPercent <number> Процент покрытых функций.
      • workingDirectory <string> Рабочий каталог на момент начала сбора данных о покрытии кода. Это полезно для отображения относительных путей, если тесты изменили рабочий каталог процесса Node.js.
    • nesting <number> Уровень вложенности теста.

Генерируется, когда сбор данных о покрытии кода включен и все тесты завершены.

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

  • data <Object>
    • column <number> | <undefined> Номер столбца, в котором определен тест, или 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:dequeue'

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

Генерируется, когда тест извлекается из очереди непосредственно перед запуском. Не гарантируется, что это событие будет сгенерировано в том же порядке, в котором определены тесты. Соответствующее событие, упорядоченное по объявлению, — '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> Уровень вложенности теста.
    • level <string> Уровень серьезности диагностического сообщения. Возможные значения:
      • 'info': информационные сообщения.
      • 'warn': предупреждения.
      • 'error': ошибки.

Генерируется при вызове 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> Уровень вложенности теста.
    • type <string> Тип теста: 'suite' или 'test'.

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

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

  • data <Object>
    • column <number> | <undefined> Номер столбца, в котором определен тест, или undefined, если тест был запущен через REPL.
    • details <Object> Дополнительные метаданные выполнения.
      • duration_ms <number> Длительность теста в миллисекундах.
      • error <Error> Ошибка, оборачивающая ошибку, вызванную тестом.
        • 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:complete'.

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

  • data <Object>
    • column <number> | <undefined> Номер столбца, в котором определен тест, или undefined, если тест был запущен через REPL.
    • details <Object> Дополнительные метаданные выполнения.
      • duration_ms <number> Длительность теста в миллисекундах.
      • 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:complete'.

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

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

Генерируется после завершения всех под-тестов для данного теста. Гарантируется, что это событие будет генерироваться в том же порядке, в котором определены тесты.

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

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

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

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

  • data <Object>
    • file <string> Путь к файлу теста.
    • message <string> Сообщение, записанное в stderr.

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

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

  • data <Object>
    • file <string> Путь к файлу теста.
    • message <string> Сообщение, записанное в stdout.

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

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

  • data <Object>
    • counts <Object> Объект, содержащий количество результатов различных тестов.
      • cancelled <number> Общее количество отменённых тестов.
      • failed <number> Общее количество не пройденных тестов.
      • passed <number> Общее количество пройденных тестов.
      • skipped <number> Общее количество пропущенных тестов.
      • suites <number> Общее количество запущенных наборов тестов.
      • tests <number> Общее количество запущенных тестов, не включая наборы тестов.
      • todo <number> Общее количество тестов TODO.
      • topLevel <number> Общее количество тестов и наборов тестов верхнего уровня.
    • duration_ms <number> Длительность запуска тестов в миллисекундах.
    • file <string> | <undefined> Путь к файлу теста, для которого создана сводка. Если сводка относится к нескольким файлам, этому значению присваивается undefined.
    • success <boolean> Указывает, считается ли запуск тестов успешным. Если возникает какое-либо условие ошибки, например тест не пройден или пороговое значение покрытия не достигнуто, этому значению присваивается false.

Генерируется после завершения запуска тестов. Это событие содержит показатели завершённого запуска тестов и полезно для определения того, прошёл ли запуск успешно. Если используется изоляция на уровне процесса, для каждого файла тестов создаётся событие 'test:summary', а также итоговая сводка.

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

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

Класс: TestContext

История
Версия Изменения
v20.1.0, v18.17.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 <Function> | <AsyncFunction> Функция-хук. Первый аргумент этой функции — объект TestContext. Если хук использует обратные вызовы, функция обратного вызова передается в качестве второго аргумента. По умолчанию: Функция-заглушка.
  • options <Object> Параметры конфигурации хука. Поддерживаются следующие свойства:
    • signal <AbortSignal> Позволяет прервать выполняющийся хук.
    • timeout <number> Количество миллисекунд, по истечении которого выполнение хука завершится ошибкой. Если значение не указано, вложенные тесты наследуют его от родительского теста. По умолчанию: Infinity.

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

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

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

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

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

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

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

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

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

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

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

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

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

context.assert

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

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

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

Эта функция сериализует value и записывает его в файл, указанный в path.

test('snapshot test with default serialization', (t) => {
  t.assert.fileSnapshot({ value1: 1, value2: 2 }, './snapshots/snapshot.json');
}); copy

Эта функция отличается от context.assert.snapshot() следующим:

  • Путь к файлу снимка явно указывается пользователем.
  • Каждый файл снимка содержит не более одного значения снимка.
  • Тестовый исполнитель не выполняет дополнительное экранирование.

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

context.assert.snapshot(value[, options])
Добавлено в: v22.3.0
  • value <any> Значение, которое нужно сериализовать в строку. Если Node.js был запущен с флагом --test-update-snapshots, сериализованное значение записывается в файл снимка. В противном случае сериализованное значение сравнивается с соответствующим значением в существующем файле снимка.
  • options <Object> Необязательные параметры конфигурации. Поддерживаются следующие свойства:
    • serializers <Array> Массив синхронных функций, используемых для сериализации 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 <string> Сообщение для вывода.

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

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

context.filePath

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

Абсолютный путь к файлу теста, в котором был создан текущий тест. Если файл теста импортирует дополнительные модули, создающие тесты, импортированные тесты будут возвращать путь к корневому файлу теста.

context.fullName

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

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

context.name

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

Имя теста.

context.plan(count[,options])

История
Версия Изменения
v23.9.0, v22.15.0

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

v23.4.0, v22.13.0

Эта функция больше не является экспериментальной.

v22.2.0, v20.15.0

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

  • count <number> Количество проверок и вложенных тестов, которые должны быть выполнены.
  • options <Object> Дополнительные параметры плана.
    • wait <boolean> | <number> Время ожидания для плана:
      • Если значение равно true, план бесконечно ожидает выполнения всех проверок и вложенных тестов.
      • Если значение равно false, план немедленно выполняет проверку после завершения тестовой функции, не дожидаясь выполнения ожидающих проверок или вложенных тестов. Проверки или вложенные тесты, завершившиеся после этой проверки, не будут учитываться в плане.
      • Если указано число, оно задает максимальное время ожидания в миллисекундах до истечения тайм-аута при ожидании соответствия ожидаемым проверкам и вложенным тестам. По истечении тайм-аута тест завершится ошибкой. По умолчанию: false.

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

Примечание. Чтобы отслеживать проверки, необходимо использовать 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

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

test('plan with wait: 2000 waits for async assertions', (t) => {
  t.plan(1, { wait: 2000 }); // Waits for up to 2 seconds for the assertion to complete.

  const asyncActivity = () => {
    setTimeout(() => {
      t.assert.ok(true, 'Async assertion completed within the wait time');
    }, 1000); // Completes after 1 second, within the 2-second wait time.
  };

  asyncActivity(); // The test will pass because the assertion is completed in time.
}); copy

Примечание. Если указан тайм-аут wait, его отсчет начинается только после завершения выполнения тестовой функции.

context.runOnly(shouldRunOnlyTests)

Добавлено в: v18.0.0, v16.17.0
  • shouldRunOnlyTests <boolean> Нужно ли запускать тесты only.

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

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

Добавлено в: 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])

Добавлено в: 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: 1 },
    (t) => {
      t.assert.ok('some relevant assertion here');
    },
  );
}); copy

context.waitFor(condition[, options])

Добавлено в: v22.14.0
  • condition <Function> | <AsyncFunction> Функция проверки, периодически вызываемая до успешного завершения или истечения заданного времени ожидания опроса. Успешным считается завершение без выбрасывания исключения или отклонения промиса. Эта функция не принимает аргументов и может возвращать любое значение.
  • options <Object> Необязательный объект конфигурации операции опроса. Поддерживаются следующие свойства:
    • interval <number> Количество миллисекунд ожидания после неудачного вызова condition перед следующей попыткой. По умолчанию: 50.
    • timeout <number> Тайм-аут опроса в миллисекундах. Если condition не завершится успешно до его истечения, произойдет ошибка. По умолчанию: 1000.
  • Возвращает: <Promise> Выполняется со значением, возвращенным condition.

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

Класс: SuiteContext

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

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

context.filePath

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

Абсолютный путь к файлу теста, в котором был создан текущий набор тестов. Если файл теста импортирует дополнительные модули, создающие наборы тестов, импортированные наборы будут возвращать путь к корневому файлу теста.

context.name

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

Имя набора тестов.

context.signal

Добавлено в: v18.7.0, v16.17.0
  • Тип: <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/dist/latest-v22.x/docs/api/test.html

Spec-Zone.ru

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