Сучасна диджитал-освіта для дітей — безоплатне заняття в GoITeens ×
Mazda CX 5
×

Cucumber и Spock для автоматизации API-тестов. В чем польза этих фреймворков

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті

Привет, я — Владимир Пасюга, QA Engineer в NIX. В IT-сфере я уже 7 лет. 2,5 года был мануальным тестировщиком в биомедицинском проекте, где приложение включало UI и API части. В текущем проекте занимаюсь автоматизированным тестированием. Здесь приложение для медицинской сферы состоит только из API.

В данной статье я подробно расскажу о тестировании API приложений. Материал будет полезен начинающим QA. Вы узнаете, что такое API, какие инструменты наша команда использует для мануального тестирования API и какие технологии мы применяем для автоматизированного тестирования. Также поделюсь опытом применения фреймворков Cucumber и Spock, которые пригодятся вам для автоматизации API-тестов.

Коротко пробежимся по матчасти

Чтобы предметно говорить о тестировании 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 такое сделать не получится.

Особенности применения Cucumber и Spock фреймворков

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-специалистов и делают процесс тестирования более эффективным.

👍ПодобаєтьсяСподобалось10
До обраногоВ обраному1
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Я ж правильно понимаю что статья и комменты про апи тесты на джаве?
ребят, а может кто-нибудь объяснить почему вы используете вот это вот все вместо restassured?

RESTassured — это одна из возможных библиотек для тестирования rest Api.
Нам было удобно использовать Спок+груви.
В случае с кукумбером альтернативы особой не было. У нас была большая команда мануальных тестеровщиков и использование геркин нотаций позволяло всем членам команды писать сразу автоматизированные спецификации.

Spock — это считай что замена Junit/TestNG. Он решает одну простую проблему: добавляет текстовые блоки в тесты, которые потом можно вытащить в репорт. В этом есть огромный плюс в больших проектах: со временем не потеряется смысл теста. Даже если код перерефакторится в фигню, у тебя останется описание того, что именно тест проверял. Можно конечно запихивать всё в название метода в обычном Junit, но такое читается сильно сложнее и там будет только конечная цель теста, а не промежуточные этапы.

можно взять Allure и его прекрасные Step аннотации и получить красивый репорт.

Так Gherkin блоки и так вытягиваются в Аллюр. А со степами есть нюанс: анноташку нужно вешать на методы. По итогу у тебя или будут методы на группы методов вы разных вариациях, но не будет шума в отчёте, или будет полно гранулярных методов, но при этом дофига шума в отчёте. Ну и у тебя один фиг со временем потеряется intention теста, ибо останется только декларация происходящего.

Никакого Gherkin и прочего бддшного садомазо с Аллюром не нужно.

По итогу у тебя или будут методы на группы методов вы разных вариациях, но не будет шума в отчёте, или будет полно гранулярных методов, но при этом дофига шума в отчёте

Никакого шума — методы прячутся под одним основным в теле теста, прм желании можно развернуть и почитать вложенные шаги, но это редко когда нужно.

Ну и у тебя один фиг со временем потеряется intention теста, ибо останется только декларация происходящего.

Шта?

Никакого шума — методы прячутся под одним основным в теле теста, прм желании можно развернуть и почитать вложенные шаги, но это редко когда нужно.

Это если у тебя это всё оборачивается без потери смысла. Чаще у тебя просто будет получаться монстроузный метод с дофигищей параметров или пачка одинаковых методов, которые будут различаться одним словом в названии. Так что нужно чтобы тут еще повезло со спецификой проекта.

Шта?

Если ты пишешь тесты один раз и они потом не саппортятся, то такой проблемы у тебя не будет. А если твой продукт бодро развивается и тесты постоянно дописываются и старые меняются, то получается простая картина: из-за регулярных рефакторингов тест начинает проверять совсем не то, что должен. Особенно в большой команде. Кто-то заменил проверку, кто-то обернул всё в метод, сделал это неправильно и всё. И вот тут без человеческого описания становится совсем печально.

Чаще у тебя просто будет получаться монстроузный метод с дофигищей параметров или пачка одинаковых методов, которые будут различаться одним словом в названии.

