Skip to content
Vitest 3
Main Navigation Руководство & APIКонфигурацияРежим браузераРасширенный API
3.2.0
2.1.9
1.6.1
0.34.6

Русский

English
简体中文
繁體中文
Español
Français
Português – Brasil
Deutsch
日本語
한국어
Italiano
Polski
Türkçe
čeština
magyar

Русский

English
简体中文
繁體中文
Español
Français
Português – Brasil
Deutsch
日本語
한국어
Italiano
Polski
Türkçe
čeština
magyar

Внешний вид

Sidebar Navigation

Введение

Почему Vitest

Начало работы

Возможности

Настройка Vitest

API

Справочник по API тестирования

Мок-функции

Vi

expect

expectTypeOf

assert

assertType

Руководство

Интерфейс командной строки

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

Тестовые проекты

Средства отчётности

Покрытие кода

Снапшот-тестирование

Мокирование

Параллелизм

Тестирование типов

Vitest UI

Тестирование в исходном коде

Контекст теста

Аннотации тестов

Среда тестирования

Расширение матчеров

Интеграции с IDE

Отладка

Распространенные ошибки

Руководство по миграции

Миграция на Vitest 3.0

Миграция с Jest

Производительность

Профилирование производительности тестов

Улучшение производительности

Режим браузера

Расширенный API

Сравнение с другими тестовыми раннерами

Содержание страницы

Справочник по API тестирования ​

Следующие типы используются в приведенных ниже сигнатурах типов:

ts
type Awaitable<T> = T | PromiseLike<T>;
type TestFunction = () => Awaitable<void>;

interface TestOptions {
  /**
   * Тест завершится с ошибкой, если его выполнение превысит установленный таймаут.
   */
  timeout?: number;
  /**
   * Будет повторять тест указанное количество раз при неудачном выполнении.
   *
   * @default 0
   */
  retry?: number;
  /**
   * Повторит тот же тест несколько раз, даже если он каждый раз завершается ошибкой.
   * Если включена опция "retry" и тест завершается ошибкой, каждая попытка будет задействована в каждом цикле.
   * Полезно для отладки нерегулярных сбоев.
   *
   * @default 0
   */
  repeats?: number;
}

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

TIP

В Jest TestFunction также может быть типа (done: DoneCallback) => void. Если используется эта форма, тест не будет завершен, пока не будет вызван done. Того же можно достичь, используя async функцию; см. раздел «Обратный вызов done» в руководстве по миграции.

Вы можете задать опции, используя цепочечный вызов свойств функции:

ts
import { test } from 'vitest';

test.skip('пропущенный тест', () => {
  // некоторая логика, которая сейчас приводит к сбою
});

test.concurrent.skip('пропущенный параллельный тест', () => {
  // некоторая логика, которая сейчас приводит к сбою
});

Но вы также можете предоставить объект в качестве второго аргумента:

ts
import { test } from 'vitest';

test('пропущенный тест', { skip: true }, () => {
  // некоторая логика, которая сейчас приводит к сбою
});

test('пропущенный параллельный тест', { skip: true, concurrent: true }, () => {
  // некоторая логика, которая сейчас приводит к сбою
});

Оба варианта работают абсолютно одинаково. Выбор одного из них — чисто стилистический.

Обратите внимание: если таймаут указан в качестве последнего аргумента, вы больше не сможете использовать опции:

ts
import { test } from 'vitest';

// ✅ это работает
test.skip('тяжелый тест', () => {
  // ...
}, 10_000);

// ❌ это не работает
test(
  'тяжелый тест',
  { skip: true },
  () => {
    // ...
  },
  10_000
);

Однако вы можете указать таймаут внутри объекта:

ts
import { test } from 'vitest';

// ✅ это работает
test('тяжелый тест', { skip: true, timeout: 10_000 }, () => {
  // ...
});

test ​

  • Псевдоним: it

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

Опционально вы можете указать таймаут (в миллисекундах), по истечении которого тест будет завершен. По умолчанию установлено 5 секунд; это значение можно настроить глобально с помощью testTimeout.

ts
import { expect, test } from 'vitest';

test('должен работать как ожидалось', () => {
  expect(Math.sqrt(4)).toBe(2);
});

test.extend ​

  • Псевдоним: it.extend

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

ts
import { expect, test } from 'vitest';

const todos = [];
const archive = [];

