REST API test cucumber steps best practice REST API test cucumber steps best practice ruby ruby

REST API test cucumber steps best practice


I just stumbled on this helpful article: https://www.gregbeech.com/2014/01/19/effective-api-testing-with-cucumber/

To summarize...

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        |

Validating a result against JSON is tricky business because if the result is an array, the elements may not be the same order as how you are validating in the test.

Edit: Updated link using finderAUT's comment. Thanks!


Here's a (close enough) example to what the Pragmatic Programmer's "the Cucumber Book" says about testing REST APIs via Cuke,and it seems to more closely relate to your second example:

Feature: Addresses  In order to complete the information on the place  I need an addressScenario: 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)  endend    When(/^client requests GET (.*)$/) do |path|   @last_response = HTTParty.get('local host url goes here' + path)endThen /^the response should be JSON:$/ do |json|   JSON.parse(@last_response.body).should == JSON.parse(json)endENV 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.startTimeout.timeout(3) do  loop do    begin      HTTParty.get('local host here')      break    rescue Errno::ECONNREFUSED => try_again      sleep 0.1    end  endendat_exit do  server.stopend


I've been using cucumber to test and more importantly to document the API that I created using rails-api in my current project. I looked around for some tools to use and I ended up using a combination of cucumber-api-steps and json_spec. It worked well for me.

There is no convention on how to write the cucumber steps. The way you write your steps depends on how you want to use your cucumber suite. I used the cucumber output as the reference for our Angular JS client devs to implement the API client. So my cucumber steps contained the actual JSON requests and responses along with the status code for each scenario. This made it really easy to communicate with a client side team whenever something changed ( especially when the client side team was not physically present at my workplace ).

Everytime I would create or update an API, the CI server would run cucumber as part of the build and move the HTML formatted output to a "build_artifacts" location that can be opened in the browser. The client side devs would always get the most recent reference that way.

I've written all of this down in a blog post about creating a tested, documented and versioned JSON API, hope it helps you in some way.