Пишем API gem: как написать тесты для внешнего API

Пишем API gem: как написать тесты для внешнего API

В прошлой статье мы разобрались как совладать с Hypermedia API и зачем оно вообще нужно. С момента написания той статьи я успел добавить все API точки в код гема, а так же внёс некоторые мелкие фиксы. Вот ссылка на все изменения с того момента: 8056904. c9088e6.

В этой статье мы исправим главный недостаток гема GrooveHQ: отсутствие тестов. Тестирование кода, зависящего от внешнего API – неприятная, но часто встречающаяся задача. Я постараюсь упростить её как можно сильней.

Если тебя мучает вопрос “почему не TDD? А как же red green refactor?”, то прочитай статью про написание первых тестов платформы mkdev, там я объясняю причины моей не любви к этому подходу.

Настройка тестового окружения

В качестве библиотеки для тестов я снова выбираю Rspec – особых преимуществ кроме привычности и бо`льшей популярности я не вижу, но и их достаточно чтобы сделать выбор. Обновим Gemfile:

Внимательный читатель спросит: а почему я добавил гем в Gemfile, а не в gemspec? Отвечаю: просмотрев исходники популярных гемов и пару статей я пришёл к выводу, что гемы для тестов не являются настоящей зависимостью гема, а значит их не стоит добавлять в gemspec.

Дальше нужно добавить папку spec и файл spec/spec_helper.rb :

Можно переходить к тестам.

Выявление недоработок в коде тестами

Первый же написанный мой тест выловил небольшой косяк в коде:

Оказывается, если в качестве данных передать пустую строчку, то старая версия кода выдаст исключение. Обновленный код такой проблемой не страдает и позволяет тесту снова стать зелёным:

Воодушевившись первой победой, добавляю ещё несколько тестов для GrooveHQ::Resource :

Заодно нашёл ещё один баг, смотри полный коммит со всеми тестами на данный момент: f1b5da4. Немного подумав, я решил разбить тесты этого класса на контексты, где каждый контекст посвящён отдельному методу: ed0cd7a.

Лирическое отступление

Прежде чем я продолжу писать тесты, хочется просто поговорить за жизнь. Во-первых, я решил не покрывать тестами все методы, отвечающие на конкретные API-точки. Например, вот такой метод:

Единственный тест, который я могу здесь придумать – это сделать stub результата HTTP-запроса и сравнить, что вызов этого метода возвращает результат этого stub’а. Получается какой-то странный тест. А таких методов сейчас 23. Засорять папку с тестами такими вот бестолковыми проверками, которые потеряют актуальность после малейшего обновления API смысла нет.

Таким образом, мне остаётся только написать тесты на метод GrooveHQ::Client::Connection#parse_data и можно считать 80% важного кода покрытым тестами.

Тестируем запросы к API

Сразу же возникла одна концептуальная проблема: метод #parse_data помечен как private , а значит я не могу вызывать его напрямую, только при помощи send. Да и в целом, одна из особенностей приватных методов в том, что их не нужно тестировать напрямую.

К сожалению, это означает что нам не обойтись без стабов (stubs), так как все публичные методы, которые я могу вызвать выполняют запрос к API. Значит, нужно “стабать” эти запросы и вместо проведения запроса просто возвращать готовый JSON ответ. Для этой задачи я буду использовать гем WebMock, который подключил в коммите 2bf8b92.

Здесь вместо разбивки на контексты по методам, я сделал контекст для каждого типа ответов от API. Вот, например, тест для самого простого варианта – один корневой ключ со всеми атрибутами ресурса внутри:

Строчкой stub_request(:get, "https://api.groovehq.com/v1/tickets/1").to_return(body: response) я говорю: “вместо проведения настоящего запроса по этому адресу просто возвращай мне сразу response ”. Тест получился достаточно объёмным, поэтому за всеми спеками нужно идти и смотреть коммит 69e56b4.

TravisCI

На этом, поидее, можно было бы и завершить написание тестов. Но я посчитал хорошей идеей добавить к проекту Travis CI – самое популярное CI решение для OpenSource проектов. Добавляется он просто – созданием файла .travis.yml и следованием документации.

В результате после каждого коммита прогоняются тесты и все, кто пользуется гемом всегда могут проверить работоспособен ли он. GrooveHQ гем, например, работоспособен.

Что дальше?

На данный момент гем feature complete – можно подключать его к своему приложению и использовать для удобного обращения к любым API точкам GrooveHQ. Все нуждающиеся в этом участки кода покрыты тестами, и у гема даже есть красивый значок от Трэвиса, рапортующий о том, что эти тесты проходят. Впринципе, на этом можно и остановиться. Но вместо этого тебя ждут ещё одна статья, а меня – ещё немного работы по улучшению гема.

Во-первых, в следующей статье мы рассмотрим метапрограммирование в Ruby. Мне хочется использовать что-то подобное: client.ticket(2).state вместо client.ticket(2).rels[:state].get.data .

Во-вторых, нужно куда-то этот гем опубликовать, а ещё написать к нему документацию.

Так что впереди по-прежнему много интересного. Если на твой взгляд в геме не хватает чего-то ещё – пиши в комментариях и, возможно, появится необходимость в ещё нескольких статьях ;-)

Мы рассказываем, как стать более лучшим разработчиком, как поддерживать и эффективно применять свои навыки. Информация о вакансиях и акциях эксклюзивно для более чем 8000 подписчиков. Присоединяйся!

📎📎📎📎📎📎📎📎📎📎