Jest предоставляет функцию test.each, которая позволяет
удобно проводить параметризированные тесты. Это особенно полезно, когда
необходимо протестировать одну и ту же логику с разными входными
данными, минимизируя дублирование кода.
test.eachФункция test.each принимает два основных параметра:
массив данных и сам тест, который будет выполнен для каждого элемента из
этого массива. Каждый элемент массива передаётся в качестве аргумента в
тестовую функцию, что позволяет легко повторно запускать один и тот же
тест с различными входными данными.
Пример базового использования:
test.each([
[1, 2, 3],
[2, 3, 5],
[3, 4, 7]
])('сложение %i и %i даёт %i', (a, b, expected) => {
expect(a + b).toBe(expected);
});
В этом примере массив данных состоит из подмассивов, где каждый подмассив содержит два числа и ожидаемый результат их сложения. Каждый набор данных будет протестирован с выводом сообщения, в котором отображается текущий набор чисел.
test.eachДанные для test.each могут быть представлены в различных
форматах:
Массив массивов: Каждый подмассив содержит параметры для теста.
test.each([
[a, b, result],
[a2, b2, result2],
...
])('%i + %i = %i', (a, b, result) => {
expect(a + b).toBe(result);
});Массив объектов: Если входные данные сложнее, можно использовать массив объектов с именованными полями.
test.each([
{ a: 1, b: 2, expected: 3 },
{ a: 2, b: 3, expected: 5 },
{ a: 3, b: 4, expected: 7 }
])('сложение %i и %i даёт %i', ({ a, b, expected }) => {
expect(a + b).toBe(expected);
});Шаблон строк: Для использования строк в качестве шаблонов, можно указать параметры через шаблонные строки.
test.each([
[1, 2, 3],
[2, 3, 5]
])('сложение %i + %i должно быть равно %i', (a, b, expected) => {
expect(a + b).toBe(expected);
});Если тесты асинхронные, то с помощью async/await можно
легко реализовать асинхронную проверку:
test.each([
[1, 2, 3],
[2, 3, 5]
])('сложение %i и %i даёт %i', async (a, b, expected) => {
const result = await someAsyncFunction(a, b);
expect(result).toBe(expected);
});
test.each полезным для сложных тестов?Параметризированные тесты позволяют тестировать функции с множеством различных входных данных, что значительно сокращает количество повторений кода и улучшает читаемость тестов. Особенно это полезно при тестировании математических операций, валидации данных, преобразования значений и других похожих сценариев.
Можно также передавать динамические значения в
test.each, например, результат выполнения функции. В таких
случаях стоит быть осторожным, так как вызов функции будет происходить
каждый раз перед запуском теста:
const generateTestCases = () => [
[1, 2, 3],
[2, 3, 5],
[3, 4, 7]
];
test.each(generateTestCases())('сложение %i и %i даёт %i', (a, b, expected) => {
expect(a + b).toBe(expected);
});
Здесь generateTestCases возвращает массив, который
используется в test.each. Это позволяет гибко подходить к
созданию тестов с переменными данными.
Читаемость тестов: Использование
test.each делает тесты компактными, но важно следить за их
читаемостью. Выводимые строки, содержащие параметризированные данные,
должны быть ясными и понятными.
Уникальные имена тестов: Шаблоны строк в
test.each позволяют создавать уникальные имена тестов, что
упрощает их идентификацию в отчёте о тестах.
Пример:
test.each([
[1, 2, 3],
[2, 3, 5]
])('при сложении %i и %i результат должен быть %i', (a, b, expected) => {
expect(a + b).toBe(expected);
});Тесты с большим количеством данных: Если наборы
данных очень большие, можно использовать test.each с
сокращениями или слайсами массивов, чтобы не перегружать тесты.
В процессе работы с test.each могут возникать ошибки,
связанные с несоответствием данных. Если результат теста не совпадает с
ожидаемым, важно проверять саму формулировку теста и входные данные.
test.each можно комбинировать с другими возможностями
Jest, такими как beforeEach, afterEach, или
mock-функциями. Это позволяет создавать гибкие и мощные тестовые
сценарии, которые могут включать подготовку и очистку данных, а также
проверку взаимодействий с внешними зависимостями.
Пример:
let mockFunction;
beforeEach(() => {
mockFunction = jest.fn();
});
test.each([
[1, 2, 3],
[2, 3, 5]
])('сложение %i и %i даёт %i', (a, b, expected) => {
mockFunction(a, b);
expect(mockFunction).toHaveBeenCalledWith(a, b);
expect(a + b).toBe(expected);
});
Здесь мы подготавливаем mockFunction с помощью
beforeEach и проверяем, что она вызывается с ожидаемыми
параметрами.
Использование test.each значительно упрощает написание
тестов, которые требуют повторного использования одной и той же логики с
разными данными. Это мощный инструмент для параметризированного
тестирования, который позволяет повысить читаемость и поддерживаемость
тестов, а также минимизировать дублирование кода.