Подтвердить что ты не робот

Лучшая практика проверки теста огурца API REST

Попытка написать шаги функции огурца для теста REST API.

Я не уверен, какой подход лучше:

Given I log in with username and password
When I add one "tv" into my cart
And I check my cart
Then I should see the item "tv" is in my cart

или

Given the client authenticate with username and password
When the client send POST to "/cart/add" with body "{item: body}"    
Then the response code should be "200"
And the response body should expect "{success: true}"
When the client send GET to "/cart"    
Then the response code should be "200"
And the response body should expect "{"items": ["tv"]}"

Существует ли какое-либо соглашение, когда люди пытаются писать шаги огурца для API REST?

4b9b3361

Ответ 1

Я просто наткнулся на эту полезную статью: http://gregbee.ch/blog/effective-api-testing-with-cucumber

Подводя итог...

Scenario: List fruit
  Given the system knows about the following fruit:
    | name       | color  |
    | banana     | yellow |
    | strawberry | red    |
  When the client requests a list of fruit
  Then the response is a list containing 2 fruits
  And one fruit has the following attributes:
    | attribute | type   | value  |
    | name      | String | banana |
    | color     | String | yellow |
  And one fruit has the following attributes:
    | attribute | type   | value      |
    | name      | String | strawberry |
    | color     | String | red        |

Проверка результата против JSON - это сложная задача, потому что, если результатом является массив, элементы могут быть не такими же, как и то, как вы проверяете в тесте.

Ответ 2

Вот пример (достаточно близко) к тому, что Pragmatic Programmer "Книга огурцов" говорит о тестировании API REST через Cuke и, по-видимому, более тесно относится к вашему второму примеру:

Feature: Addresses
  In order to complete the information on the place
  I need an address

Scenario: Addresses
  Given the system knows about the following addresses:
   [INSERT TABLE HERE or GRAB FROM DATABASE]
  When client requests GET /addresses
  Then the response should be JSON:
  """
    [
     {"venue": "foo", "address": "bar"},
     { more stuff }
    ]
  """
STEP DEFINITION:

Given(/^the system knows about the following addresses:$/) do |addresses| 
# table is a Cucumber::Ast::Table
  File.open('addresses.json', 'w') do |io|
    io.write(addresses.hashes.to_json)
  end
end    

When(/^client requests GET (.*)$/) do |path|
   @last_response = HTTParty.get('local host url goes here' + path)
end

Then /^the response should be JSON:$/ do |json|
   JSON.parse(@last_response.body).should == JSON.parse(json)
end
ENV File:

require File.join(File.dirname(__FILE__), '..', '..', 'address_app')
require 'rack/test'
require 'json'
require 'sinatra'
require 'cucumber'
require 'httparty'
require 'childprocess'
require 'timeout'

server = ChildProcess.build("rackup", "--port", "9000")
server.start
Timeout.timeout(3) do
  loop do
    begin
      HTTParty.get('local host here')
      break
    rescue Errno::ECONNREFUSED => try_again
      sleep 0.1
    end
  end
end

at_exit do
  server.stop
end

Ответ 3

Я использую огурец для тестирования и, что более важно, документировать API, который я создал с помощью rails-api в моем текущем проекте. Я просмотрел некоторые инструменты для использования, и в итоге я использовал комбинацию cucumber-api-steps и json_spec. Это сработало для меня.

Существует никаких соглашений о том, как писать шаги огурца. Способ, которым вы пишете свои действия, зависит от того, как вы хотите использовать свой набор огурцов. Я использовал вывод огурца в качестве ссылки для наших Angular JS-клиентов для реализации API-клиента. Таким образом, мои шаги огурца содержали фактические запросы и ответы JSON вместе со кодом состояния для каждого сценария. Это сделало его очень легким для общения с клиентской командой всякий раз, когда что-то изменилось (особенно когда команда на стороне клиента физически не присутствовала на моем рабочем месте).

Каждый раз, когда я создавал или обновлял API, сервер CI запускал огурец как часть сборки и перемещал вывод в формате HTML в место "build_artifacts", которое можно было открыть в браузере. Разработчики клиентской стороны всегда получат самую последнюю ссылку.

Я написал все это в блоге о создании проверенного, документально подтвержденного и проверенного версиями JSON API, надеюсь, что это вам поможет.

Ответ 4

Одним из оригинальных намерений Cucumber, который способствует его дизайну, является преодоление разрыва между технической реализацией и людьми, которые знают бизнес-потребности, чтобы описания тестов могли быть написаны и/или поняты не разработчиками. Таким образом, это не очень подходит для подробных технических спецификаций или по отдельности.