const myTest = test.extend({
  todos: async ({ task }, use) => {
    todos.push(1, 2, 3);
    await use(todos);
    todos.length = 0;
  },
  archive,
});

myTest('добавить элемент', ({ todos }) => {
  expect(todos.length).toBe(3);

  todos.push(4);
  expect(todos.length).toBe(4);
});

test.skip ​

  • Псевдоним: it.skip

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

ts
import { assert, test } from 'vitest';

test.skip('пропущенный тест', () => {
  // Тест пропущен, и это не вызывает ошибок
  assert.equal(Math.sqrt(4), 3);
});

Вы также можете пропустить тест, динамически вызвав skip в его контексте:

ts
import { assert, test } from 'vitest';

test('пропущенный тест', context => {
  context.skip();
  // Тест пропущен, и это не вызывает ошибок
  assert.equal(Math.sqrt(4), 3);
});

Начиная с Vitest 3.1, если условие не определено, вы можете передать его методу skip в качестве первого аргумента:

ts
import { assert, test } from 'vitest';

test('пропущенный тест', context => {
  context.skip(Math.random() < 0.5, 'необязательное сообщение');
  // Тест пропущен, и это не вызывает ошибок
  assert.equal(Math.sqrt(4), 3);
});

test.skipIf ​

  • Псевдоним: it.skipIf

В некоторых случаях тесты могут запускаться несколько раз в разных средах, при этом некоторые из них могут быть специфичными для конкретной среды. Вместо того чтобы оборачивать код теста в if, вы можете использовать test.skipIf для пропуска теста, если условие выполняется.

ts
import { assert, test } from 'vitest';

const isDev = process.env.NODE_ENV === 'development';

test.skipIf(isDev)('тест, запускаемый только в продакшене', () => {
  // этот тест запускается только в продакшене
});

WARNING

Вы не можете использовать этот синтаксис при использовании Vitest в качестве проверки типов.

test.runIf ​

  • Псевдоним: it.runIf

Противоположность test.skipIf.

ts
import { assert, test } from 'vitest';

const isDev = process.env.NODE_ENV === 'development';

test.runIf(isDev)('тест, запускаемый только в разработке', () => {
  // этот тест запускается только в разработке
});

WARNING

Вы не можете использовать этот синтаксис при использовании Vitest в качестве проверки типов.

test.only ​

  • Псевдоним: it.only

Используйте test.only для выполнения только определенных тестов в данном наборе. Это полезно при отладке.

Опционально вы можете указать таймаут (в миллисекундах), по истечении которого тест будет завершен. По умолчанию установлено 5 секунд; это значение можно настроить глобально с помощью testTimeout.

ts
import { assert, test } from 'vitest';

test.only('тест', () => {
  // Запускается только этот тест (и другие, помеченные `only`)
  assert.equal(Math.sqrt(4), 2);
});

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

Для этого запустите vitest с указанием конкретного файла, содержащего интересующие тесты.

# vitest interesting.test.ts

test.concurrent ​

  • Псевдоним: it.concurrent

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

ts
import { describe, test } from 'vitest';

// Два теста, помеченные как concurrent, будут выполняться параллельно
describe('набор', () => {
  test('последовательный тест', async () => {
    /* ... */
  });
  test.concurrent('параллельный тест 1', async () => {
    /* ... */
  });
  test.concurrent('параллельный тест 2', async () => {
    /* ... */
  });
});

test.skip, test.only и test.todo работают с параллельными тестами. Все следующие комбинации допустимы:

ts
test.concurrent(/* ... */);
test.skip.concurrent(/* ... */); // или test.concurrent.skip(/* ... */)
test.only.concurrent(/* ... */); // или test.concurrent.only(/* ... */)
test.todo.concurrent(/* ... */); // или test.concurrent.todo(/* ... */)

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

ts
test.concurrent('тест 1', async ({ expect }) => {
  expect(foo).toMatchSnapshot();
});
test.concurrent('тест 2', async ({ expect }) => {
  expect(foo).toMatchSnapshot();
});

WARNING

Вы не можете использовать этот синтаксис при использовании Vitest в качестве проверки типов.

test.sequential ​

  • Псевдоним: it.sequential

test.sequential помечает тест как последовательный. Это полезно, если вы хотите запускать тесты последовательно внутри describe.concurrent или с опцией командной строки --sequence.concurrent.

ts
import { describe, test } from 'vitest';

// с опцией конфигурации { sequence: { concurrent: true } }
test('параллельный тест 1', async () => {
  /* ... */
});
test('параллельный тест 2', async () => {
  /* ... */
});

