В последнее время я учусь писать все больше и больше своего кода JavaScript без помощи какой-либо библиотеки или фреймворка. Мне нравится иметь хорошее покрытие модульным тестом для любого кода, который я пишу, потому что это дает мне уверенность, когда я хочу реорганизовать свой код или изменить его по любой другой причине. В этом сообщении в блоге я продемонстрировал, как писал модульные тесты без какой-либо структуры.
Начнем с создания двух файлов:
test.js
содержит тестовые функцииassert
иit
, которые нам нужны для тестирования. Он также содержит все модульные тесты.test.html
- тестовый бегун.
Функции тестирования
Давайте сначала создадим test.js
файл и напишем функцию it
, как показано ниже.
Функция it
принимает два параметра. Первый параметр desc
- это описание тестового примера, а второй параметр fn
- это тестовая функция. fn
заключен в try/catch
блок. Если fn
выполняется успешно, мы показываем сообщение об успешном завершении в консоли, а если тест не проходит, мы показываем сообщение об ошибке в консоли.
Затем мы реализуем функцию assert
в test.js
.
Функция assert
принимает один параметр isTrue
, который является условием, например x === y
. assert
проверяет условие и выдает ошибку, если условие равно false
.
Вот и все. Это вся наша среда тестирования.
Test Runner
test.html
- это наша программа для выполнения тестов, которая включает файл test.js
.
Простые тестовые примеры для тестирования фреймворка
Давайте убедимся, что наша тестовая среда работает должным образом, написав пару простых тестов.
Неудачный тест
Напишите следующий тестовый пример после функции assert
в test.js
it('should fail', function() { assert(1 !== 1); });
Откройте файл средства выполнения тестов test.html
в браузере (желательно в Chrome). Откройте консоль браузера. Вы должны увидеть сообщение об ошибке в консоли, как показано ниже.
Поскольку 1 !== 1
является недопустимым условием, тест не проходит. Вы можете понять, где произошел сбой, посмотрев на стек ошибок. В этом случае я бы проверил строку 26 в моем test.js, чтобы начать отладку проблемы.
Прохождение теста
Теперь давайте напишем небольшой проходной тест на test.js
.
it('should pass', function() { assert(1 === 1); });
Обновите test.html
в браузере и проверьте консоль. Вы должны увидеть сообщение об успешном завершении в консоли, как показано ниже.
Большой! Наша тестовая среда, похоже, работает нормально. Теперь давайте используем нашу тестовую среду для некоторых реальных сценариев.
Создать файл кода приложения
Как правило, вы будете писать код своего приложения в отдельном файле JavaScript, таком как app.js
. Создадим app.js
файл
/* app.js */ (function(){ 'use strict'; //Create a global variable and expose it to the world var $myapp = {}; self.$myapp = $myapp; })();
Мы создали глобальную переменную $myapp
и предоставили ее миру, чтобы мы могли вызывать эту глобальную переменную из файла test.js
. Всегда используйте уникальное имя для вашей глобальной переменной, чтобы она не конфликтовала с другими глобальными переменными.
Теперь давайте включим app.js
файл в test.html
, как показано ниже.
/* test.html */ ... <body> ... <script src="app.js"></script> <script src="test.js"></script> </body>
Убедитесь, что app.js
включен до test.js
Тестирование метода в коде приложения
Давайте напишем метод проверки даты в нашем app.js
файле
isValidDate
определяет, действительна ли данная строка даты, и возвращает true
или false
.
Теперь давайте напишем тестовый пример для этого метода в нашем test.js
//test.js ... it('should validate a date string', function () { // Valid Date assert($myapp.isValidDate('02/02/2020')); // Invalid Date assert(!$myapp.isValidDate('01/32/2020')); }); ...
В приведенном выше тестовом примере первый assert проверяет допустимую строку даты, а второй assert проверяет недопустимую строку даты. Откройте или обновите test.html
файл средства запуска тестов и проверьте консоль. Вы должны увидеть сообщение, подобное приведенному ниже
Тестовый DOM
Допустим, мы пишем простое приложение со списком задач. У нас есть форма с полем ввода для ввода задачи и кнопкой отправки. Мы слушаем событие отправки в нашем app.js
файле, и обработчик событий обновляет список задач в DOM.
Вот HTML-код
Ниже приведен код JavaScript в app.js
, который обновляет список задач.
Мы хотим протестировать код JavaScript и убедиться, что он добавляет элемент todo к #todo-list
элементу неупорядоченного списка в DOM, как и ожидалось.
Тестовый пример для DOM
Ниже приведен тестовый пример для проверки кода обработчика событий, чтобы убедиться, что он обновляет DOM при вводе нового элемента todo.
В нашем test.html
мы создали элемент-заполнитель <div id="selector"></div>
для вставки тестового кода в DOM нашего средства выполнения тестов.
В тестовом примере var selector = document.querySelector('#selector')
получает ссылку на наш элемент-заполнитель. Затем мы добавляем selector
к форме с идентификатором aform
. Мы должны убедиться, что все имена и идентификаторы элементов соответствуют ожиданиям обработчика событий в app.js
.
Следующая строка устанавливает значение поля ввода
form.elements['todo-input'].value = 'task 1'
Затем мы создаем и инициализируем HTML-событие «submit», и наша форма отправляет это событие.
form.dispatchEvent(ev)
Это запустит обработчик событий в app.js
файле, который прослушивает событие «submit». Обработчик событий добавит «задачу 1» в todo-input
HTML-список.
Следующая строка кода подтверждает, что задача была добавлена в список HTML, как ожидалось.
assert(selector.innerHTML.toLowerCase().includes('<li>task 1</li>'));
Запустите средство запуска тестов в браузере и проверьте консоль браузера. Если все прошло должным образом, вы должны увидеть следующее сообщение об успешном выполнении.
Последняя строка в тестовом примере selector.innerHTML = ''
очищает элемент-заполнитель.
Тестирование при задействовании асинхронной функции
Допустим, мы выполняем вызов REST API, чтобы получить имя и фамилию пользователя, которые затем отображаются в DOM. Мы хотим проверить, успешно ли отображается DOM без вызова API.
Ниже приведен код, который мы хотели бы протестировать.
$myapp.get
инкапсулирует запрос XMLHttpRequest
GET. Он принимает строковый параметр url
и вызывает функцию callback
с ответом.
$myapp.getUser
- это метод, который мы хотим протестировать. Он вызывает метод $myapp.get
, а затем функция обратного вызова отображает DOM с именем и фамилией пользователя.
Заглушите асинхронный код
Как показано выше, мы закрываем асинхронный метод $myapp.get
и возвращаем фальшивый объект пользователя.
Мы вызываем $myapp.getUser(1)
метод. Это должно успешно выполнить заглушенный метод $myapp.get
и отобразить имя и фамилию пользователя, как определено в заглушке.
В следующем коде проверяется, была ли обновлена наша тестовая DOM с правильными именем и фамилией.
assert(selector.innerHTML.includes('Amit Gupta'))
Наконец, мы очищаем объект DOM-заполнителя, сбрасывая его innerHTML.
Резюме
В этом сообщении в блоге показано, как можно выполнить модульное тестирование кода JavaScript переднего плана без использования какой-либо структуры. В блоге показано
- Как создать
it
иassert
тестовые функции - Как выполнить модульное тестирование функций приложения
- Как провести модульное тестирование DOM
- Как проводить модульное тестирование при использовании асинхронных вызовов
Это простой и практичный способ модульного тестирования кода JavaScript внешнего интерфейса в браузере.
Исходный код
Исходный код с примерами тестов размещен на GitHub.
Примечание из JavaScript In Plain English
Мы всегда заинтересованы в продвижении качественного контента. Если у вас есть статья, которую вы хотели бы отправить в какую-либо из наших публикаций, отправьте нам электронное письмо по адресу [email protected] с вашим именем пользователя Medium, и мы добавим вас в качестве автора.