RSpec на страже микросервисов
В современном мире тяжело представить разработку приложений без тестирования. Особенно в мире ruby. Особенно когда лёгкая виртуализация стала уже стандартом и любой разработчик знает, как запускать докер. Качественные тесты позволяют не столько надеяться, что код работает правильно, сколько смело вносить изменения и не бояться при этом сломать то, что есть.
Эта статья продолжает тему использования языка ruby в отрыве от фреймворка rails. И сегодня речь пойдет про Go. Точнее про тестирование приложений на Go, про RSpec и про то, как можно (и я не побоюсь сказать нужно) использовать удобные инструменты для полезных вещей.
Как я писал ранее, в нашей компании есть направления с уклоном в микросервисы. А какие же сегодня микросервисы без Go? В Go есть свои хорошие фреймворки, свои подходы к тестированию, но в основном это касается юнитов. С юнитами все хорошо — писать их относительно легко и удобно. А вот написать интеграционный тест, например такой, в котором нам надо запускать процесс, общаться с ним и проверять какой-то результат (black-box testing) бывает чрезвычайно трудно. Вот тут нам на помощь и приходит RSpec. RSpec — один из самых известных фреймворков тестирования, известен не только в мире ruby, но и за его пределами. В примере мы будем тестировать небольшую консольную утилиту, работающую с consul. Функционал у неё простой: ждать готовность consul
, читать key/value хранилище в виде yaml и соответственно загружать значения key/value из этого самого yaml обратно в хранилище consul
.
BDD, TDD, FDD, ГИБДД now!
Сначала научимся запускать полностью новый consul
для каждого теста. Почему новый? Ну во-первых потому что можем 💪, а во-вторых чтобы тесты были “чистыми” без побочных эффектов или истории (у consul
для этого даже специальный ключ -dev
имеется) — каждый раз как первый раз.
Дальше работаем с нашей утилитой: в тестах ловим и проверяем результат.
Вот тут динамика языка показывает себя во всей красе — before, after, around, ensure и rescue, работа с нетипизированными и неструктурированными и данными, различные RSpec-матчеры на все случаи жизни и многое другое. От нас, программистов, требуется только придумать что же именно мы собрались тестировать — в чём суть теста? Это и есть самое замечательное в RSpec и ruby — можно сконцентрироваться на самом сложном — на том “что” делать. А всю утилитарную обвязку берёт на себя тестовый фреймворк. Дальше всё в докер, гитлаб и готово.
Такие тесты у нас работают в нескольких сервисах и вспомогательных утилитах и, чувствуют себя хорошо. Спеки получаются очень читабельными, и гораздо более понятными, чем юниты на Go. А вишенкой является то, что когда мы переписали одну консольную утилиту с ruby на Go, то переписывание тестов заняло от силы пару часов — правки аргументов и параметров.