test.sequential('последовательный тест 1', async () => {
  /* ... */
});
test.sequential('последовательный тест 2', async () => {
  /* ... */
});

// внутри параллельного набора
describe.concurrent('набор', () => {
  test('параллельный тест 1', async () => {
    /* ... */
  });
  test('параллельный тест 2', async () => {
    /* ... */
  });

  test.sequential('последовательный тест 1', async () => {
    /* ... */
  });
  test.sequential('последовательный тест 2', async () => {
    /* ... */
  });
});

test.todo ​

  • Псевдоним: it.todo

Используйте test.todo для обозначения тестов, которые нужно реализовать позже. Запись будет отображена в отчете, чтобы вы знали, сколько тестов вам еще нужно реализовать.

ts
// Запись будет отображена в отчете для этого теста
test.todo('нереализованный тест');

test.fails ​

  • Псевдоним: it.fails

Используйте test.fails, чтобы явно указать, что ожидается сбой утверждения.

ts
import { expect, test } from 'vitest';

function myAsyncFunc() {
  return new Promise(resolve => resolve(1));
}
test.fails('тест с ошибкой', async () => {
  await expect(myAsyncFunc()).rejects.toBe(1);
});

WARNING

Вы не можете использовать этот синтаксис при использовании Vitest в качестве проверки типов.

test.each ​

  • Псевдоним: it.each

TIP

Хотя test.each предусмотрен для совместимости с Jest, Vitest также имеет test.for с дополнительной функцией для интеграции TestContext.

Используйте test.each, когда вам нужно запустить один и тот же тест с разными переменными. Вы можете внедрять параметры с форматированием printf в имя теста, следуя порядку параметров тестовой функции.

  • %s: строка
  • %d: число
  • %i: целое число
  • %f: число с плавающей запятой
  • %j: json
  • %o: объект
  • %#: 0-индексированный номер тестового случая
  • %$: 1-индексированный номер тестового случая
  • %%: одиночный знак процента ('%')
ts
import { expect, test } from 'vitest';

test.each([
  [1, 1, 2],
  [1, 2, 3],
  [2, 1, 3],
])('add(%i, %i) -> %i', (a, b, expected) => {
  expect(a + b).toBe(expected);
});

// это вернет
// ✓ add(1, 1) -> 2
// ✓ add(1, 2) -> 3
// ✓ add(2, 1) -> 3

Вы также можете получить доступ к свойствам объекта и элементам массива, используя префикс $:

ts
test.each([
  { a: 1, b: 1, expected: 2 },
  { a: 1, b: 2, expected: 3 },
  { a: 2, b: 1, expected: 3 },
])('add($a, $b) -> $expected', ({ a, b, expected }) => {
  expect(a + b).toBe(expected);
});

// это вернет
// ✓ add(1, 1) -> 2
// ✓ add(1, 2) -> 3
// ✓ add(2, 1) -> 3

test.each([
  [1, 1, 2],
  [1, 2, 3],
  [2, 1, 3],
])('add($0, $1) -> $2', (a, b, expected) => {
  expect(a + b).toBe(expected);
});

// это вернет
// ✓ add(1, 1) -> 2
// ✓ add(1, 2) -> 3
// ✓ add(2, 1) -> 3

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

ts
test.each`
  a             | b      | expected
  ${{ val: 1 }} | ${'b'} | ${'1b'}
  ${{ val: 2 }} | ${'b'} | ${'2b'}
  ${{ val: 3 }} | ${'b'} | ${'3b'}
`('add($a.val, $b) -> $expected', ({ a, b, expected }) => {
  expect(a.val + b).toBe(expected);
});

// это вернет
// ✓ add(1, b) -> 1b
// ✓ add(2, b) -> 2b
// ✓ add(3, b) -> 3b

Начиная с Vitest 0.25.3, вы также можете использовать табличные шаблонные строки.

  • Первая строка должна содержать имена столбцов, разделенные символом |;
  • Одна или несколько последующих строк данных предоставляются в виде выражений шаблонных литералов с использованием синтаксиса ${value}.
ts
import { expect, test } from 'vitest';

test.each`
  a             | b      | expected
  ${1}          | ${1}   | ${2}
  ${'a'}        | ${'b'} | ${'ab'}
  ${[]}         | ${'b'} | ${'b'}
  ${{}}         | ${'b'} | ${'[object Object]b'}
  ${{ asd: 1 }} | ${'b'} | ${'[object Object]b'}
`('возвращает $expected, когда $a добавляется $b', ({ a, b, expected }) => {
  expect(a + b).toBe(expected);
});

