Writing Dredd Hooks In Python

Build Status

GitHub repository

Python hooks are using Dredd’s hooks handler socket interface. For using Python hooks in Dredd you have to have Dredd already installed


$ pip install dredd_hooks


$ dredd apiary.apib --language=python --hookfiles=./hooks*.py

API Reference

Module dredd_hooks imports following decorators:

  1. before_each, before_each_validation, after_each

  2. before, before_validation, after

  3. before_all, after_all

Refer to Dredd execution life-cycle to find when is each hook function executed.

Using Python API

Example usage of all methods in

import dredd_hooks as hooks

def my_before_all_hook(transactions):
  print('before all')

def my_before_each_hook(transaction):
  print('before each')

def my_before_hook(transaction):

def my_before_each_validation_hook(transaction):
  print('before each validation')

def my_before_validation_hook(transaction):
  print('before validations')

def my_after_hook(transaction):

def my_after_each(transaction):

def my_after_all_hook(transactions):


More complex examples are to be found in the Github repository under the examples directory. If you want to share your own, don’t hesitate and sumbit a PR.

How to Skip Tests

Any test step can be skipped by setting skip property of the transaction object to true.

import dredd_hooks as hooks

@hooks.before("Machines > Machines collection > Get Machines")
def skip_test(transaction):
  transaction['skip'] = True

Sharing Data Between Steps in Request Stash

If you want to test some API workflow, you may pass data between test steps using the response stash.

import json
import dredd_hooks as hooks

response_stash = {}

@hooks.after("Machines > Machines collection > Create Machine")
def save_response_to_stash(transaction):
  # saving HTTP response to the stash
  response_stash[transaction['name']] = transaction['real']

@hooks.before("Machines > Machine > Delete a machine")
def add_machine_id_to_request(transaction):
  #reusing data from previous response here
  parsed_body = json.loads(response_stash['Machines > Machines collection > Create Machine'])
  machine_id = parsed_body['id']
  #replacing id in URL with stashed id from previous response
  transaction['fullPath'] = transaction['fullPath'].replace('42', machine_id)

Failing Tests Programmatically

You can fail any step by setting fail property on transaction object to true or any string with descriptive message.

import dredd_hooks as hooks

@hooks.before("Machines > Machines collection > Get Machines")
def fail_transaction(transaction):
  transaction['fail'] = "Some failing message"

Modifying Transaction Request Body Prior to Execution

import json
import dredd_hooks as hooks

@hooks.before("Machines > Machines collection > Get Machines")
def add_value_to_body(transaction):
  # parse request body from API description
  request_body = json.loads(transaction['request']['body'])

  # modify request body here
  request_body['someKey'] = 'some new value'

  # stringify the new body to request
  transaction['request']['body'] = json.dumps(request_body)

Adding or Changing URI Query Parameters to All Requests

import dredd_hooks as hooks

def add_api_key(transaction):
  # add query parameter to each transaction here
  param_to_add = "api-key=23456"

  if '?' in transaction['fullPath']:
    transaction['fullPath'] = ''.join((transaction['fullPath'], "&", param_to_add))
    transaction['fullPath'] = ''.join((transaction['fullPath'], "?", param_to_add))

Handling sessions

import json
import dredd_hooks as hooks

stash = {}

# hook to retrieve session on a login
@hooks.after('Auth > /remoteauth/userpass > POST')
def stash_session_id(transaction):
  parsed_body = json.loads(transaction['real']['body'])
  stash['token'] = parsed_body['sessionId']

# hook to set the session cookie in all following requests
def add_session_cookie(transaction):
  if 'token' in stash:
    transaction['request']['headers']['Cookie'] = "id=" + stash['token']

Remove trailing newline character in expected plain text bodies

import dredd_hooks as hooks

def remove_trailing_newline(transaction):
  if transaction['expected']['headers']['Content-Type'] == 'text/plain':
    transaction['expected']['body'] = transaction['expected']['body'].rstrip()