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.