TIP

Vitest обрабатывает $values методом Chai format. Если значение слишком сильно сокращено, вы можете увеличить chaiConfig.truncateThreshold в вашем файле конфигурации.

WARNING

Вы не можете использовать этот синтаксис при использовании Vitest в качестве проверки типов.

test.for ​

  • Псевдоним: it.for

Альтернатива test.each для предоставления TestContext.

Различие с test.each заключается в способе предоставления массивов в аргументах. Аргументы, не являющиеся массивами, для test.for (включая использование шаблонных строк) работают точно так же, как для test.each.

ts
// `each` разворачивает массивы
test.each([
  [1, 1, 2],
  [1, 2, 3],
  [2, 1, 3],
])('add(%i, %i) -> %i', (a, b, expected) => { 
  expect(a + b).toBe(expected);
});

// `for` не разворачивает массивы (обратите внимание на квадратные скобки вокруг аргументов)
test.for([
  [1, 1, 2],
  [1, 2, 3],
  [2, 1, 3],
])('add(%i, %i) -> %i', ([a, b, expected]) => { 
  expect(a + b).toBe(expected);
});

Второй аргумент — это TestContext и может использоваться для параллельных снимков, например:

ts
test.concurrent.for([
  [1, 1],
  [1, 2],
  [2, 1],
])('add(%i, %i)', ([a, b], { expect }) => {
  expect(a + b).matchSnapshot();
});

bench ​

  • Тип: (name: string | Function, fn: BenchFunction, options?: BenchOptions) => void

bench определяет бенчмарк. В контексте Vitest, бенчмарк — это функция, которая определяет серию операций. Vitest запускает эту функцию несколько раз для отображения различных результатов производительности.

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

ts
import { bench } from 'vitest';

bench(
  'обычная сортировка',
  () => {
    const x = [1, 5, 4, 2, 3];
    x.sort((a, b) => {
      return a - b;
    });
  },
  { time: 1000 }
);
ts
export interface Options {
  /**
   * время выполнения задачи бенчмарка (миллисекунды)
   * @default 500
   */
  time?: number;

  /**
   * количество раз, которое задача должна быть выполнена, независимо от истечения опции time
   * @default 10
   */
  iterations?: number;

  /**
   * функция для получения текущей временной метки в миллисекундах
   */
  now?: () => number;

  /**
   * AbortSignal для прерывания бенчмарка
   */
  signal?: AbortSignal;

  /**
   * Выбрасывать исключение, если задача завершается ошибкой (события не будут работать, если это значение true)
   */
  throws?: boolean;

  /**
   * время прогрева (миллисекунды)
   * @default 100ms
   */
  warmupTime?: number;

  /**
   * итерации прогрева
   * @default 5
   */
  warmupIterations?: number;

  /**
   * функция настройки, запускаемая перед каждой задачей бенчмарка (циклом)
   */
  setup?: Hook;

  /**
   * функция очистки, запускаемая после каждой задачи бенчмарка (цикла)
   */
  teardown?: Hook;
}

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

  name                      hz     min     max    mean     p75     p99    p995    p999     rme  samples
· обычная сортировка  6,526,368.12  0.0001  0.3638  0.0002  0.0002  0.0002  0.0002  0.0004  ±1.41%   652638
ts
export interface TaskResult {
  /*
   * последняя ошибка, возникшая во время выполнения задачи
   */
  error?: unknown;

  /**
   * Время выполнения задачи бенчмарка (цикла) в миллисекундах.
   */
  totalTime: number;

  /**
   * минимальное значение в выборках
   */
  min: number;
  /**
   * максимальное значение в выборках
   */
  max: number;

  /**
   * количество операций в секунду
   */
  hz: number;

  /**
   * сколько времени занимает каждая операция (мс)
   */
  period: number;

  /**
   * выборки времени каждой итерации задачи (мс)
   */
  samples: number[];

  /**
   * среднее значение выборок (оценка среднего значения генеральной совокупности)
   */
  mean: number;

  /**
   * дисперсия выборок (оценка дисперсии генеральной совокупности)
   */
  variance: number;

  /**
   * стандартное отклонение выборок (оценка стандартного отклонения генеральной совокупности)
   */
  sd: number;

