Юнит-тесты и Jest: toBe or not.toBe

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

Сейчас рассмотрим юнит-тестирование с JavaScript-фреймворком Jest.

Тестирование в жизни

Понять важность Тестирования как процесса, а не только в ИТ-сфере, поможет пример из жизни. Представим, что есть бывший в употреблении автомобиль, с виду приличный. Его владелец утверждает, что автомобиль “как новый, на 10 из 10”. Конечно, надо проверить автомобиль перед покупкой, и глупо будет если этого не сделать. Так же и с софтом. 

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

Юнит-тестирование

Юнит-тестирование (также называемое “модульным”) — это, как следует из второго названия, подвид тестирования, который сосредотачивается на тестировании отдельных модулей кода. 

Jest

Этот фреймворк разработан Facebook, что уже должно о чем-то говорить.

Как утверждают создатели фреймворка из Jest Core Team, “он позволяет быстро писать легкие, удобные и функциональные тесты с отличным API”

Установки и настройки

1. Устанавливаем npm

Он может быть уже установлен, и чтобы проверить это, вводим в терминале  npm —version. Если не установлен, идем сюда и читаем документацию, как установить npm.

2. Создаем package.json

Это можно сделать двумя способами. Или инициализация после команды npm init создаст package.json, но для этого надо сначала кое-что настроить, то есть ввести своё описание, присвоить название, и возможно ввести еще что-то дополнительное. Второй путь: ввод команды npm init -y, чтобы проскочить этот этап конфигурации, и тогда получим файл дефолтной конфигурации.

3. Устанавливаем Jest

Вводим в терминале npm install —save-dev jest. При этом автоматически пропишется нужная зависимость.

Далее идем к файлу package.json, находим в нем, в начале, раздел “scripts” и меняем в нем значение “test” на “jest”.

Все готово к тестированию.

Матчеры

Перед тем как погрузиться в процесс, нужно понять, что такое матчеры (matchers).

Как утверждается в документации, Jest применяет “матчеры” для проверки тестовых значений в различных ситуациях.

Перейдем к практике.

toBe

Матчер toBe означает полную эквивалентность. Другими словами “===”.

test('10 plus 10 is 20', () => {
  expect(10 + 10).toBe(20)
})

Такой тест пройдет успешно.

test('numbers is the same as sameNumbers', () => {
  const numbers = [1, 2, 3]
  const sameNumbers = [1, 2, 3]
  expect(numbers).toBe(sameNumbers)
})

А вот этот тест выше — упадет, даже если значения те же — потому что массивы имеют разные адреса в памяти. (Если этот нюанс вызывает затруднения, надо почитать что-то базовое об управлении памятью в JavaScript).

Как видим, тестируя массивы (или объекты), применять toBe — не лучшая опция. Для этого существует матчер удобнее — toEqual.

toEqual

Этот матчер почти всегда подойдет. Он означает то что называется “глубокая эквивалентность” (так называемая “deep equality”), то есть он попарно сопоставляет каждое значение в объектах или массивах. Поэтому если в предыдущем тесте применить toEqual вместо toBe, то тест пройдет.

toMatch

Сравнивая строки с регулярными выражениями, применяем toMatch.

test('there is an "e" in hello', () => {
  expect('hello').toMatch(/e/)
})

toContain

Если хотим проверить, входит ли элемент в последовательность, применяем матчер toContain.

const numbers = [1, 2, 3]
  expect(numbers).toContain(2)

Тестирование на противоположность матчеру

Если нужно протестировать на противоположность, просто пишем .not перед матчером: если это матчер toBe, то пишем: .not.toBe(…) .

Посмотреть весь список матчеров и опций можно здесь — в документации по Jest.

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

Процесс тестирования достаточно прост.

  1. Допустим, у нас есть функция, принимающая массив из строк, и выбирающая из них самую длинную:
const longestStr = (arr) => {
let longestString = arr[0]
for (let i = 0; i < arr.length; i++) {
 if (longestString.length < arr[i].length) {
   longestString = arr[i]
 }
}
return longestString
}
module.exports = longestStr

Обращаем внимание на module.exports = longestStr в конце. Это для экспорта результата функции; так мы можем потом импортировать его в файл теста.

  1. Создаем отдельный JavaScript-файл, который при работе с функциями рекомендуется назвать так же как функция которую собираемся протестировать, и расширение ему желательно иметь или .spec.js, или .test.js. Оба расширения подходят.
  2. В файле из пункта 2, импортируем нашу функцию:
COPY
const longestStr = require('./longestString')
  1. Теперь пишем свой тест. В нем пишем test(), получающий 2 параметра: первый это строка, описывающая что код будет делать. 

И второй параметр — это функция в которую мы будем писать две вещи: 1) функцию называемую expect, в которую будем передавать функцию с проверяемыми аргументами. 2) наш матчер. Вот так:

const longestStr = require('./longestString')
  1. Запускаем тест, вводом команды npm test в терминале.

Тогда увидим что-то такое:

Если тест пройдет, увидим такое:

Если тест не пройдет, то увидим результат выполнения. (В данном примере мы специально изменили кое-что в в файле longestString.js, чтобы тест выдал fail):

Несколько тестов

Если надо запустить только один файл с тестами, надо указать его название при запуске npm test (и не забыть добавить расширение):

  • Например у нас есть еще файл sum.js
  • Если запустить npm test, оба тестовых файла запустятся одновременно, и если один из них упадет, можно запутаться. Поэтому указываем, какой файл запустить: npm test sum.spec.js

Пропускаем ненужные тесты

Итак, если у нас есть несколько тестов, в одном файле .spec.js или test.js, то при запуске npm test fileName все тесты запустятся одновременно. Если надо запустить лишь один отдельный тест, и чтобы не надо было удалять или закомментировать другие, используем метод .skip:

test.skip('adds 1 + 2 to equal 3', () => {
  expect(sum(1, 2)).toEqual(3)
})
test.skip('adds 10+10 to equal 20', () => {
  expect(sum(10, 10)).toEqual(20)
})
test('2 + 2 is not equal to 6', () => {
  expect(sum(2, 2)).not.toEqual(6)
})

Запустится только один тест, остальные будут пропущены, однако попадут в лог:

На этом пока все, удачи в юнит-тестировании! Посмотри соответствующий раздел на сайте — там бывает полезное.

Какой была ваша первая зарплата в QA и как вы искали первую работу?

Мега обсуждение в нашем телеграм-канале о поиске первой работы. Обмен опытом и мнения.

Подписаться
Уведомить о
guest

0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии

Мы в Telegram

Наш официальный канал
Полезные материалы и тесты
Готовимся к собеседованию
Project- и Product-менеджмент

? Популярное

? Telegram-обсуждения

Наши подписчики обсуждают, как искали первую работу в QA. Некоторые ищут ее прямо сейчас.
Наши подписчики рассказывают о том, как не бояться задавать тупые вопросы и чувствовать себя уверенно в новой команде.
Обсуждаем, куда лучше податься - в менеджмент или по технической ветке?
Говорим о конфликтных ситуациях в команде и о том, как их избежать
$1100*
медианная зарплата в QA в июне 2023

*по результатам опроса QA-инженеров в нашем телеграм-канале

Собеседование

19%*
IT-специалистов переехало или приняло решение о переезде из России по состоянию на конец марта 2022

*по результатам опроса в нашем телеграм-канале

live

Обсуждают сейчас