ну тут уж как сам напишешь, тест-дизайн никто не отменял :)

Если ты пишешь тесты один раз и они потом не саппортятся, то такой проблемы у тебя не будет. А если твой продукт бодро развивается и тесты постоянно дописываются и старые меняются, то получается простая картина: из-за регулярных рефакторингов тест начинает проверять совсем не то, что должен. Особенно в большой команде. Кто-то заменил проверку, кто-то обернул всё в метод, сделал это неправильно и всё. И вот тут без человеческого описания становится совсем печально.

опять же — смотря как договоришься сотрудничать в команде.

TestNG/Junit и любой http client. Самоё простое решение. Зачем натягивать BDD туда где он не нужен? У вас бизнес аналитики пишут эти сценарии? Они являются одновременно требованиями? В них смотрят девелоперы, аналитики, менеджеры, заказчики? Если нет (а в 99% случаев это именно так), то это просто пустая трата времени. Особенно Cucumber. +20-30% эффорта на поддержку дополнительного слоя во фреймворке по сравнению с не бдд тулами. Spock получше будет, но все равно смысла особо в нем нет

BDD подход позволяет писать структурированные тесты.
Использование Cucumber имеет смысмл если в команде сценарии пишут люди не умеющие писать код (мануальные тестировщики, BA/PM), а автоматизаторы просто пишут код для ключевых фраз, которые описывабт шаги тестов. В моем случае команда мануальных тестеровщиков писали тесторые сценарии на Gherkin используя ключевые фразы шагов, автоматизированные командой автоматизаторов. Если тесты пишутся сразу автоматизатром, то использование Cucumber не имеет ни какого смысла.
Spock позволяет писать структурированные тесты, но без сложностей Cucumber.
Плюсом Spock является еще и то, что тестовые методы имеют удобочитаемые назавания и отделные блоки так же содержат четкие описание что делает каждый шаг. Такая структура позволяет новичку быстрее войти в проект.

И что действительно мануальные тестировщики пишут спеки по тому словарю который уже автоматизирован?

Если мануальщики и автоматизаторы — это разные люди, то может быть все это бдд и приносит пользу, но вообще-то инструмент не самая большая тут проблема. А если у еще и тестдизайном занимаются ВА/ПМ, то вообще.

у нас была именно такая ситуация. И я на кукумбер и весь БДД подход в самом начале смотрел именно с позиции мануальщика. И с точки зрения мануальщика писать тесты с помощью геркин-нотаций очень легко и быстро.

Spock — это считай что замена Junit/TestNG. Он решает одну простую проблему: добавляет текстовые блоки в тесты, которые потом можно вытащить в репорт. В этом есть огромный плюс в больших проектах: со временем не потеряется смысл теста. Даже если код перерефакторится в фигню, у тебя останется описание того, что именно тест проверял. Можно конечно запихивать всё в название метода в обычном Junit, но такое читается сильно сложнее и там будет только конечная цель теста, а не промежуточные этапы.

Дякую за статтю!
Дозволю собі прокоментувати кілька моментів:

проблематично использовать системы контроля версий

Postman має workspace — не зовсім git, але для командної роботи в принципі підходить (можна шарити колекції і тд)

SoapUI и Postman позволяют запускать тесты только локально и не могут применяться в системах интеграции (Jenkins).

не зовсім, в Postman є Newman — раннер колекцій в терміналі, що дозволяє інтегрувати його з СІ

Для решения подобной задачи наша команда обратилась к Cucumber и Spock.

загалом так, але якщо глянути глибше, то Cucumber/Spock не можна порівнювати з Postman/SoapUI, оскільки вони мають різні шляхи реалізації тестів.
Для першого рішення треба знати мову програмування, апі клієнт, тестову лібу для асертів, білд тулу, репортінгу тулу і ще й спроектувати фреймворк, щоб зручно і легко модифікувати/масштабувати тести.
Друге рішення вимагає створити колекцію ріквестів, написати кілька рядків асертів респонсу для кожного ріквесту і все, можна ранити і інтегрувати з СІ.

public void sent_request_to_ openweathermap ( String cityReq) {

тут зайвий пробіл перед openweathermap :)

