How to build an automated API test framework - Part 3

So here we are. The final post on building an automated API framework. We’ve covered a lot of ground already so if you if you haven’t already I would recommend reading the first post on creating a framework with basic checks followed by the second post on extending the framework to handle POST requests. If you are all caught up then let’s continue…

Before we start let’s take a look at what we have so far:

  • spec stores our automated checks
  • api a library of API endpoints we use in spec to communication with restful-booker
  • payloads a suite of builders to create payloads for POST requests
  • gemfile / Rakefile manages the running of our framework and it’s dependencies

In the previous posts we’ve focused on creating basic checks around GET and POST endpoints, but what if we need to create something more complex?

Extending the framework further

For our next check, we want to turn our attention to the DELETE endpoint of restful-booker. The DELETE action itself is simple but there are a few actions we need to cover before executing the DELETE such as:

  • Create a booking for deletion and store the ID for later use
  • Send a request to the /auth endpoint to get a token to use in the DELETE request

Before we create the check itself lets extend our API library. First, We need to add an additional method in api/booking.rb

def delete_booking(id, token)
    begin
      return RestClient.delete 'http://localhost:3001/booking/' + id.to_s, :cookie => 'token=' + token
    rescue => e
      return e.response
    end
  end

Next, we need to create a new file in api/ named authorise.rb and add the following:

require 'rest-client'

module Authorise

  def post_credentials(payload)
    begin
      return RestClient.post 'http://localhost:3001/auth', payload, :content_type => :json
    rescue => e
      return e.to_s
    end
  end

end

Next, /auth requires a payload with our username and password so let’s create a new builder in payloads

class AuthorisePayload

  attr_accessor :username, :password

  def initialize(&block)
    instance_eval &block if block_given?
  end

  def toJson
    return "{
        \"username\": \"#{username}\",
        \"password\": \"#{password}\"
    }"
  end

end

Also don’t forget to add require './api/authorise' and require './payloads/authorise_payload' to spec_helper.rb

Creating the DELETE check

With the api and payloads files added let’s create our check first include the Authorise module from api in integration_spec.rb by adding the following under the Booking include

include Authorise

Then create the check itself

it('DELETE /booking/{id} should return a 200') do
    payload = BookingPayload.new do
      self.firstname = 'Sally'
      self.lastname = 'Jenkins'
      self.totalprice = 111
      self.depositpaid = true
      self.checkin = '11-11-2010'
      self.checkout = '12-11-2010'
      self.additionalneeds = 'Breakfast'
    end

    created_response = Booking.create_booking(payload.toJson, :json)

    auth_payload = AuthorisePayload.new do
      self.username = "admin"
      self.password = "password123"
    end

    auth_response = Authorise.post_credentials(auth_payload.toJson)

    delete_response = Booking.delete_booking(JSON.parse(created_response.body)["bookingid"].to_i, JSON.parse(auth_response.body)["token"])
    
    expect(delete_response.code).to be(201)
  end

So let’s talk through what’s going on in this check:

  1. First, we create a booking payload and use create_booking to create the booking we plan to delete. We also store the response in created_response for later use.
  2. Next are the payload and request to authenticate with restful-booker. Again, we store the response in auth_response for use in the delete request
  3. Finally, we take the booking ID for created_response to determine which booking to delete and we take the token value from auth_response to use in our Cookie header to allow us to make the request. We then assert on the response code.

Conclusion

So what we have created is a check that depends on multiple requests to be called that share various bits of information to be used to build further requests. Using this process we can create user workflows through the application that are much more sophisticated than a simple check on a single API call.

Going forward

And that’s it! A copy of the framework can be found here on GitHub for you to compare against. Before I finished I challenge you to take your copy of the framework and extend it. Why not try:

  • Creating a check for the PUT endpoint in restful-booker
  • Extend the API library to work on different environments
  • Use the framework structure to create a series of checks against a different application