  /**
   * стандартная ошибка среднего (также известная как стандартное отклонение выборочного распределения среднего значения выборки)
   */
  sem: number;

  /**
   * степени свободы
   */
  df: number;

  /**
   * критическое значение выборки
   */
  critical: number;

  /**
   * погрешность
   */
  moe: number;

  /**
   * относительная погрешность
   */
  rme: number;

  /**
   * медианное абсолютное отклонение
   */
  mad: number;

  /**
   * 50-й/медианный перцентиль
   */
  p50: number;

  /**
   * 75-й перцентиль
   */
  p75: number;

  /**
   * 99-й перцентиль
   */
  p99: number;

  /**
   * 995-й перцентиль
   */
  p995: number;

  /**
   * 999-й перцентиль
   */
  p999: number;
}

bench.skip ​

  • Тип: (name: string | Function, fn: BenchFunction, options?: BenchOptions) => void

Вы можете использовать синтаксис bench.skip для пропуска выполнения определенных бенчмарков.

ts
import { bench } from 'vitest';

bench.skip('обычная сортировка', () => {
  const x = [1, 5, 4, 2, 3];
  x.sort((a, b) => {
    return a - b;
  });
});

bench.only ​

  • Тип: (name: string | Function, fn: BenchFunction, options?: BenchOptions) => void

Используйте bench.only для запуска только определенных бенчмарков в данном наборе. Это полезно при отладке.

ts
import { bench } from 'vitest';

bench.only('обычная сортировка', () => {
  const x = [1, 5, 4, 2, 3];
  x.sort((a, b) => {
    return a - b;
  });
});

bench.todo ​

  • Тип: (name: string | Function) => void

Используйте bench.todo для заглушки бенчмарков, которые будут реализованы позже.

ts
import { bench } from 'vitest';

bench.todo('нереализованный тест');

describe ​

Когда вы используете test или bench на верхнем уровне файла, они автоматически включаются в неявный набор. Используя describe, вы можете определить новый набор в текущем контексте, который будет содержать связанные тесты, бенчмарки и другие вложенные наборы. Набор позволяет организовать тесты и бенчмарки для получения более понятных отчетов.

ts
// basic.spec.ts
// организация тестов

import { describe, expect, test } from 'vitest';

const person = {
  isActive: true,
  age: 32,
};

describe('человек', () => {
  test('человек определён', () => {
    expect(person).toBeDefined();
  });

  test('активен', () => {
    expect(person.isActive).toBeTruthy();
  });

  test('ограничение по возрасту', () => {
    expect(person.age).toBeLessThanOrEqual(32);
  });
});
ts
// basic.bench.ts
// организация бенчмарков

import { bench, describe } from 'vitest';

describe('сортировка', () => {
  bench('обычная', () => {
    const x = [1, 5, 4, 2, 3];
    x.sort((a, b) => {
      return a - b;
    });
  });

  bench('обратная сортировка', () => {
    const x = [1, 5, 4, 2, 3];
    x.reverse().sort((a, b) => {
      return a - b;
    });
  });
});

Вы также можете вкладывать блоки describe, если у вас есть иерархия тестов или бенчмарков:

ts
import { describe, expect, test } from 'vitest';

function numberToCurrency(value: number | string) {
  if (typeof value !== 'number') {
    throw new TypeError('Значение должно быть числом');
  }

  return value
    .toFixed(2)
    .toString()
    .replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}

describe('numberToCurrency', () => {
  describe('при недопустимом значении числа', () => {
    test('состоящем из нечисловых символов, должно вызывать ошибку', () => {
      expect(() => numberToCurrency('abc')).toThrowError();
    });
  });

  describe('при допустимом значении числа', () => {
    test('возвращает правильный формат валюты', () => {
      expect(numberToCurrency(10000)).toBe('10,000.00');
    });
  });
});

describe.skip ​

  • Псевдоним: suite.skip

Используйте describe.skip для пропуска выполнения определенного блока describe.

ts
import { assert, describe, test } from 'vitest';

describe.skip('пропущенный набор', () => {
  test('sqrt', () => {
    // Набор пропущен, ошибок нет
    assert.equal(Math.sqrt(4), 3);
  });
});

describe.skipIf ​

  • Псевдоним: suite.skipIf

В некоторых случаях вы можете запускать наборы несколько раз с разными средами, и некоторые из наборов могут быть специфичными для среды. Вместо того чтобы оборачивать набор в if, вы можете использовать describe.skipIf, чтобы пропустить набор, если условие истинно.

