Привет! Я Владимир Пасюга, QA Engineer в NIX. Общий опыт в IT у меня составляет 7 лет, из них 2,5 года я был мануальным тестировщиком в биомедицинском проекте, который включал и UI, и API-часть. Сейчас занимаюсь автоматизированными тестами API в приложении для медицинской сферы.
В этой статье я хочу поделиться своим опытом тестирования API с помощью фреймворков Cucumber и Spock. Я расскажу, что представляет собой API и как проходит мануальное и автоматизированное тестирование этого интерфейса в нашей команде, опишу действенные инструменты и технологии и уделю особое внимание Cucumber и Spock.
Коротко о базовых понятиях
Чтобы предметно говорить о тестировании API, для начала освежим знания о базовых понятиях. API фактически позволяет независимым компонентам программного обеспечения обмениваться информацией. Иными словами API выступает посредником между внутренними и внешними программными функциями. Если программу рассматривать как черный ящик, то API — это набор «ручек», которые доступны пользователю данного ящика и которые он может вертеть и дергать, как ему угодно.
На сегодняшний день существует два основных подхода к построению программного интерфейса веб-приложений: REST (RESTful) API и SOAP API. Если сравнить HTTP-запрос с бумажным носителем, то можно сказать, что REST API в большинстве случаев передает простые записки и время от времени — письмо в конверте (возможно, написав при этом часть послания и на самом конверте). В свою очередь, SOAP API отправляет все инструкции в подробном письме стандартного вида, используя конверт (единичный HTTP-запрос) лишь как средство доставки.
Когда клиенты и серверы работают только в веб-среде, информация об объектах не важна и нет транзакций с несколькими вызовами, применяют REST API. Если же необходимо соблюсти строгий контракт между сервером и клиентом, обеспечить те самые транзакции с несколькими вызовами с высокой безопасностью и нет проблем с пропускной способностью, тогда микросервисы настраивают на SOAP API.
Какие инструменты нужны для тестирования API?
Отсутствие элементов UI-интерфейса с непривычки может ввести QA-специалиста в ступор: нет ни кнопок, ни полей, ни понятного формата обращения к сервисам. Облегчают взаимодействие с API специальные инструменты. Наиболее популярные среди них — SoapUI и Postman.
SoapUI. Приложение с открытым исходным кодом для тестирования Soap и Rest API. SoapUI был первоначально выпущен для SourceForge в сентябре 2005 года. Это бесплатное программное обеспечение с публичной лицензией Европейского Союза. Начиная с первого выпуска, SoapUI был загружен более 2 000 000 раз. Он полностью построен на платформе Java и использует Swing для пользовательского интерфейса (то есть SoapUI — кроссплатформенный). Его функциональные возможности включают проверку веб-службы, запуск, разработку, моделирование и макетирование, функциональное тестирование, тестирование нагрузки и соответствия.
Компания-разработчик программного обеспечения SmartBear также создала коммерческую версию SoapUI Pro (ныне носит название ReadyAPI), которая в основном фокусируется на функциях, предназначенных для повышения производительности. SoapUI может тестировать веб-сервисы SOAP и REST, JMS, AMF, а также выполнять любые вызовы HTTP(S) и JDBC. Для написания автоматизированных скриптов используется язык Groovy.
Postman. Как говорят его создатели, это своего рода швейцарский нож, который позволяет формировать и выполнять запросы, документировать и мониторить сервисы в одном месте. Тестировщики могут писать тесты и производить автоматизированное тестирование прямо из Postman.
Его основное предназначение — создавать коллекции с запросами к API. Коллекции позволяют удобно хранить запросы к тестируемому или разрабатываемому приложению, а новичку на проекте быстро разобраться с запросами к приложению. Кроме того, команда разработки может с легкостью использовать Postman для проектирования дизайна API. Для написания автоматизированных скриптов в Postman используется JavaScript.
Почему мы выбрали именно Cucumber и Spock?
В использовании SoapUI и Postman есть свои нюансы. Подобные тесты очень трудно поддерживать и проблематично использовать системы контроля версий (git, например) для их хранения.
Несмотря на то, что они широко используются в автоматизированном тестировании, SoapUI и Postman позволяют запускать тесты только локально и не могут применяться в системах интеграции (Jenkins). Для решения подобной задачи наша команда обратилась к Cucumber и Spock. С ними можно запускать тесты с Jenkins удаленно. Кроме того, эти фреймворки позволяют создавать автоматизированные смок-тесты, которые запускаются во время установки приложения. А вот с помощью Postman или SoapUI такое сделать не получится.
Spock и Cucumber отражают философию Behavior Driven Development — разработки через поведение. Идея BDD заключается в том, что перед тем, как написать какой-либо тест, необходимо сначала описать на предметно-ориентированном языке желаемый результат от добавляемой функциональности. После этого полученная документация передается разработчикам.
Спецификация поведения подается в полу формальном виде и имеет следующую структуру:
Заголовок (Title) — в сослагательной форме дается описание бизнес-цели.
Описание (Narrative) — в краткой форме даются ответы на следующие вопросы:
кто является заинтересованным лицом данной истории;
что входит в состав истории;
какую ценность эта история представляет для бизнеса.
Сценарии (Scenarios) — спецификация может содержать один и более сценариев, каждый из которых раскрывает одну из ситуаций поведения пользователя.
Сценарий обычно строится по одной и той же схеме:
одно или несколько начальных условий (Given);
событие, которое инициирует начало этого сценария (When);
ожидаемый результат или результаты (Then).
BDD не предоставляет каких-либо формальных правил, но настаивает на том, чтобы использовался ограниченный стандартный набор фраз, включающий все элементы спецификации поведения. В 2007 году «отец» BDD Дэн Норт предложил шаблон для спецификации, который обрел широкую популярность и впоследствии стал известен, как язык Gherkin.
На сегодня один из самых популярных инструментов BDD — Cucumber. Его авторы стремились объединить автоматизированные приемочные испытания, функциональные требования и документацию ПО в единый формат, понятный и техническим, и нетехническим участникам проекта.
Основой описания сценария тестирования являются шаги Given, When, Then. Каждому из них соответствует аннотация, которая с помощью регулярного выражения связывает метод со строкой в текстовом описании сценария. Шаги тестирования группируются в сценарии (Scenario), которые в свою очередь описывают определенную функциональность (Feature).
Для автоматизации описанных сценариев в Cucumber можно использовать Ruby, Java и Python. Тест записывается в виде Gherkin-нотации в отдельный файл с расширением *.feature. Этот файл может содержать один или несколько сценариев. Сценарии могут писать BA или мануальные QA. Далее специалист, занимающийся автоматизацией тестов, создает отдельный класс с реализацией шагов на определенном языке программирования.
С Cucumber фреймворком я познакомился во время написания сценариев поведения тестируемого API приложения. Точнее говоря, это был не сам Cucumber, а язык Gherkin и наши попытки описывать сценарии поведения приложения согласно правилам BDD. С точки зрения мануального тестировщика это интересный опыт. В команде было несколько мануальных тестировщиков, которые писали сценарии на Gherkin. Основная проблема состояла в сложности договориться с ними о едином формате описания каждого шага и создания набора шагов, которые могут повторяться в разных тестах, чтобы не дублировать их реализацию.
Feature: Test OpenWeather API
As a customer
In order to check weather
I want to get my city name in response.
Scenario Outline: Check if city name is returned correctly
When Sent request to openweathermap for “<cityReq>”
Then Check that 200 response code is returned
And Server returns correct city name “<cityResp>”
Examples
| cityReq | cityResp |
| “Kharkiv, UA” | “Kharkiv” |
| “London, GB” | “London” |
На примере выше представлена Gherkin-нотация сценария для тестирования открытого OpenWeather API приложения. Для примера я написал простой сценарий, который отправляет запрос с определенными параметрами на сервер приложения и затем проверяет ответ с этого сервера.
public class Stepdefs {
@when ( “Sent request to openweathermap for {cityReq} “ )
public void sent_request_to_ openweathermap ( String cityReq) {
HTTP Builder http = null;
try {
http = new HTTP Builder (testUrl);
String [ ] actualCity = cityReq.split ( regex: “, “ ) ;
Здесь в коде представлен пример класса Stepsdef на языке Java. Каждый шаг из feature файла привязывается к его реализации в Stepsdef классе с помощью аннотации (@Given, @When, @Then и тд.) и текста шага из feature файла.
Чтобы получить максимальную отдачу от Cucumber, нужно следовать принципам BDD, потому что Cucumber — только активатор для BDD.
Spock — это тестовая среда. Некоторые даже сказали бы «язык, построенный на базе языка Groovy». К этому фреймворку я обратился уже на другом проекте, где выступал в роли автоматизатора. Как я писал ранее, в Cucumber сценарии выполнения и реализация каждой конструкции разделены. Это позволяет составить удобочитаемые сценарии, но занимает много времени. Поэтому такой подход может быть непрактичным при написании реализации.
Описание шагов и их реализация в Spock находятся в одном groovy классе. Благодаря использованию в качестве основы платформы JUnit, этот фреймворк совместим со всеми популярными IDE (в частности, IntelliJ IDEA), различными инструментами сборки (Ant, Gradle, Maven) и CI-сервисами (continuous integration). Тестовый класс являет собой набор методов-сценариев с названиями в кавычках, подобные названиям сценариев в Cucumber. А поскольку эти классы являются производными от JUnit, есть возможность запускать их из IDE как обычный модульный тест Groovy. При этом мы получаем стандартные JUnit отчеты, что очень удобно при разработке и отладке автоматизированных тестов.
В Spock каждая фаза теста выделена в отдельный блок кода, который начинается с лейбла и завершается началом следующего блока кода или окончанием теста. Блок Given отвечает за настройку начальных условий теста. В блоке When — стимулятор, раздражитель системы, а в блоке Then — ответная реакция системы. Оба блока всегда используются вместе. Если есть возможность сократить конструкцию When-Then до одного выражения, можно использовать один блок Expect.
class WeatherTestSpec extends Specification {
@Shared def testUrl, testResponse
def setupSpec () {
testUrl = “http:// api. openweathermap.org”
testRequest = [ ‘APPID’ : “aaa” ]
testResponse = ‘ ‘
}
def ‘ Check if city name and coordinates is returned correctly’ () {
when: ‘ Sent request to openweathermap’
def http = new HTTPBuilder(testUrl)
testRequest.put ( ‘q’, cityReq)
testResponse = http.get( path : ‘/data/2.5/weather’ , query : testRequest )
then: “Check that 200 response code is returned”
testResponse. cod == 200
and: “Server returns correct city name”
testResponse. name == cityResp
where:
cityReq << [ “Kharkiv, UA”” , “London, GB”” ]
cityResp << [ “Kharkiv”” , “London ” ]
}
На примере выше представлен Groovy класс с тестом на Spock. Описание шага идет после символа «:» и представляет произвольную строку. При этом оно не является обязательным элементом. Spock допускает создание спецификации теста без описания шагов. Однако такая практика не считается общепринятой и в будущем приводит к затруднению понимания логики теста.
А что лучше?
И Cucumber, и Spock тесно связывают спецификацию на человеческом языке с тестовым кодом. Это прямое следствие парадигмы BDD, для поддержки которой создали обе платформы. Но Cucumber делает это более строго. Большие изменения описания шага на человеческом языке нарушат тестовый код, например, с отсутствующей реализацией шага, если ни одно регулярное выражение метода не соответствует заданному тексту шага. В то время как для Spock текст представляет собой произвольную строку после символа «:». Описание шага проверяется на соответствие в последующей реализации.
Cucumber четко разделяет спецификацию на человеческом языке и тестовым кодом. Для нетехнических специалистов, которые пишут или читают спецификации, это безусловно удобно. Да и сама суть BDD — это тесное сотрудничество Product Owner, BA, QA, архитекторов и разработчиков. Так что в случае с Cucumber спецификация будет согласована и понятна всем участникам проекта до начала разработки.
С другой стороны, Spock предлагает быстрое, краткое и однофайловое решение. Возможность Groovy использовать любую строку в качестве названия метода позволяет применять удобные для восприятия названия отдельного тестового сценария. Spock дает разработчикам единую точку для чтения и понимания спецификации и кода, который ее реализует. А еще давайте не забывать о «плюшках», с которыми поставляется Spock (например, расширенные возможности таблицы данных).
Также стоит отметить, что Cucumber подходит исключительно для интеграционных тестов. В то время, как Spock может использоваться и для Unit-тестов.
Было бы неправильно определять, какой из этих способов автоматизации тестирования API однозначно лучше. Мы в NIX, в зависимости от задач и целей, выбираем и то, и другое. SoapUI и Postman отлично подходят на начальных этапах автоматизации, когда в команде нет или очень мало автоматизаторов. С ростом команды логичнее переходить на Cucumber или Spock. У каждого из этих фреймворков есть свои преимущества, которые упрощают рутинные задачи QA-специалистов и делают процесс тестирования более эффективным.