Модульное тестирование (в большинстве случаев это скучно 😝) является неотъемлемой частью разработки через тестирование (TDD). Это процесс определения желаемого вывода функции, а также того, чего ожидать и чего не следует делать в начале фактической функции.
Такой подход к процессу разработки программного обеспечения имеет свои преимущества:
- Это помогает наметить задачу, которая должна быть выполнена в ходе выполнения функции.
- Получаешь четкое представление о том, как мой код должен вести себя в разных сценариях.
- Поскольку поведение функции может быть изменено в будущем, это гарантирует, что изменения в функции не нарушат любой другой сценарий, упомянутый в тестовом примере.
В этом блоге вы получите общее представление о том, что такое Jest, зачем его использовать и как использовать Jest для модульного тестирования.
Надеюсь, вам понравится остальная часть блога. 😄
Что и почему шутить
Jest — это средство запуска тестов JavaScript, то есть библиотека JavaScript для создания, запуска и структурирования тестов. Jest поставляется в виде пакета NPM, вы можете установить его в любой проект JavaScript.
Это гарантирует, что разные тесты не влияют на результаты друг друга. В Jest тесты выполняются параллельно, каждый из которых работает в своем собственном процессе. Это означает, что они не могут мешать другим тестам, а Jest действует как организатор, собирающий результаты всех тестовых процессов.
Настройка проекта с шуткой
- Создайте папку с помощью
mkdir learning_jest && cd learning_jest
- Настройка среды NPM
npm init -y
- Установите Jest, используя
npm i jest --save-dev
После этого мы внесем изменения в файл package.json
, чтобы мы могли запустить наш тестовый файл.
[package.json] "script": { "test": "jest --verbose" }
Использование --verbose
покажет подробности о каждом тестовом примере. (Попробуйте ту же команду без этого флага, чтобы увидеть разницу)
Определение желаемого результата
Здесь мы определим функцию, которую мы создаем, и каким должен быть ожидаемый результат при ее вызове.
Для этого блога мы собираемся использовать объект, содержащий информацию об информации пользователя в Twitter.
const user = { username: "John Doe", tweets:[ { likes: 100, content: "Tweet 1 content..." }, { likes: 100, content: "Tweet 2 content..." } ] }
Мы будем писать 2 функции,
getTotalLikes
чтобы получить общее количество лайков твитов пользователяgetMostPopularTweet
для возврата объекта твита указанного пользователя с наибольшим количеством лайков
Следуя процессу TDD, мы разработаем тесты для этих функций до разработки логики самих функций.
У нас есть намерение для функции, давайте инициализируем наш тестовый файл.
Инициализируйте тестовые файлы
Для хранения всех наших тестовых файлов у нас может быть папка tests
или __test__
. Вы также можете хранить тестовые файлы в любом месте каталога проекта, но рекомендуется собрать все тестовые файлы в одном месте.
Имя файла должно иметь .test.js
, а фактическое имя должно совпадать с именем файла, в котором вы собираетесь писать свою функцию.
mkdir __test__ && cd __test__ && touch demoFunction.test.js
Теперь в тестовый файл нам нужно импортировать функции, которые мы собираемся тестировать.
// example.test.js file { getTotalLikes, getMostPopularTweet } = require("../exampleFunction.js") // user object using which we are going to test these 2 functions const user = { username: "John Doe", tweets:[ { likes: 200, content: "Tweet 1 content..." }, { likes: 90, content: "Tweet 2 content..." } ] }
Теперь приготовьтесь написать свой первый тестовый пример. ✨
Написание тестов
Тесты обычно содержат следующие общие компоненты:
- функция
describe
— принимает 2 аргумента.
строка — она появится в терминале, когда мы запустим тестовый пример
функция обратного вызова, которая будет содержать отдельные тесты.
- функция
test
— принимает 2 аргумента
строка — описывает действие для конкретного теста
функция обратного вызова, которая будет содержать ожидание и функцию сопоставления
expect
Функция принимает тестируемый вызов и связана с matcher
функцией, которая описывает ожидаемые результаты.
Теперь для функции getTotalLikes
мы хотим, чтобы наша функция принимала объект пользователя в качестве аргумента и возвращала общее количество лайков пользователя в виде целого числа.
Добавив тест для функции, наш файл будет выглядеть так:
// example.test.js file { getTotalLikes, getMostPopularTweet } = require("../exampleFunction.js") // user object using which we are going to test these 2 functions const user = { username: "John Doe", tweets:[ { likes: 200, content: "Tweet 1 content..." }, { likes: 90, content: "Tweet 2 content..." } ] } describe("getTotalLikes", ()=>{ test("should return the total likes of a user", ()=>{ expect(getTotalLikes(user)).toBe(290) }) })
Здесь сопоставитель .toBe
используется для сопоставления ожидаемого вывода с фактическим возвращаемым значением функции.
Фреймворк Jest предоставляет множество сопоставителей для работы.
toBeNull
соответствует только нулюtoBeUndefined
соответствует только undefinedtoBeTruthy
соответствует всему, что оператор if считает истиннымtoBeFalsy
соответствует всему, что оператор if считает ложнымtoBeGreaterThan
илиtoBeLessThan
для сравнения числовых значенийtoMatch
принимает шаблон Regex для соответствия строковому выводуtoContain
можно использовать, чтобы увидеть, содержится ли значение в массиве
Чтобы увидеть полный список совпадений, посетите этот официальный документ.
Для нашей второй функции, getMostPopularTweet
, мы определим ожидаемый объект вывода в блоке describe
и передадим этот объект в функцию сопоставления. Для этого мы будем использовать сопоставитель toEqual
, который обычно используется для работы с массивами и объектами.
describe('getMostPopularTweet', () => { test('should return the most popular tweet of a user', () => { const output = { likes: 200, content: "Tweet 1 Content..." } expect( getMostPopularBlog(user)).toEqual(output) }) })
Давайте попробуем запустить наш тестовый файл, используя npm test
Ой! наши тесты провалились!
Потому что мы не определили функции для тестирования.
Давайте решим это и напишем реальные функции.
Функции записи
Создайте файл с именем exampleFunction.js
, который будет содержать наши функции. Имя файла должно совпадать с именем тестового файла.
// exampleFunction.js file function getTotalLikes( user ){ // iterate through the tweet entries and sum the like values const totalLikes = user.tweets.reduce( (total, tweet) => { return total += tweet.likes }, 0) return totalLikes; } function getMostPopularTweet( user ){ const maxLikes = user.tweets.reduce( (max, tweet, index) => { if (tweet.likes > max.likes) { return { index: index, likes: tweet.likes } } else { return max } }, {index: undefined, likes: 0} ) const topTweet = user.tweets[ maxLikes.index ] return topTweet } module.exports = { getTotalLikes, getMostPopularTweet }
Теперь, когда у нас все готово, давайте запустим наши тесты.
Запуск тестов
Используйте следующую команду для запуска всех тестовых файлов:
npm test
Вас встретят индикаторы прохождения тестов.
Заключение
Написание теста поможет увидеть, влияет ли добавление какого-либо кода в существующую функциональность на старую функциональность. Это определенно очень полезно, когда у вас есть команда, работающая над одним и тем же кодом. Негативное влияние на старый код укажут письменные тесты.
Однако написание тестов будет зависеть от того, сколько сценариев вы рассмотрели, прежде чем приступить к созданию фактической функциональности. Не забудьте рассмотреть крайние сценарии, которые могут нарушить работу кода.
Тема тестирования глубока, но, надеюсь, этот блог поможет вам понять процесс тестирования и написания собственных тестов.
Продолжайте тестировать ❤️