ts
import { describe, test } from 'vitest';

const isDev = process.env.NODE_ENV === 'development';

describe.skipIf(isDev)('набор тестов, запускаемый только в продакшене', () => {
  // этот набор тестов запускается только в продакшене
});

WARNING

Вы не можете использовать этот синтаксис при использовании Vitest в качестве проверки типов.

describe.runIf ​

  • Псевдоним: suite.runIf

Противоположность describe.skipIf.

ts
import { assert, describe, test } from 'vitest';

const isDev = process.env.NODE_ENV === 'development';

describe.runIf(isDev)('набор тестов, запускаемый только в разработке', () => {
  // этот набор тестов запускается только в разработке
});

WARNING

Вы не можете использовать этот синтаксис при использовании Vitest в качестве проверки типов.

describe.only ​

  • Тип: (name: string | Function, fn: TestFunction, options?: number | TestOptions) => void

Используйте describe.only для запуска только определенных наборов.

ts
import { assert, describe, test } from 'vitest';

// Запускается только этот набор (и другие, помеченные `only`)
describe.only('набор', () => {
  test('sqrt', () => {
    assert.equal(Math.sqrt(4), 3);
  });
});

describe('другой набор', () => {
  // ... будет пропущен
});

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

Для этого запустите vitest с указанием конкретного файла, содержащего интересующие тесты.

# vitest interesting.test.ts

describe.concurrent ​

  • Псевдоним: suite.concurrent

describe.concurrent запускает все вложенные наборы и тесты параллельно.

ts
import { describe, test } from 'vitest';

// Все наборы и тесты в этом наборе будут выполняться параллельно
describe.concurrent('набор', () => {
  test('параллельный тест 1', async () => {
    /* ... */
  });
  describe('параллельный набор 2', async () => {
    test('параллельный внутренний тест 1', async () => {
      /* ... */
    });
    test('параллельный внутренний тест 2', async () => {
      /* ... */
    });
  });
  test.concurrent('параллельный тест 3', async () => {
    /* ... */
  });
});

.skip, .only и .todo работают с параллельными наборами. Все следующие комбинации допустимы:

ts
describe.concurrent(/* ... */);
describe.skip.concurrent(/* ... */); // или describe.concurrent.skip(/* ... */)
describe.only.concurrent(/* ... */); // или describe.concurrent.only(/* ... */)
describe.todo.concurrent(/* ... */); // или describe.concurrent.todo(/* ... */)

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

ts
describe.concurrent('набор', () => {
  test('параллельный тест 1', async ({ expect }) => {
    expect(foo).toMatchSnapshot();
  });
  test('параллельный тест 2', async ({ expect }) => {
    expect(foo).toMatchSnapshot();
  });
});

WARNING

Вы не можете использовать этот синтаксис при использовании Vitest в качестве проверки типов.

describe.sequential ​

  • Псевдоним: suite.sequential

describe.sequential помечает каждый тест в наборе как последовательный. Это полезно, если вы хотите запускать тесты последовательно внутри describe.concurrent или с опцией командной строки --sequence.concurrent.

ts
import { describe, test } from 'vitest';

describe.concurrent('suite', () => {
  test('параллельный тест 1', async () => {
    /* ... */
  });
  test('параллельный тест 2', async () => {
    /* ... */
  });

  describe.sequential('', () => {
    test('последовательный тест 1', async () => {
      /* ... */
    });
    test('последовательный тест 2', async () => {
      /* ... */
    });
  });
});

describe.shuffle ​

  • Псевдоним: suite.shuffle

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

ts
import { describe, test } from 'vitest';

// или describe('набор', { shuffle: true }, ...)
describe.shuffle('набор', () => {
  test('случайный тест 1', async () => {
    /* ... */
  });
  test('случайный тест 2', async () => {
    /* ... */
  });
  test('случайный тест 3', async () => {
    /* ... */
  });

  // `shuffle` является наследуемым
  describe('все еще случайный', () => {
    test('случайный 4.1', async () => {
      /* ... */
    });
    test('случайный 4.2', async () => {
      /* ... */
    });
  });

  // отключить перемешивание для вложенных тестов
  describe('не случайный', { shuffle: false }, () => {
    test('по порядку 5.1', async () => {
      /* ... */
    });
    test('по порядку 5.2', async () => {
      /* ... */
    });
  });
});
// порядок зависит от опции sequence.seed в конфигурации (по умолчанию используется Date.now())

