Тестирование и отладка Node-приложений в Docker-контейнерах

тестирование и отладка в контейнерах

Контейнеры в целом и Docker-контейнеры в частности немного изменили наше представление о развертывании и распространении программного обеспечения. Запуск приложения в контейнере, а не прямо на вашем компьютере или сервере, имеет много преимуществ. Но что насчет тестирования и отладки? Сможем ли мы также отлаживать приложение в контейнере, как если бы оно было установлено на машине? В этой статье рассказывается, как настроить приложение и среду для тестирования Node-контейнеров. Исходный код предложенного проекта можно найти GitHub.

Создание простого приложения

Примечание В качестве примера рассматривается простое Node-приложение. Представленные здесь принципы могут быть легко адаптированы к другим языкам программирования, например, Python, Go или .NET Core.

Создаем директорию проекта и в терминале перемещаемся в нее. Выполняем команду:

На вопрос о точке входа (entry point) вводим server.js и на вопрос о тестовой команде (test command) отвечаем jasmine-node spec . Остальные вопросы можно пропустить, оставив значение по умолчанию. По завершении работы этой команды будет создан файл package.json, который должен выглядеть примерно так:

Наше приложение будет использовать Express JS. Установим пакет командой:

Теперь создаем файл server.js, который будет содержать следующий код:

В строке 4 мы импортируем модуль primes.js, который содержит логику, позволяющую определить, является ли данное число простым. Таким образом, нужно добавить в проект файл primes.js со следующим содержимым:

Добавляем Dockerfile

Чтобы иметь возможность упаковать наше приложение в Docker-контейнер, нам нужно добавить Dockerfile в проект. Содержимое этого файла должно выглядеть так:

Обратите внимание, что в строке 3 мы устанавливаем jasmine-node, который нужен для запуска тестов. Также мы открываем не только порт 3000, но и порт 5858. Последний будет использоваться для присоединения отладчика. Также обратите внимание на то, что мы сначала копируем package.json в образ и запускаем npm install, и только после этого копируем оставшуюся часть папки приложения. Это помогает нам оптимизировать сборку Docker-образа.

Запуск приложения в контейнере

Теперь давайте соберем Docker-образ нашего приложения. Выполним команду:

Примечание Не забудьте указать точку в конце команды.

Теперь мы можем получить контейнер из этого образа:

Мы должны увидеть длинный ID (хеш-код), который выводится в терминал. Чтобы повторно убедиться, работает ли контейнер, мы можем использовать команду docker ps, и должны увидеть следующее:

Если по какой-либо причине контейнер не создался, мы можем просмотреть логи создания командой docker logs my-app:

 Добавляем тесты

Для тестирования мы будем использовать Jasmine. Мы можем поставить его глобально на нашей машине, но зачем это делать, если у нас есть контейнер? В данной статье продемонстрирована глобальная установка Jasmine, но вы можете самостоятельно установить Jasmine в контейнер.  Давайте установим:

Теперь настроим несложный тест. Создайте папку spec и добавьте в нее файл primes-spec.js со следующим содержимым:

Здесь не будет описана логика Jasmine. Вы можете обратиться к подробной документации, чтобы разобраться с этим.

Как только мы определили тест, выполним эту команду в терминале:

Эта команда вызывает Jasmine-node, который мы определили в package.json. Вывод будет примерно такой:

Также мы можем добавлять новые тесты в приложение. Для этого нам нужно добавить модуль require:

Теперь добавьте файл с именем server-spec.js в папку spec. Он должен иметь такое содержание:

Теперь мы можем снова запустить все тесты: npm test.

Давайте запустим тест в контейнере. Для этого используется docker-compose. Добавим файл docker-compose.test.yml в проект:

Этот yaml-файл содержит инструкции по созданию образа контейнера с использованием Dockerfile, открытии порта 3000 и сопоставлении его с портом 3000 на хосте. Наконец, переопределяем значение entrypoint. Теперь в терминале введите следующую команду:

Это создаст образ Docker и запустит контейнер с использованием этого образа с переопределенной точкой входа. Если все работает правильно, мы должны увидеть такой вывод в терминале:

Здесь создается Docker-контейнер и выполняются все тесты. Тесты, которые прошли успешно, возвращают код 0. Мы можем остановить тестирование командой:

Отладка приложения

Мы научились выполнять автоматические тесты приложений. Но что насчет отладки? Ниже будет показано, как проходить код по строкам и проверять значения переменных.

Примечание В данном примере используется Visual Studio Code. Но эти действия можно совершить в большинстве современных редакторов.

Для начала нам нужно узнать, на каком IP-адресе находится хост Docker. Выполним команду:

Добавим в проект файл docker-compose.debug.yml со следующим содержимым:

Подобно файлу docker-compose для тестирования, мы используем Dockerfile для создания образа, открываем порт 3000 и порт 5858, сопоставляем их с теми же портами на хосте. Наконец, мы переопределяем точку входа node --debug = 5858 server.js. То есть запускаем узел в режиме отладки, прослушивая порт 5858. Мы можем начать сеанс отладки, используя эту команду:

В качестве последнего шага нам необходимо настроить Visual Studio Code для присоединения к Node-приложению, запущенному в контейнере. Добавим папку .vscode в наш проект. Внутри этой папки мы добавляем файл launch.json.

Содержимое файла должно быть следующим:

Обратите внимание на раздел с именем Attach. Вы должны убедиться, что в поле address командой docker-machine ip default указан IP-адрес вашего Docker-хоста.
Как только была добавлена конфигурация запуска, мы можем щелкнуть по кнопке отладки. Убедитесь, что выбрана настройка Attach, а затем нажмите кнопку запуска.

Теперь добавьте точку останова в строку 7 файла server.js. Откройте браузер и перейдите к 192.168.99.100:3000 (замените IP-адрес своим, если у вас другой). Отладчик должен остановиться в строке 7:

В окне отладки мы видим всю отладочную информацию:

Итог

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

Перевод статьи «Testing and Debugging a Containerized Node application»