- PVSM.RU - https://www.pvsm.ru -
Здравствуй! Данное руководство является первой частью в запланированном цикле статей про такой замечательный фреймворк для тестирования как Jest. Материал будет полезен новичкам и тем, кто только знакомится с тестированием, и хотел бы изучить этот фреймворк. В первой части мы разберём: как начать работу с jest, как написать простой тест, и какие есть методы для сопоставления проверяемых значение с ожидаемыми. Кому интересно — добро пожаловать под кат!
Как указано на домашней странице проекта:
Jest — это восхитительная среда тестирования JavaScript с упором на простоту.
И действительно, Jest очень простой. Он не требует дополнительных настроек, легкий в понимании и применении, а так же имеет довольно хорошую документацию. Отлично подходит для проектов использующих Node, React, Angular, Vue, Babel, TypeScript и не только.
Также он имеет открытый исходный код и поддерживается компанией Facebook.
Для установки Jest в ваш проект выполните:
npm install --save-dev jest
Если вы используете yarn:
yarn add --dev jest
После установки можете обновить секцию scripts вашего package.json:
“scripts” : {
“test”: “jest”
}
С помощью такого простого вызова мы уже можем запустить наши тесты (на самом деле jest потребует существование хотя бы одного теста).
Также можно установить глобально (но так делать я бы не рекомендовал, так как по мне глобальная установка модулей является плохой практикой):
npm install jest --global
И соответственно для yarn:
yarn global add jestl
После этого вы можете использовать jest непосредственно из командной строки.
При помощи вызова команды jest --init в корне проекта, ответив на несколько вопросов, вы получите файл с настройками jest.config.js. Или можно добавить конфигурацию прямиком в ваш package.json. Для этого добавьте в корень json ключ «jest» и в соответствующем ему объекте можете добавлять необходимые вам настройки. Сами опции мы разберем позже. На данном этапе в этом нет необходимости, поскольку jest можно использовать «сходу», без дополнительных конфигураций.
Давайте создадим файл first.test.js и напишем наш первый тест:
//first.test.js
test('My first test', () => {
expect(Math.max(1, 5, 10)).toBe(10);
});
И запустим наши тесты с помощью npm run test или непосредственно командой jest (если он установлен глобально). После запуска мы увидим отчет о прохождении тестов.
<b>PASS</b> ./first.test.js
✓ My first test (1 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 0.618 s, estimated 1 s
Давайте «сломаем» наш тест и запустим jest повторно:
//first.test.js
test('My first test', () => {
expect(Math.max(1, 5, 10)).toBe(5);
});
Как мы видим, теперь наш тест не проходит проверки. Jest отображает подробную информацию о том, где возникла проблема, какой был ожидаемый результат, и что мы получили вместо него.
Теперь давайте разберём код самого теста. Функция test используется для создания нового теста. Она принимает три аргумента (в примере мы использовали вызов с двумя аргументами). Первый — строка с названием теста, его jest отобразит в отчете. Второй — функция, которая содержит логику нашего теста. Также можно использовать 3-й аргумент — таймаут. Он является не обязательным, а его значение по умолчанию составляет 5 секунд. Задаётся в миллисекундах. Этот параметр необходим когда мы работаем с асинхронным кодом и возвращаем из функции теста промис. Он указывает как долго jest должен ждать разрешения промиса. По истечению этого времени, если промис не был разрешен — jest будет считать тест не пройденным. Подробнее про работу с асинхронными вызовами будет в следующих частях. Также вместо test() можно использовать it(). Разницы между такими вызовами нету. it() это просто алиас на функцию test().
Внутри функции теста мы сначала вызываем expect(). Ему мы передаем значение, которое хотим проверить. В нашем случае, это результат вызова Math.max(1, 5, 10). expect() возвращает объект «обертку», у которой есть ряд методов для сопоставления полученного значения с ожидаемым. Один из таких методов мы и использовали — toBe.
Давайте разберем основные из этих методов:
test('toEqual with objects', () => {
expect({ foo: 'foo', subObject: { baz: 'baz' } })
.toEqual({ foo: 'foo', subObject: { baz: 'baz' } }); // Ок
expect({ foo: 'foo', subObject: { num: 0 } })
.toEqual({ foo: 'foo', subObject: { baz: 'baz' } }); // А вот так ошибка.
});
test('toEqual with arrays', () => {
expect([11, 19, 5]).toEqual([11, 19, 5]); // Ок
expect([11, 19, 5]).toEqual([11, 19]); // Ошибка
});
const arr = ['apple', 'orange', 'banana'];
expect(arr).toContain('banana');
expect(new Set(arr)).toContain('banana');
expect('apple, orange, banana').toContain('banana');
expect([{a: 1}, {b: 2}]).toContainEqual({a: 1});
expect([1, 2, 3, 4]).toHaveLength(4);
expect('foo').toHaveLength(3);
expect({ length: 1 }).toHaveLength(1);
const num = 0.1 + 0.2; // 0.30000000000000004
expect(num).toBeCloseTo(0.3);
expect(Math.PI).toBeCloseTo(3.14, 2);
expect('Banana').toMatch(/Ba/);
function funcWithError() {
throw new Error('some error');
}
expect(funcWithError).toThrow();
expect(funcWithError).toThrow(Error);
expect(funcWithError).toThrow('some error');
expect(funcWithError).toThrow(/some/);
expect(true).not.toBe(false);
expect({ foo: 'bar' }).not.toEqual({});
function funcWithoutError() {}
expect(funcWithoutError).not.toThrow();
Давайте напишем пару простых тестов. Для начала создадим простой модуль, который будет содержать несколько методов для работы с окружностями.
// src/circle.js
const area = (radius) => Math.PI * radius ** 2;
const circumference = (radius) => 2 * Math.PI * radius;
module.exports = { area, circumference };
Далее добавим тесты:
// tests/circle.test.js
const circle = require('../src/circle');
test('Circle area', () => {
expect(circle.area(5)).toBeCloseTo(78.54);
expect(circle.area()).toBeNaN();
});
test('Circumference', () => {
expect(circle.circumference(11)).toBeCloseTo(69.1, 1);
expect(circle.circumference()).toBeNaN();
});
В этих тестах мы проверили результат работы 2-х методов — area и circumference. При помощи метода toBeCloseTo мы сверились с ожидаемым результатом. В первом случае мы проверили или вычисляемая площадь круга с радиусом 5 приблизительно равна 78.54, при этом разница с полученым значением (оно составит 78.53981633974483) не большая и тест будет засчитан. Во втором мы указали, что нас интересует проверка с точностью до 1 знака после запятой. Также мы вызвали наши методы без аргументов и проверили результат с помощью toBeNaN. Поскольку результат их выполнения будет NaN, то и тесты будут пройдены успешно.
Разберём ещё один пример. Создадим функцию, которая будет фильтровать массив продуктов по цене:
// src/productFilter.js
const byPriceRange = (products, min, max) =>
products.filter(item => item.price >= min && item.price <= max);
module.exports = { byPriceRange };
И добавим тест:
// tests/product.test.js
const productFilter = require('../src/producFilter');
const products = [
{ name: 'onion', price: 12 },
{ name: 'tomato', price: 26 },
{ name: 'banana', price: 29 },
{ name: 'orange', price: 38 }
];
test('Test product filter by range', () => {
const FROM = 15;
const TO = 30;
const filteredProducts = productFilter.byPriceRange(products, FROM, TO);
expect(filteredProducts).toHaveLength(2);
expect(filteredProducts).toContainEqual({ name: 'tomato', price: 26 });
expect(filteredProducts).toEqual([{ name: 'tomato', price: 26 }, { name: 'banana', price: 29 }]);
expect(filteredProducts[0].price).toBeGreaterThanOrEqual(FROM);
expect(filteredProducts[1].price).toBeLessThanOrEqual(TO);
expect(filteredProducts).not.toContainEqual({ name: 'orange', price: 38 });
});
В этом тесте мы проверям результат работы функии byRangePrice. Сначала мы проверили соответствие длины полученого массива ожидаемой — 2. Следующая проверка требует, чтобы в массиве находился элемент — { name: 'tomato', price: 26 }. Объект в массиве и объект переданный toContainEqual — это два разных объекта, а не ссылка на один и тот же. Но toContainEqual сверит каждое свойство. Так как оба объекта идентичные — проверка пройдет успешно. Далее мы используем toEqual для провеки структуры всего массива и его элементов. Методы toBeGreaterThanOrEqual и toBeLessThanOrEqual помогут нам проверить price первого и второго элемента массива. И, наконец, вызов not.toContainEqual сделает проверку, не содержится ли в массиве элемент — { name: 'orange', price: 38 }, которого по условию там быть не должно.
В данных примерах мы написали несколько простых тестов используя функции проверки описанные выше. В следующих частях мы разберём работу с асинхронным кодом, функции jest которые не затрагивались в этой части туториала, поговорим о его настройке и многое другое.
Автор: AlexGoryny4
Источник [1]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/353095
Ссылки в тексте:
[1] Источник: https://habr.com/ru/post/502302/?utm_source=habrahabr&utm_medium=rss&utm_campaign=502302
Нажмите здесь для печати.