В последнее время я учусь писать все больше и больше своего кода 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, и мы добавим вас в качестве автора.