Итак, это укажет мне на ваше первое тестовое описание, если это также причина, по которой вы используете Огурцы.

Нет серьезной проблемы с реализацией тестов, таких как вторая версия, Cucumber может ее поддерживать. Там, вероятно, не так много типов операторов, которые вам нужно будет анализировать. Но вы можете в конечном итоге немного бороться с тестовым каркасом или идти против вашего обоснования использования огурца в первую очередь.

Что касается соглашения, я не знаю достаточных тестов API REST на практике для комментариев, и ни один из них, который я видел, не использовал Cucumber в качестве основы.

Обновление: обозревая SO по этому вопросу, я нашел ссылку на это: https://github.com/jayzes/cucumber-api-steps, который больше похож на ваш второй формат.

Ответ 5

Я думаю, что первое лучше. Я бы поместил технику в классы и модули ruby. Например, например, модуль cart.add(items) в шаге "когда" и на этапе затем введите expect (cart.item).to include ( "items" = > a_string_matching (item))

Таким образом, классы и модули ruby ​​могут быть повторно использованы на других этапах функций. Например, например, возможно, у вас есть другой сценарий, который добавит несколько элементов в корзину, а затем проверит общую сумму.

Однако второй, я думаю, может сделать это как технические характеристики. Например, как общий/глобальный заголовок или запрос тела ожидается во всех api.

Ответ 7

Сейчас есть несколько библиотек для тестирования REST на стороне сервера с огурцом в Ruby. Вот пара:

Библиотека, которую я использовал для тестирования REST на стороне сервера с помощью огурца, Cucumber-API-Steps.

Cucumber-API-Steps

Здесь, как я напишу ваш тест, используя "oucum-api-steps" (рекомендуется):

@success
Scenario: Successfully add to cart
  Given I am logged in
  When I send a POST request to "/cart/add" with the following:
       | item | body |
  Then the response status should be "200"
  And the JSON response should have "success" with the text "true"
  When I send a GET request to "/cart"
  Then the response status should be "200"
  And the JSON response should be "{'items': ['tv']}"

И вот, как выглядят мои тесты, используя 'cucumber-api-steps':

@success
Scenario: Successfully log in
  Given I am logged out
  When I send a POST request to "/login" with:
       | username | [email protected] |
       | password | mypassword |
  Then the response status should be "200"
  And the JSON response should have "firstName" with the text "Katie"

Cucumber-API

Здесь, как я напишу ваш тест, используя 'огурец-api':

@success
Scenario: Successfully add to cart
  Given I am logged in
  When I send a POST request to "/cart/add"
       And I set JSON request body to '{item: body}'
  Then the response status should be "200"
  And the response should have key "success" with value "true"
  When I send a GET request to "/cart"
  Then the response status should be "200"
  And the response should follow "{'items': ['tv']}"

И вот как выглядят мои тесты, используя 'cucumber-api':

@success
Scenario: Successfully log in
  Given I am logged out
  When I send a POST request to "/login" with:
       | username | [email protected] |
       | password | mypassword |
  Then the response status should be "200"
  And the response should have key "firstName"
  • Примечание о Cucumber-API: в настоящее время не существует способа should have key "firstName" with value "Katie". Часть "со значением" еще не выполнена.
  • Также "Follow" ожидает файл JSON

Другой ресурс здесь, но он старый (2011).

Ответ 8

Я бы порекомендовал ваш первый сценарий.

Из моего собственного опыта я лично считаю, что наибольшее значение, которое вы получаете от использования BDD в качестве способа доставки ПО, - это когда вы делаете акцент на стоимости бизнеса.

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

Это известно как внешняя разработка.

Дополнительные тесты поведения системы могут использоваться и должны использоваться для покрытия технических требований, но я думаю, что в расходах, связанных с затратами, это меньше затрат, что часто требует много времени и трудоемкости большое количество сценариев.

Я рекомендую следующий подход:

1) Работайте с BAs и POs, чтобы разработать примеры поведения, которое они хотят, используя неспецифический язык (например, ваш первый пример).

2) Инженеры используют их для разработки разработки с первого подхода к тестированию, автоматизируя их как интеграционные тесты - с большинством ниже браузера (например, против вашего REST API) и большинства основных сценариев через браузер (если вы разрабатывают один).

3) Инженеры TDD используют код функции с модульными испытаниями, пока не пройдут как модульные тесты, так и примеры BDD.