Щодо Spock, то досить цікаво, бо раніше ніколи не стикався, але плюсую інших людей, що читабельність в нього супертяжка.

Загалом погоджуюсь, що юзати BDD підхід на проекті треба тільки в тому випадку, коли абсолютна вся команда пише в стилі BDD, інакше це просто зайвий рівень абстракції, який не приносить і ніколи не принесе ніякої користі.

P.S: також досить цікавий апі клієнт — Insomnia https://insomnia.rest/ (аналог Postman/SoapUI)

github.com/...​ckframework/spock-example
Вот тут можно посмотреть больше примеров использования Спока. Примеры совсем простецкие, правда.

На текущем проекте познакомился со споком. Сам я джавист и мне не понравилось.

Получается, что под видом некой эфемерной «удобности» на проект заносят другой язык с другим синтаксисом, который, имхо, имеет весьма плохую читабельность и весьма днищенскую поддержку в иде, которая иногда фейлит даже банальный компайл чек. Т.е. поддержка спока в иде вроде показывает что все ок, но на самом деле там компайл еррор внутри.

Я не вкурил зачем мне нужен еще один язык на проекте.

Под Спок можно писать на чистой Джаве же. Да и Груви — это Джава + синтаксический сахар. Считай что тот-же язык, но с плюшками. А вот кейс с компайл еррором я прям первый раз вижу. Реальное что там может быть неудобным — implicit throws.Типа ты хз что за эксепшен может вылететь. Но это становится траблой только когда пилишь продакшен код, а не в тестах.

Мы активно используем Spock как замену Mockito и JUnit для юнит тестов. У него очень удобная работа с моками и проверка результатов (можно вытягивать значение поля из списка объектов, и проверять их как список). Так же where: блок удобнее записывать таблицей аналогично Cucumber. Мы не пишем обычно дополнительный текст в where/then, а просто даём нормальное имя теста — в имя метода можно подставлять переменные из where, а аннотация @Unroll размножит этот тест для каждой комбинации данных — удобно потом отлавливать на какой именно комбинации свалился тест.

да, спасибо. @Unroll не добавил. Но в статье я тест указал посто для примера.

Postman позволяют запускать тесты только локально и не могут применяться в системах интеграции

у постмана есть newman который умеет в ci :)

Не использовал Spock на практике, но из примера выглядит менее читабельным и поддерживаемым чем Cucumber. Но спасибо за ваш опыт и статью :)

Во время чтения примера у меня прям кровь из глаз потекла... Такое ощущение что код спецом написан так нечитаемо... Спок как-раз улучшает читаемость, плюс более удобная параметризация тестов, удобная система плагинов, офигенно удобные фичи для юнит тестирования ну и возможность Геркин дескрипшены в отчёт выносить.

тест в споке я привел для примера как может один и тот же тест выглядеть в кукумбур на геркине и в спок. По хорошему HTTPBuilder нужно было в отдельный класс вынести а не в when все городить. Тогда будет более читабельно.

В примере спока код действительно не очень удобно читаем. В кукумбере код ответсвенный за каждый шаг вынесен в отдельный класс и его можно переиспользовать в нескольких спеках. В споке только копи паст блоков кода.

Там не в этом дело. Организация кода в фреймворке — это другое совсем. А в приведённом примере даже отсутствуют банальные отступы между блоками, из-за чего всё сливается в 1 кучу, которую очень сложно читать.
При прочих равных, тест раннер не особо влияет на правила организации кода. Правильно организованный код не будет копи-пастой целых блоков. Если в большинстве тестов используется один и тот-же код, это значит что такой код должен быть вынесен в отдельный метод или в сервис. Ну, кроме проверок.

learning.postman.com/...​integration-with-jenkins
та вроде можна в сі постмен пихнути

Якщо почитаєте своє посилання, то з’ясуєте, що в CI пхається зовсім не Постман :)

проблема постмана не столько в ci, сколько в поддержке кода теста на git.

А в чем именно проблема в поддержке кода теста на git? Я автоматизировала тестирование API с помощью Postman, интегрировала в CI/CD (Jenkins) с помощью newman, тесты хранятся вместе с проектом на git-e и никаких проблем не возникало.

Підписатись на коментарі