Статьи

Использование BDD с веб-сервисами: учебник с использованием JBehave и Thucydides

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 в действии для Мэннинга.