.skip, .only и .todo работают со случайными наборами.

WARNING

Вы не можете использовать этот синтаксис при использовании Vitest в качестве проверки типов.

describe.todo ​

  • Псевдоним: suite.todo

Используйте describe.todo для заглушки наборов, которые будут реализованы позже. Запись будет отображена в отчете, чтобы вы знали, сколько тестов вам еще нужно реализовать.

ts
// Запись будет отображена в отчете для этого набора
describe.todo('нереализованный набор');

describe.each ​

  • Псевдоним: suite.each

TIP

Хотя describe.each предусмотрен для совместимости с Jest, Vitest также имеет describe.for, который упрощает типы аргументов и соответствует test.for.

Используйте describe.each, если у вас есть более одного теста, зависящего от одних и тех же данных.

ts
import { describe, expect, test } from 'vitest';

describe.each([
  { a: 1, b: 1, expected: 2 },
  { a: 1, b: 2, expected: 3 },
  { a: 2, b: 1, expected: 3 },
])('описание объекта: add($a, $b)', ({ a, b, expected }) => {
  test(`возвращает ${expected}`, () => {
    expect(a + b).toBe(expected);
  });

  test(`возвращенное значение не должно превышать ${expected}`, () => {
    expect(a + b).not.toBeGreaterThan(expected);
  });

  test(`возвращенное значение не должно быть меньше ${expected}`, () => {
    expect(a + b).not.toBeLessThan(expected);
  });
});

Начиная с Vitest 0.25.3, вы также можете использовать табличные шаблонные строки.

  • Первая строка должна содержать имена столбцов, разделенные символом |;
  • Одна или несколько последующих строк данных предоставляются в виде выражений шаблонных литералов с использованием синтаксиса ${value}.
ts
import { describe, expect, test } from 'vitest';

describe.each`
  a             | b      | expected
  ${1}          | ${1}   | ${2}
  ${'a'}        | ${'b'} | ${'ab'}
  ${[]}         | ${'b'} | ${'b'}
  ${{}}         | ${'b'} | ${'[object Object]b'}
  ${{ asd: 1 }} | ${'b'} | ${'[object Object]b'}
`('описание шаблонной строки: add($a, $b)', ({ a, b, expected }) => {
  test(`возвращает ${expected}`, () => {
    expect(a + b).toBe(expected);
  });
});

WARNING

Вы не можете использовать этот синтаксис при использовании Vitest в качестве проверки типов.

describe.for ​

  • Псевдоним: suite.for

Различие с describe.each заключается в способе предоставления массива в аргументах. Другие аргументы, не являющиеся массивами (включая использование шаблонных строк), работают точно так же.

ts
// `each` разворачивает массив
describe.each([
  [1, 1, 2],
  [1, 2, 3],
  [2, 1, 3],
])('add(%i, %i) -> %i', (a, b, expected) => { 
  test('тест', () => {
    expect(a + b).toBe(expected);
  });
});

// `for` не разворачивает массив
describe.for([
  [1, 1, 2],
  [1, 2, 3],
  [2, 1, 3],
])('add(%i, %i) -> %i', ([a, b, expected]) => { 
  test('тест', () => {
    expect(a + b).toBe(expected);
  });
});

Настройка и очистка ​

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

beforeEach ​

  • Тип: beforeEach(fn: () => Awaitable<void>, timeout?: number)

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

Опционально вы можете передать таймаут (в миллисекундах), определяющий, сколько времени ждать до завершения. По умолчанию 5 секунд.

ts
import { beforeEach } from 'vitest';

beforeEach(async () => {
  // Очистить моки и добавить тестовые данные перед каждым запуском теста
  await stopMocking();
  await addUser({ name: 'John' });
});

Здесь beforeEach гарантирует добавление пользователя для каждого теста.

beforeEach также принимает необязательную функцию очистки (эквивалентную afterEach).

ts
import { beforeEach } from 'vitest';

beforeEach(async () => {
  // вызывается перед каждым запуском теста
  await prepareSomething();

  // функция очистки, вызываемая после каждого запуска теста
  return async () => {
    await resetSomething();
  };
});

afterEach ​

  • Тип: afterEach(fn: () => Awaitable<void>, timeout?: number)

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

Опционально вы можете указать таймаут (в миллисекундах), определяющий, сколько времени ждать до завершения. По умолчанию 5 секунд.

