Behavior Driven Development (BDD) — это подход, который использует преобразования вокруг конкретных примеров для обнаружения, описания и формализации поведения системы. Инструменты BDD, такие как JBehave и Cucumber, часто используются для написания автоматизированного приемочного тестирования через Интернет. Но BDD также является отличным подходом, если вам необходимо разработать веб-сервис. В этой статье мы увидим, как вы можете использовать JBehave и Thucydides для выражения и автоматизации четких, значимых критериев принятия для веб-службы RESTful. (Общий подход также будет работать для веб-службы, использующей SOAP.) Мы также увидим, как отчеты (или «живая документация», в терминах BDD), генерируемые этими автоматическими критериями принятия, также отлично справляются с документированием веб-службы.
Thucydides — это библиотека отчетов и приемочного тестирования BDD с открытым исходным кодом, которая используется вместе с другими инструментами тестирования, такими как среды тестирования BDD, такие как JBehave , Cucumber или SpecFlow , или более традиционные библиотеки, такие как JUnit.
Веб-сервисы легко моделировать и тестировать, используя методы BDD, во многих отношениях больше, чем веб-приложения. Веб-сервисы (или должны быть) относительно легко описать в поведенческих терминах. Они принимают четко определенный набор входных параметров и возвращают четко определенный результат. Таким образом, они хорошо вписываются в типичный способ описания поведения в стиле BDD, используя формат « задано когда »:
Given some precondition When something happens Then a particular outcome is expected
В оставшейся части этой статьи мы увидим, как описать и автоматизировать поведение веб-службы таким образом. Для этого вам понадобятся Java и Maven, установленные на вашем компьютере (я использовал Java 8 и Maven 3.2.1). Исходный код также доступен на Github (https://github.com/thucydides-webtests/webservice-demo). Если вы хотите построить проект с нуля, сначала создайте новый проект Thucydides / JBehave из командной строки следующим образом:
mvn archetype:generate -Dfilter=thucydides-jbehave
Введите любые имена артефактов и групп, которые вам нравятся: для этого примера это не имеет значения:
Choose archetype: 1: local -> net.thucydides:thucydides-jbehave-archetype (Thucydides automated acceptance testing project using Selenium 2, JUnit and JBehave) Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): : 1 Define value for property 'groupId': : com.wakaleo.training.webservices Define value for property 'artifactId': : bdddemo Define value for property 'version': 1.0-SNAPSHOT: : 1.0.0-SNAPSHOT Define value for property 'package': com.wakaleo.training.webservices: : Confirm properties configuration: groupId: com.wakaleo.training.webservices artifactId: bdddemo version: 1.0.0-SNAPSHOT package: com.wakaleo.training.webservices Y: :
Это создаст простой проект с JBehave и Thucydides. Он предназначен для тестирования веб-приложений, но его достаточно легко адаптировать для работы с веб-сервисом RESTful. Нам не нужен демонстрационный код, поэтому вы можете безопасно удалить все классы Java (за исключением класса AcceptanceTestSuite) и файлы JBehave .story.
Теперь обновите pom.xml
файл, чтобы использовать последнюю версию Thucydides, например
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <thucydides.version>0.9.239</thucydides.version> <thucydides.jbehave.version>0.9.235</thucydides.jbehave.version> </properties>
Как только вы это сделаете, вам нужно определить некоторые истории и сценарии для вашего веб-сервиса. Для простоты в этом примере мы будем работать с двумя простыми требованиями: сокращение и расширение URL-адресов с помощью службы сокращения URL- адресов Google . Мы опишем их в двух файлах истории JBehave. Создайте stories
каталог в src/test/resources
и создайте подкаталог для каждого требования с именем expanding_urls
и shortening_urls
. Каждый каталог представляет возможность высокого уровня, которую мы хотим реализовать. Внутри этих каталогов мы размещаем файлы историй JBehave ( expanding_urls.story
и shortening_urls.story
) для необходимых нам функций. (В данном случае эта структура немного излишня, но она полезна для реальных проектов, где требования более многочисленны и сложны). Эта структура показана здесь:
[Img_assist | NID = 167149 | название = | убывание = | ссылка = всплывающее окно | ALIGN = слева | ширина = 600 | Высота = 234]
Файлы истории содержат сценарии типа « когда тогда», в стиле BDD , описывающие поведение веб-службы. Когда вы разрабатываете веб-сервис с использованием BDD, вы можете выражать поведение на двух уровнях (и многие проекты используют оба). Первый подход заключается в описании данных JSON в сценариях BDD, как показано здесь:
Scenario: Shorten Urls Given a url http://www.google.com When I request the shortened form of this url Then I should obtain the following JSON message: { "kind": "urlshortener#url", "id": "http://goo.gl/fbsS", "longUrl": "http://www.google.com/" }
Это хорошо работает, если ваши сценарии имеют очень техническую аудиторию (например, если вы пишете веб-сервис исключительно для других разработчиков), и если содержимое JSON остается простым. Это также хороший способ согласовать формат JSON, который создаст веб-сервис. Но если вам нужно обсудить сценарий с бизнесом, BA или даже с тестировщиками, и / или если JSON, который вы возвращаете, является более сложным, включение JSON в сценарии не такая хорошая идея. Этот подход также плохо работает для веб-служб на основе SOAP, где структура сообщений XML является более сложной. Лучшим подходом в этих ситуациях является описание входных и ожидаемых результатов в бизнес-терминах, а затем преобразование их в соответствующий формат JSON в определении шага:
Scenario: Shorten URLs Given a url <providedUrl> When I request the shortened form of this url Then the shortened form should be <expectedUrl> Examples: | providedUrl | expectedUrl | | http://www.google.com/ | http://goo.gl/fbsS | | http://www.amazon.com/ | http://goo.gl/xj57 |
Давайте посмотрим, как мы могли бы автоматизировать этот сценарий, используя JBehave и Thucydides. Во-первых, нам нужно написать JBehave определения шагов в Java для каждого из заданных / когда / затем шагов в сценариях, которые мы только что видели. Создайте класс с именем ProcessingUrls
рядом с AcceptanceTestSuite
классом или в подкаталоге под этим классом.
[Img_assist | NID = 167151 | название = | убывание = | ссылка = всплывающее окно | ALIGN = слева | ширина = 600 | высота = 240]
UrlShortenerSteps
для выполнения тяжелой работы. Этот подход делает более четкое отделение от
того, что
и
как
, и облегчает повторное использование — например, если нам нужно изменить базовый веб-сервис, который мы использовали для реализации функции сокращения URL, эти определения шагов должны остаться неизменными:
public class ProcessingUrls { String providedUrl; String returnedMessage; @Steps UrlShortenerSteps urlShortener; @Given("a url <providedUrl>") public void givenAUrl(String providedUrl) { this.providedUrl = providedUrl; } @When("I request the shortened form of this url") public void shortenUrl() { returnedMessage = urlShortener.shorten(providedUrl); } @When("I request the expanded form of this url") public void expandUrl() { returnedMessage = urlShortener.expand(providedUrl); } @Then("the shortened form should be <expectedUrl>") public void shortenedFormShouldBe(String expectedUrl) throws JSONException { urlShortener.response_should_contain_shortened_url(returnedMessage, expectedUrl); } }
Теперь добавьте UrlShortenerSteps
класс. Этот класс содержит реальный тестовый код, который взаимодействует с вашим веб-сервисом. Для этого мы могли бы использовать любой клиент Java REST, но здесь мы используем Spring RestTemplate . Полный класс выглядит так:
public class UrlShortenerSteps extends ScenarioSteps { RestTemplate restTemplate; public UrlShortenerSteps() { restTemplate = new RestTemplate(); } @Step("longUrl={0}") public String shorten(String providedUrl) { Map<String, String> urlForm = new HashMap<String, String>(); urlForm.put("longUrl", providedUrl); return restTemplate.postForObject("https://www.googleapis.com/urlshortener/v1/url", urlForm, String.class); } @Step("shortUrl={0}") public String expand(String providedUrl) { return restTemplate.getForObject("https://www.googleapis.com/urlshortener/v1/url?shortUrl={shortUrl}", String.class, providedUrl); } @Step public void response_should_contain_shortened_url(String returnedMessage, String expectedUrl) throws JSONException { String expectedJSONMessage = "{'id':'" + expectedUrl + "'}"; JSONAssert.assertEquals(expectedJSONMessage, returnedMessage, JSONCompareMode.LENIENT); } @Step public void response_should_contain_long_url(String returnedMessage, String expectedUrl) throws JSONException { String expectedJSONMessage = "{'longUrl':'" + expectedUrl + "'}"; JSONAssert.assertEquals(expectedJSONMessage, returnedMessage, JSONCompareMode.LENIENT); } }
Класс Spring RestTemplate — это простой способ взаимодействия с веб-службой с минимальными усилиями. В этом shorten()
методе мы вызываем urlshortener
веб-сервис с помощью операции POST для сокращения URL:
@Step("longUrl={0}") public String shorten(String providedUrl) { Map<String, String> urlForm = new HashMap<String, String>(); urlForm.put("longUrl", providedUrl); return restTemplate.postForObject("https://www.googleapis.com/urlshortener/v1/url", urlForm, String.class); }
Услугу расширения еще проще вызвать, поскольку она использует простую операцию GET:
@Step("shortUrl={0}") public String expand(String providedUrl) { return restTemplate.getForObject("https://www.googleapis.com/urlshortener/v1/url?shortUrl={shortUrl}", String.class, providedUrl); }
В обоих случаях мы возвращаем документ JSON, созданный веб-службой, и проверяем содержимое на шаге then с помощью библиотеки JSONAssert . Существует много библиотек, которые можно использовать для проверки данных JSON, возвращаемых веб-службой. Если вам нужно проверить всю структуру JSON, JSONAssert предоставляет удобный API для этого. JSONAssert позволяет сопоставлять документы JSON строго (все элементы должны совпадать, в правильном порядке) или снисходительно (вы указываете только подмножество полей, которые должны появляться в документе JSON, независимо от порядка).
Следующий шаг проверяет, содержит ли документ JSON поле id с ожидаемым значением URL. Полный документ JSON появится в отчетах, поскольку он передается в качестве параметра на этот шаг.
@Step public void response_should_contain_shortened_url(String returnedMessage, String expectedUrl) throws JSONException { String expectedJSONMessage = "{'id':'" + expectedUrl + "'}"; JSONAssert.assertEquals(expectedJSONMessage, returnedMessage, JSONCompareMode.LENIENT); }
Вы можете запустить эти сценарии, используя mvn verify
из командной строки: это создаст отчеты об испытаниях и живую документацию Thucydides для этих сценариев. После запуска mvn verify
откройте index.html
файл в target/site/thucydides
каталоге. Это дает обзор результатов теста. Если вы нажмете на вкладку « Требования », вы увидите обзор результатов с точки зрения возможностей и возможностей. Мы называем это «функцией покрытия»:
Разверните результаты теста «Сократить URL-адреса». Здесь вы увидите краткое изложение истории или функции, проиллюстрированной этим сценарием:
[Img_assist | NID = 167153 | название = | убывание = | ссылка = всплывающее окно | Align = нет | ширина = 600 | Высота = 324]
И если вы прокрутите дальше вниз, вы увидите детали того, как этот веб-сервис был протестирован, включая документ JSON, возвращаемый сервисом:
[Img_assist | нидь = 167155 | название = | убывание = | ссылка = всплывающее окно | Align = нет | ширина = 640 | Высота = 346]
BDD отлично подходит для разработки и тестирования веб-сервисов. Если вы хотите узнать больше о BDD, обязательно посетите семинары по BDD , TDD и автоматизации тестирования, которые мы проводим в мае в Сиднее и Мельбурне!
Джон, известный международный деятель в области разработки, основанной на поведении, автоматизированного тестирования и оптимизации жизненного цикла программного обеспечения, помогает организациям во всем мире улучшить свои методы гибкой разработки и оптимизировать процессы и инфраструктуры Java-разработки. Он является автором нескольких книг, в последнее время BDD в действии для Мэннинга.