Automatic testing of (RESTful) API documentation API Days Australia, February 2017 By Rouven Weßling ( ) Ecosystem Developer / Developer Evangelist, Contentful @RouvenWessling photo credit: bySydney Harbour Bridge, Australia Lenny K Photography (CC-BY)
A content management developer platform with an API at its core.
What do you do?
Powered by
A new look.
Documentation will be wrong
Users hate that
It's all in the spec api blueprint A powerful high-level API description language for web APIs.
## Questions Collection [/questions] ### Create a New Question [POST] You may create your own question using this action. It takes a JSON object containing a question and a collection of answers in the form of choices. + Request (application/json) { "question": "Favourite programming language?", "choices": [ "Swift", "Python", "Objective-C", "Ruby" ] } + Response 201 (application/json) + Headers Location: /questions/2 + Body { "question": "Favourite programming language?", "published_at": "2015-08-05T08:40:51.620Z", "choices": [ { "choice": "Swift",
Let's get testing DREDD No more outdated API documentation.
Testing read-only node_modules/.bin/dredd cma.apib https://api.contentful.com -m GET
Hooks beforeAll called at the beginning of the whole test run beforeEach called before each HTTP transaction before called before some specific HTTP transaction beforeEachValidation called before each HTTP transaction is validated beforeValidation called before some specific HTTP transaction is validated after called a er some specific HTTP transaction regardless its result afterEach called a er each HTTP transaction afterAll called a er whole test run
Hooks node_modules/.bin/dredd cma.apib https://api.contentful.com --hookfiles=./test-hooks.js -m GET
Skipping Tests var hooks = require('hooks'); hooks.before( "Webhook calls > Webhook call details > Get the webhook call details", function (transaction) { transaction.skip = true; });
Mutating data var hooks = require('hooks'); hooks.before( "Entries > Delete an Entry", function (transaction) { client.createEntry(entry, "1234") });
Rate limiting var hooks = require('hooks'); const DELAY = 1000/6.0; hooks.afterEach(function(transaction, done) { setTimeout(done, DELAY); });
Changing request data var hooks = require('hooks'); hooks.beforeEach(function (transaction, done) { transaction.fullPath = transaction.fullPath.replace('fp91oelsziea', 'gbkxklvmolc1'); done(); });
Chai assertions var hooks = require('hooks'); var assert = require('chai').assert; hooks.afterEach(function(transaction, done) { if (!transaction.skip) { assert.match(transaction.real.headers['x-contentful-request-id'], /^content-api:[a-zA-Z0-9]{22}$/ } done(); });
Security
Censor private data var hooks = require('hooks'); const SECRET_HEADERS = ['Authorization'].map(header => header.toLowerCase()); hooks.afterEachValidation(function(transaction, done) { Object.keys(transaction.request.headers).forEach(function(key) { if (SECRET_HEADERS.indexOf(key.toLowerCase()) > -1) { transaction.request.headers[key] = "***HIDDEN SECRET DATA***"; } }); done(); });
CI the beast
Conclusion Base your documentation on an API spec Test that spec Make it part of your CI Don't substitute your integration tests
Slides available on Slideshare: http://www.slideshare.net/rwessling/ Follow me on Twitter: @RouvenWessling
Meetup Thursday, March 2, 2017 7:00 pm Pivotal Labs, Level 11, 155 Clarence Street, Sydney https://www.meetup.com/Contentful-User-Meetup-Sydney/events/237520492/

API Days Australia - Automatic Testing of (RESTful) API Documentation

  • 1.
    Automatic testing of (RESTful)API documentation API Days Australia, February 2017 By Rouven Weßling ( ) Ecosystem Developer / Developer Evangelist, Contentful @RouvenWessling photo credit: bySydney Harbour Bridge, Australia Lenny K Photography (CC-BY)
  • 2.
    A content managementdeveloper platform with an API at its core.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
    It's all inthe spec api blueprint A powerful high-level API description language for web APIs.
  • 10.
    ## Questions Collection[/questions] ### Create a New Question [POST] You may create your own question using this action. It takes a JSON object containing a question and a collection of answers in the form of choices. + Request (application/json) { "question": "Favourite programming language?", "choices": [ "Swift", "Python", "Objective-C", "Ruby" ] } + Response 201 (application/json) + Headers Location: /questions/2 + Body { "question": "Favourite programming language?", "published_at": "2015-08-05T08:40:51.620Z", "choices": [ { "choice": "Swift",
  • 11.
    Let's get testing DREDD Nomore outdated API documentation.
  • 12.
    Testing read-only node_modules/.bin/dredd cma.apibhttps://api.contentful.com -m GET
  • 15.
    Hooks beforeAll called atthe beginning of the whole test run beforeEach called before each HTTP transaction before called before some specific HTTP transaction beforeEachValidation called before each HTTP transaction is validated beforeValidation called before some specific HTTP transaction is validated after called a er some specific HTTP transaction regardless its result afterEach called a er each HTTP transaction afterAll called a er whole test run
  • 16.
  • 17.
    Skipping Tests var hooks= require('hooks'); hooks.before( "Webhook calls > Webhook call details > Get the webhook call details", function (transaction) { transaction.skip = true; });
  • 18.
    Mutating data var hooks= require('hooks'); hooks.before( "Entries > Delete an Entry", function (transaction) { client.createEntry(entry, "1234") });
  • 19.
    Rate limiting var hooks= require('hooks'); const DELAY = 1000/6.0; hooks.afterEach(function(transaction, done) { setTimeout(done, DELAY); });
  • 20.
    Changing request data varhooks = require('hooks'); hooks.beforeEach(function (transaction, done) { transaction.fullPath = transaction.fullPath.replace('fp91oelsziea', 'gbkxklvmolc1'); done(); });
  • 21.
    Chai assertions var hooks= require('hooks'); var assert = require('chai').assert; hooks.afterEach(function(transaction, done) { if (!transaction.skip) { assert.match(transaction.real.headers['x-contentful-request-id'], /^content-api:[a-zA-Z0-9]{22}$/ } done(); });
  • 22.
  • 23.
    Censor private data varhooks = require('hooks'); const SECRET_HEADERS = ['Authorization'].map(header => header.toLowerCase()); hooks.afterEachValidation(function(transaction, done) { Object.keys(transaction.request.headers).forEach(function(key) { if (SECRET_HEADERS.indexOf(key.toLowerCase()) > -1) { transaction.request.headers[key] = "***HIDDEN SECRET DATA***"; } }); done(); });
  • 24.
  • 26.
    Conclusion Base your documentationon an API spec Test that spec Make it part of your CI Don't substitute your integration tests
  • 27.
    Slides available onSlideshare: http://www.slideshare.net/rwessling/ Follow me on Twitter: @RouvenWessling
  • 28.
    Meetup Thursday, March 2,2017 7:00 pm Pivotal Labs, Level 11, 155 Clarence Street, Sydney https://www.meetup.com/Contentful-User-Meetup-Sydney/events/237520492/