ts
import { afterEach } from 'vitest';

afterEach(async () => {
  await clearTestingData(); // очистить тестовые данные после каждого теста
});

Здесь afterEach гарантирует очистку тестовых данных после каждого запуска теста.

TIP

Vitest 1.3.0 добавил хук onTestFinished. Вы можете вызвать его во время выполнения теста для очистки состояния после завершения теста.

beforeAll ​

  • Тип: beforeAll(fn: () => Awaitable<void>, timeout?: number)

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

Опционально вы можете указать таймаут (в миллисекундах), определяющий, сколько времени ждать до завершения. По умолчанию 5 секунд.

ts
import { beforeAll } from 'vitest';

beforeAll(async () => {
  await startMocking(); // вызывается перед всеми тестами
});

Здесь beforeAll гарантирует настройку мок-данных перед запуском тестов.

beforeAll также принимает необязательную функцию очистки (эквивалентную afterAll).

ts
import { beforeAll } from 'vitest';

beforeAll(async () => {
  // вызывается перед всеми тестами
  await startMocking();

  // функция очистки, вызываемая после всех тестов
  return async () => {
    await stopMocking();
  };
});

afterAll ​

  • Тип: afterAll(fn: () => Awaitable<void>, timeout?: number)

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

Опционально вы можете указать таймаут (в миллисекундах), определяющий, сколько времени ждать до завершения. По умолчанию 5 секунд.

ts
import { afterAll } from 'vitest';

afterAll(async () => {
  await stopMocking(); // этот метод вызывается после всех тестов
});

Здесь afterAll гарантирует вызов метода stopMocking после выполнения всех тестов.

Хуки тестирования ​

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

WARNING

Эти хуки вызовут ошибку, если они будут вызваны вне тела теста.

onTestFinished ​

Этот хук всегда вызывается после завершения теста. Он вызывается после хуков afterEach, поскольку они могут влиять на результат теста. Он получает объект ExtendedContext, аналогично beforeEach и afterEach.

ts
import { onTestFinished, test } from 'vitest';

test('выполняет запрос', () => {
  const db = connectDb();
  onTestFinished(() => db.close());
  db.query('SELECT * FROM users');
});

WARNING

Если вы запускаете тесты параллельно, всегда используйте хук onTestFinished из контекста теста, поскольку Vitest не отслеживает параллельные тесты в глобальных хуках:

ts
import { test } from 'vitest';

test.concurrent('выполняет запрос', ({ onTestFinished }) => {
  const db = connectDb();
  onTestFinished(() => db.close());
  db.query('SELECT * FROM users');
});

Этот хук особенно полезен при создании переиспользуемой логики:

ts
// это может быть в отдельном файле
function getTestDb() {
  const db = connectMockedDb();
  onTestFinished(() => db.close());
  return db;
}

test('выполняет запрос пользователя', async () => {
  const db = getTestDb();
  expect(await db.query('SELECT * from users').perform()).toEqual([]);
});

test('выполняет запрос организации', async () => {
  const db = getTestDb();
  expect(await db.query('SELECT * from organizations').perform()).toEqual([]);
});

TIP

Этот хук всегда вызывается в обратном порядке и не зависит от опции sequence.hooks.

onTestFailed ​

Этот хук вызывается только после сбоя теста. Он вызывается после хуков afterEach, поскольку они могут влиять на результат теста. Он получает объект ExtendedContext, аналогично beforeEach и afterEach. Этот хук полезен при отладке.

ts
import { onTestFailed, test } from 'vitest';

test('выполняет запрос', () => {
  const db = connectDb();
  onTestFailed(({ task }) => {
    console.log(task.result.errors);
  });
  db.query('SELECT * FROM users');
});

WARNING

Если вы запускаете тесты параллельно, всегда используйте хук onTestFailed из контекста теста, поскольку Vitest не отслеживает параллельные тесты в глобальных хуках:

ts
import { test } from 'vitest';

test.concurrent('performs a query', ({ onTestFailed }) => {
  const db = connectDb();
  onTestFailed(({ task }) => {
    console.log(task.result.errors);
  });
  db.query('SELECT * FROM users');
});
Pager
Предыдущая страницаНастройка Vitest
Следующая страницаМок-функции

Выпущено на условиях лицензии MIT.

Авторские права (c) 2021-Present Vitest Team

https://vitest.dev/api/

Выпущено на условиях лицензии MIT.

Авторские права (c) 2021-Present Vitest Team