RESTful API Testing with Behat and Guzzle

Behat and Guzzle

Behat is a behaviour driven development framework for the PHP application. Behat can be used for acceptance testing and api testing.

Guzzle is PHP HTTP client to work with HTTP and web services. You can read more about Guzzle on the official website . We can use combination of the Behat and Guzzle for the testing of the REST API. In this post, we will see how to use Guzzle http  for testing GitHub web services.

Behat in Action

Let’s do some action now. We will install behat, create feature simple file and implement step definitions.

Installation & Config

Let’s create our composer.json to install all the dependencies with composer.

$ mkdir RESTful-Behat
$ cd RESTful-Behat
$ vim composer.json 

{
    "require": {
        "behat/behat": "2.4.0",
        "guzzle/guzzle": "2.4.*",
        "guzzlehttp/guzzle": "4.*"
    },
    "config": {
        "bin-dir": "bin/"
    }
}

Now, we need to download composer and install all these dependencies

$curl http://getcomposer.org/installer | php
$php composer.phar install

This will install all the dependencies in the ‘vendor’ directory. Now we will create config file for behat.

# behat.yml
default:
    context:
        parameters:
            base_url: https://api.github.com

Note, we have created basic config for the behat. Now initialise Behat so that, Behat will create ‘bootstrap’ directory and ‘FeatureContext.php’ file.

$ ./bin/behat --init

Create Feature file

In order to test the GitHub’s REST API with Behat, we need to create a feature file in the plain english. Our feature file should look like this:

$ vim github_rest_api.feature

Feature: GitHub RestFul Api Testing with Behat  

 As a behat user
 I want to test restful api of the GitHub
 So that it will bring smile for behat community

Scenario: GitHub behat Demo Api 
  Given I request "/repos/Shashikant86/BehatDemo" 
  Then the response should be JSON
  And the response status code should be 200
  And the response has a "name" property
  And the "name" property equals "BehatDemo"

As we read the feature file, we can understand that we are checking response format, response code and properties of the response a.k.a response body. At this point, we need to run ‘behat’ to get undefined steps. We need to implement these steps in the ‘FeatureContext.php’ file.

Step Definitions

Now, it’s time to implement step definitions using all the methods of the Guzzle Http library.

$ vim features/bootstrap/FeatureContext.php

<?php

use Behat\Behat\Context\ClosuredContextInterface,
    Behat\Behat\Context\TranslatedContextInterface,
    Behat\Behat\Context\BehatContext,
    Behat\Behat\Exception\PendingException;
use Behat\Gherkin\Node\PyStringNode,
    Behat\Gherkin\Node\TableNode;
use GuzzleHttp\Client;     

class FeatureContext extends BehatContext
{
    public $_response;
    public $_client;
    private $_parameters = array();
    /**
     * Initializes context.
     * Every scenario gets it's own context object.
     *
     * @param   array   $parameters     context parameters (set them up through behat.yml)
     */
    public function __construct(array $parameters)
    {

        $this->_parameters = $parameters;
        $baseUrl = $this->getParameter('base_url');
        $client = new Client(['base_url' => $baseUrl]);
        $this->_client = $client;
    }

    public function getParameter($name)
    {
        if (count($this->_parameters) === 0) {
            throw new \Exception('Parameters not loaded!');
        } else {
            $parameters = $this->_parameters;
            return (isset($parameters[$name])) ? $parameters[$name] : null;
        }
    }

    /**
     * @When /^I request "([^"]*)"$/
     */
    public function iRequest($uri)
    {
        $request = $this->_client->get($uri);
        $this->_response = $request;
    }

    /**
     * @Then /^the response should be JSON$/
     */
    public function theResponseShouldBeJson()
    {
        $data = json_decode($this->_response->getBody(true));
        if (empty($data)) { throw new Exception("Response was not JSON\n" . $this->_response);
       }
    }

    /**
     * @Then /^the response status code should be (\d+)$/
     */
    public function theResponseStatusCodeShouldBe($httpStatus)
    {
        if ((string)$this->_response->getStatusCode() !== $httpStatus) {
            throw new \Exception('HTTP code does not match '.$httpStatus.
                ' (actual: '.$this->_response->getStatusCode().')');
        }
    }  

    /**
     * @Given /^the response has a "([^"]*)" property$/
     */
    public function theResponseHasAProperty($propertyName)
    {
        $data = json_decode($this->_response->getBody(true));
        if (!empty($data)) {
            if (!isset($data->$propertyName)) {
                throw new Exception("Property '".$propertyName."' is not set!\n");
            }
        } else {
            throw new Exception("Response was not JSON\n" . $this->_response->getBody(true));
        }
    }
     /**
     * @Then /^the "([^"]*)" property equals "([^"]*)"$/
     */
    public function thePropertyEquals($propertyName, $propertyValue)
    {
        $data = json_decode($this->_response->getBody(true));

        if (!empty($data)) {
            if (!isset($data->$propertyName)) {
                throw new Exception("Property '".$propertyName."' is not set!\n");
            }
            if ($data->$propertyName !== $propertyValue) {
                throw new \Exception('Property value mismatch! (given: '.$propertyValue.', match: '.$data->$propertyName.')');
            }
        } else {
            throw new Exception("Response was not JSON\n" . $this->_response->getBody(true));
        }
    }
}

We have implemented all the steps to test GitHub REST API. At this point, we will see all the steps has been passing

behat-restful

 

GitHub-Code

The source code for this demo is available on the GitHub at ‘RESTful-Behat‘ repo. You can try this by yourself

https://github.com/Shashikant86/RESTful-Behat

 $ git clone git@github.com:Shashikant86/RESTful-Behat.git
 $ cd RESTful-Behat
 $curl http://getcomposer.org/installer | php
 $php composer.phar install
 $./bin/behat

 Video-Demo

Watch video demo of this demo on youtube

HAPPY API TESTING !!