Освоение тестирования REST API |
28.04.2017 08:36 |
Автор: Андрей Шальнев В этой статье я хочу поделиться опытом освоения тестирования (в т. ч. автоматизации) на уровне API (Application Programming Interface – интерфейс программирования приложений, интерфейс прикладного программирования). Надеюсь, что предлагаемый материал будет представлять интерес для всех, кто ранее проводил тестирование через графический интерфейс и еще не имеет опыта работы с http-запросами. Немного о REST API и SOAP API Стоит отметить, что на сегодняшний день есть два основных подхода к построению программного интерфейса веб-приложений: REST (RESTful) API и SOAP API:
Если уподобить HTTP-запрос бумажному носителю, то можно сказать, что REST API в большинстве случаев передает простые записки, а время от времени – письмо в конверте (возможно, написав при этом часть послания и на самом конверте). В свою очередь, SOAP API передает все инструкции в подробном письме стандартного вида, используя конверт (единичный HTTP-запрос) лишь как средство доставки. Для лучшего понимания разницы подходов я рекомендую читателю посмотреть следующую инфографику. В статье речь будет идти о REST API, так как этот подход является более распространенным из-за своей относительной простоты и удобства для разработчиков. SOAP API преимущественно характерен для больших корпоративных (enterprise) систем. Чем работа с API может быть полезна тестировщику? Для начала постараемся понять, зачем вообще тестировщику осваивать что-либо на таком уровне. Казалось бы, программные интерфейсы – это территория разработчиков. Ниже мы рассмотрим выгоды использования тестирования API. Выгода первая: точная локализация. Выгода вторая: экономия времени при подготовке тестовых данных и ситуаций. Более того – многочисленные действия в браузере часто являются причиной ложных «падений» автоматизированных тестов, которым на уровне GUI свойственна «хрупкость». Одно неуспешное нажатие кнопки может привести к необходимости повторения либо всего теста, либо какой-то его части. Сформировав запрос программно или воспроизведя его с помощью специальных инструментов (об этом чуть позже), мы можем существенно сократить время проверки. Выгода третья: возможность воспроизводить тесты на больших наборах входных данных. Выгода четвертая: возможность участвовать в проектах, где работа с API является требованием тест-дизайна. Сам тест-дизайн проекта может оказаться таковым, что некоторая часть тестов должна будет проводиться только через программные интерфейсы (например, если на проекте реализована концепция «пирамиды тестирования», при которой лишь немногие тесты используют графический интерфейс). Также стоит отметить, что все большую популярность набирает архитектура микросервисов, когда приложение является не «монолитным», а фактически представляет собой набор самостоятельных приложений, обменивающихся данными. И в этом случае тестирование API становится особенно востребованным, так как именно оно позволяет в полной мере убедиться в правильности интеграции отдельных сервисов и в соблюдении логики функционирования системы в целом. Неумение работать с программными интерфейсами существенно ограничивает возможность вашего участия в таких проектах. Практические шаги к освоению работы с REST API сайта Итак, вы решили освоить работу с программным интерфейсом вашего сайта. С чего же начать? Шаг 1: откройте средства разработчика в браузере. Совершайте обычные действия в браузере и наблюдайте за результатом. Первое, что бросается в глаза, – это огромное количество запросов даже при загрузке одной страницы: для получения каждого изображения, стилей, шрифтов, структуры страницы, скриптов. При использовании AJAX (от англ. Asynchronous Javascript and XML – асинхронный JavaScript и XML, подход к построению интерактивных пользовательских интерфейсов веб-приложений, заключающийся в «фоновом» обмене данными браузера с веб-сервером) количество запросов может увеличиваться, даже если вы не производите никаких активных действий. Шаг 2: скройте запросы, не относящиеся к логике работы. Выберите XHR (XMLHttpRequest) – это интерфейс языка JavaScript, используемый для конструирования запросов, имеющих тело. Обычно именно этот интерфейс используется для обращения к API. Вы можете столкнуться с большим количеством однотипных запросов, порождаемых различными системами мониторинга (например, yandex.webvisor). Их можно скрыть, применив негативный фильтр (например, «-yandex» для Chrome), даже если вы не знаете точно, что именно эти запросы делают. Однотипные и часто повторяющиеся запросы, как правило, относятся к мониторингу сайта, а не к логике совершаемых пользователем действий. Просмотрите внимательно оставшиеся после применения фильтра запросы и постарайтесь выявить те, которые относятся именно к логике действий. В случае необходимости обратитесь за разъяснениями к разработчикам. Если вам доступна документация, в которой описываются endpoint-ы сервисов вашего проекта (т. е. адреса, к которым обращаются запросы, относящиеся к API), – изучите ее. Ниже я буду рассматривать вариант, когда подробной документации или соответствующих доступов у вас нет. Достаточно часто по адресу endpoint-а можно догадаться, за что именно отвечает запрос к данному сервису. Например, адрес, содержащий фрагмент «api/rest/createContract», скорее всего, используется для создания договора, «api/rest/buildInfo» – для вывода информации о версии, установленной в текущий момент, а «api/rest/news/search» – для поиска новостей. Если трудно «выловить» нужный запрос в общей массе (а запросов к API тоже может быть немало) – очистите историю запросов перед совершением интересующего вас действия. Довольно быстро вы научитесь видеть нужные запросы и сопоставлять их с действиями в пользовательском интерфейсе. Нажмите на картинку, чтобы увеличить изображение Шаг 3: проведите более детальный анализ структуры запросов. С другой стороны, встречаются запросы, передающие большинство параметров в теле самого запроса. При этом часть параметров может передаваться и в URL. Примером могут послужить POST-запросы: URL: POST https://www.youtube.com/feed_ajax?action_pause_watch_history=1 HTTP/1.1 На структуру тела запросов и ответов не накладывается ограничений. Это может быть как просто набор пар поле/значение (т. н. Form Data, как в примере выше session_token/значение), так и документ в удобном для разработчика формате (JSON, XML или каком-то ином). Проанализируйте приходящие ответы (вкладка Response) и их коды. Помимо всего прочего, коды ответов, как правило, несут полезную информацию и сообщают о логике происходящего. Большинство запросов имеют код ответа «200 OK», сообщающий о том, что операция выполнена успешно. В случае возникновения ошибки коды будут начинаться на 4 (ошибка на стороне клиента) или на 5 (ошибка на стороне сервера). Например, таковы всем известные ошибки 404 («клиент запросил несуществующий ресурс») и 500 («внутренняя ошибка сервера»). Обратите внимание, что браузеры предоставляют возможность просмотра подробностей запросов/ответов как в удобном формате («parsed» в Google Chrome, «pretty print» в Mozilla Firefoх), так и в «сыром» виде («source»). Конечно, для понимания проще «parsed»/«pretty print», но в том случае, когда вам необходимо скопировать часть запроса, лучше переключиться в режим «source». Нажмите на картинку, чтобы увеличить изображение Нажмите на картинку, чтобы увеличить изображение Шаг 4: воспроизведите запросы. Итак, вы видите нужные запросы и понимаете, какие именно параметры они передают и с какой целью. Теперь можно попробовать самостоятельно менять значения параметров для получения нужных действий. Каким образом можно воспроизвести запросы с измененными параметрами? Самый простой способ — создавать GET-запросы, просто вводя их в адресную строку браузера (по сути, адресная строка – это интерфейс командной строки для воспроизведения GET-запросов). Но вам не удастся сделать многое, ограничившись лишь GET-методом. Для расширения ваших возможностей используйте Fiddler или подобные ему инструменты (например, такие). Эти программы перехватывают весь сетевой трафик, позволяя просматривать, редактировать и воспроизводить отдельные запросы. Уже на этом уровне можно что-то тестировать – например, валидацию данных на стороне сервера. Если веб-клиент в браузере не позволил вам ввести некоторые значения – в Fiddler-е вы сконструируете запрос сами. Такой способ может существенно ускорить проверку большого набора данных для ввода, особенно если изменение значений в браузере занимает длительное время. В качестве приятного бонуса я приведу небольшую пошаговую инструкцию по воспроизведению запроса в Fiddler.
Нажмите на картинку, чтобы увеличить изображение
Нажмите на картинку, чтобы увеличить изображение
Нажмите на картинку, чтобы увеличить изображение
Нажмите на картинку, чтобы увеличить изображение Дальше – автоматизация тестирования REST API! Постигнув принципы работы API, вы можете использовать эти навыки в автоматизированных тестах. Остается выбрать инструменты, которые будут воспроизводить нужные вам запросы и отслеживать содержимое ответов. Если вы умеете писать автоматизированные тесты для графического интерфейса (например, с использованием Selenium), то идеальным вариантом, на мой взгляд, будет интеграция тестов API в существующий фреймворк. Тесты часто содержат подготовительные/вспомогательные действия, многие из которых удобнее выполнить с использованием API. Это будет быстрее и стабильнее. С другой стороны, механизм авторизации бывает достаточно сложным, его не всегда легко пройти только с помощью запросов. Но и это не представляет проблемы в том случае, если API-тесты интегрированы с тестами GUI. Нужные cookie можно забрать в браузере, открытом с помощью Selenium (driver.manage().getCookieNamed(«sessionId»).getValue()). Для доступа к API посредством языка программирования потребуется библиотека, работающая с http-запросами. Для Java могу порекомендовать rest-assured, в своем фреймворке я использую именно ее. Эта библиотека удобна и популярна – у вас не возникает проблем ни с пониманием кода, ни с нахождением документации, примеров и обсуждений. Rest-assured использует синтаксис в стиле BDD (Behavior Driven Development – подход к автоматизации тестирования, стремящийся описывать код тестов языком, близким к естественному) с характерными ключевыми словами given/when/then: protected ExtractableResponse postRequest(String requestPayload, String endpoint, int expectedStatus){ Блок given описывает предусловия, такие как авторизация и параметры запроса. Обратите внимание: отдельно можно провести базовую http-авторизацию (auth().basic(«login», «password»)) и пользовательскую авторизацию, передав нужные куки (cookies(«sessionId», session)). Очень удобно использовать опцию relaxedHTTPSValidation(), чтобы избежать хлопот с подтверждением сертификатов. Блок when() описывает требуемое действие – запрос какого типа и на какой адрес следует отправить. Блок then() включает проверки, которые необходимо произвести (их может быть несколько одновременно). Например, вы можете проверить, соответствует ли статус ответа ожидаемому (statusCode(expectedStatus)) и содержит ли тело ответа определенный фрагмент текста (body(containsString(«www»))). Команда extract() позволяет получить ответ и использовать его, например, для извлечения определенных значений. Это можно сделать следующим образом: ExtractableResponse response = postRequest(session, payload, endpoint, 200); Здесь команда path(«results.total») позволяет извлечь значение, используя JsonPath либо XPath (в зависимости от того, в каком формате предоставлен ответ). Обратите внимание, что вызываемый метод postRequest определен в моем фреймворке, а не в библиотеке rest-assured. Если вам важно просто получить тело ответа для дальнейших проверок, а блок then не изменяется, то удобнее всего будет для каждого типа запросов (get, post, delete и т. д.) создать свой вспомогательный метод и не прописывать given/when/then каждый раз. Для работы с языком Python используется популярная библиотека requests. Стоит отметить, что и Java, и Python имеют средства работы с http в числе стандартных возможностей, но я неоднократно сталкивался с мнением, что они не слишком удобны. Если вы не планируете писать тесты с использованием языка программирования, то вам, скорее всего, подойдет инструмент Postman – он позволяет воспроизводить и сохранять запросы, а также выстраивать из них тесты. Заключение Все сказанное выше позволяет сделать следующий вывод: умение тестировщиков работать с API может принести пользу практически любому проекту. Например, это дает возможность в считанные минуты провести смоук (и убедиться, что ничего важного не сломалось), выполнить одни и те же тесты с разнообразными наборами входных данных или быстро проделать какие-либо вспомогательные действия по созданию тестовых данных и ситуаций. Наконец, еще раз хочу напомнить, что тестирование API становится особенно востребованным в свете растущей популярности микросервисной архитектуры. Следовательно, даже в том случае, если на вашем проекте пока не используется тестирование на уровне API, вам имеет смысл присмотреться к возможностям, которые оно предоставляет. |