DynamoDB + Rake + Maven + Rack::Test

The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:

В SixNines.io, одном из моих Ruby веб-приложений, я использую DynamoDB, облачную базу данных NoSQL от AWS. Она работает отлично, но проблема в том, что не так просто создать интеграционный тест, чтобы убедиться, что мой код работает совместно с “реальным” сервером и таблицами DynamoDB. Позвольте показать вам, как эта проблема была решена. Код открытый и вы можете увидеть его в репозитории yegor256/sixnines на GitHub.

Сначала вам нужно использовать DynamoDB Local, инструмент командной строки, созданный AWS именно для целей тестирования. Вам нужно запустить его перед интеграционными тестами и остановить после них.

Чтобы упростить задачу, я предлагаю вам использовать jcabi-dynamodb-maven-plugin, плагин Maven, который я создал несколько лет назад. Вам нужно добавить pom.xml в ваш репозиторий и запустить/остановить Maven из Rakefile, так же, как я делаю здесь.

Сначала я удаляю dynamodb-local/target, каталог, где Maven хранит свои временные файлы, чтобы убедиться, что мы всегда начинаем с чистого листа.

Затем я запускаю mvn install, используя Process.spawn в качестве фонового процесса с pid в качестве его идентификатора процесса (это не сработает в Windows, только в Linux/Mac). Затем я сразу регистрирую Ruby-хук at_exit, который будет выполнен, если Ruby умирает по любой причине. Я уверен, что очевидно, почему мне нужно это сделать - чтобы избежать мусора, работающего в фоновом режиме после завершения или прерывания Rake.

Обратите внимание, я использую kill -TERM вместо kill -KILL, чтобы дать Maven возможность завершить все, правильно завершить DynamoDB Local, закрыть его TCP-порт и выйти.

Далее я проверяю статус sn-endpoints, одной из таблиц в локальной DynamoDB. Она должна быть там, если сервер работает. Она будет создана с помощью jcabi-dynamodb-maven-plugin согласно sn-endpoints.json, его JSON-конфигурации.

Скорее всего, таблица не будет готова сразу, так как требуется время для загрузки Maven, запуска сервера и создания таблиц. Поэтому, если происходит исключение, я его перехватываю, жду 5 секунд и пробую снова. Я продолжаю попытки несколько раз, пока сервер не будет готов. В конечном итоге он будет готов. Это занимает около 12-15 секунд на моем MacBook, что означает 2-3 попытки/исключения.

Моим классам нужно знать, как подключиться к серверу во время интеграционных тестов. В продакшене им нужно подключаться к AWS, а при тестировании им нужно знать о только что запущенном экземпляре DynamoDB Local. Вот что у меня есть в моем классе Dynamo, который отвечает за само подключение к DynamoDB. Его решение о том, где подключаться, основывается на переменной окружения RACK_ENV, которая установлена на значение "test" в test__helper.rb, который включен в rake/testtask перед всеми остальными тестами благодаря двойному подчеркиванию в его имени.

Если переменная окружения установлена на значение "test", Dynamo берет параметры подключения из YAML-файла dynamodb-local/target/dynamo.yml, созданного с помощью maven-resources-plugin:copy-resources. TCP-порт локальной базы данных DynamoDB будет здесь, а также ключ и секрет аутентификации DynamoDB.

Это самая простая часть. Я просто использую свои объекты так, как они должны использоваться в производстве, и они подключаются к локальной версии DynamoDB вместо AWS.

Я использую Rack::Test для тестирования всего приложения путем выполнения набора HTTP-запросов. Например, здесь я пытаюсь отобразить страницу учетной записи пользователя Джеффа. Ожидается, что код ответа HTTP будет 200.

Теперь вы можете запустить весь тест из командной строки. Вы можете увидеть, как Rultor запускает его при выпуске новой версии: полный журнал. Также посмотрите, как это работает в Travis. Вкратце:

  • Рейк пытается запустить задачу default, которая зависит от test.

  • Rake пытается запустить test, который зависит от dynamo;

  • Rake, внутри задачи test, запускает mvn install в фоновом режиме с использованием этого pom.xml.

  • Maven распаковывает пакет установки DynamoDB Local;

  • Maven резервирует случайный TCP-порт и сохраняет его значение в ${dynamo.port}.

  • Maven сохраняет ${dynamo.port} и информацию о ключе/секретной паре.

  • Maven запускает локальный DynamoDB, привязывая его к зарезервированному TCP-порту;

  • Rake ожидает доступность DynamoDB Local на зарезервированном порту;

  • Rake imports все классы тестов, начиная с test__helper.rb;

  • Переменная окружения RACK_ENV установлена на "test";

  • Rack::Test пытается обработать веб-страницу.

  • Dynamo загружает YAML-конфигурацию из dynamo.yml и подключается к локальной базе данных DynamoDB.

  • Rake stops;

  • Ruby terminates Maven and it stops DynamoDB Local.

Руби terminates Мавен и останавливает DynamoDB Local.

That’s it.

Translated by ChatGPT gpt-3.5-turbo/42 on 2023-11-17 at 16:47

sixnines availability badge   GitHub stars