API provider contract testing for all with Portman, OpenAPI and Postman
Tags: api, openapi, testing, postman
Published: 2023-05-10 15:08:00

## Introduction

APIs are everywhere and power almost everything we use today.
OpenAPI has revolutionized the way APIs are designed, documented, deployed... Its kind of a big thing.

Making a great OpenAPI definition is helped with amazing tools such as [Stoplight Spectral](https://stoplight.io/open-source/spectral) which can help you ensure that your definition is not only valid against the OpenAPI specification but also your own API standards through custom linting rules.

How do you ensure that what you create and deploy matches your definition? Do you write all your tests by hand? Do you probe with Postman and hope for the best?

Maybe you do today but this blog will help you try something new... Welcome to the world of *contract testing*.

By the end of this blog you will have completed your first contract test (against my mocked API) and you should be free to use this knowledge to find gaps in your or any API out there subject to permission!

## Getting started

Rather than spending too long explaining what contract testers are, where they came from etc... Lets use one! (It's free so what is stopping you?)

We will be using [apideck Portman](https://github.com/apideck-libraries/portman). You are welcome to follow their readme.MD and come back later or follow the instructions here.

### Installing Portman

Install Portman

`$ npm install -g @apideck/portman`

Initialize your CLI

`portman --init`

### Creating a contract test to run in Postman

Make a new directory and download this example portman configuration file and store it there
https://api.oneadvanced.com/portman/configurations/portman-config.adv.json

Download this openAPI definition from SwaggerHub (the unresolved YAML works fine)
Link to SwaggerHub: https://app.swaggerhub.com/apis/AdvancedComputerSoft/Contract-Breaker/1.0.0
Direct link to YAML: https://api.swaggerhub.com/apis/AdvancedComputerSoft/Contract-Breaker/1.0.0

Open the directory that has both files and run the following:

`portman -c portman-config.adv.json -l AdvancedComputerSoft-Contract-Breaker-1.0.0-swagger.yaml`
<p align="center">
<img  src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oxvmbwzlpm0a8s1dhnof.png" alt="Terminal output from a successful creation of tests using Portman ready to import manually into Postman" width="650"/>

Portman will use the configuration file to port the openAPI definition to a Postman collection you can now import into Postman and start running tests!

### Run the test

Import the Postman collection file from the tmp/converted folder that Portman created as part of the process.
<p align="center">
<img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/evq4lni1vzgj64otiqwn.png" alt="Postman application with the manually imported collection that was created by Portman" width="650"/>

Open the List Countries request and press send!
<p align="center">
<img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8zqrjssrcskdl69pergb.png" alt="Postman test result showing failed tests" width="650"/>

Congratulations! You ran a test and you got some failed tests. (Hopefully)
Don't worry, that was supposed to happen.

### What happened?

Lets go back and look at the collection.
At first glance, it looks like any other collection. Check the tests tab and you should see something new.

This is where Portman has done its magic and created contract tests for you to run against the API. The OpenAPI definition was used to generate these tests.

<p align="center">
<img  src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7lrwnllwrd5mfbu916k2.png" alt="Postman tests that were generated by Portman and included in the collection. Details below" width="650"/>

You can see Postman will now test to ensure:

* The status code matches 200
* The response is application/json
* The response has a body which is an object
* The response body validates against the schema from the OpenAPI
* *Bonus - The response is received within 2000ms (This is not taken from the OpenAPI definition but from the Portman configuration*

All of this and you did not need to write anything. No human error, no missed tests. All of it was auto-generated.

### Interpreting the responses

<p align="center">
<img  src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2j9z68ecb3ptikr1he0n.png" alt="Postman tests results showing errors" width="650"/>

Postman has reported that 3 out of 5 tests have failed:

1) `[GET]::/countries - Response status code is 200 | AssertionError: expected 201 to equal 200` 

    This error was raised by the status code check as the API incorrectly returned a 201 response code instead of a 200 which it was expecting

2) `[GET]::/countries - Schema is valid | AssertionError: expected data to satisfy schema but found following errors: data.data[0] should have required property 'countryId', data.data[0].population should be integer, data.data[1] should NOT have additional properties, data.data[1].countryId should be string, data.data[1].population should be integer, data.pagination should NOT have additional properties, data.pagination.offset should be integer`

    This error was contains all the json schema validation issues. There are missing required properties, wrong types and additionProperties (these are caused by misspelled properties or those that were not documented)

What you should find is this isn't an API that you would want to release! Contract testing lets you find where your deployed API (or your one that you are developing) doesn't match the OpenAPI definition. Catch things now before you release!

## More tests

Portman has lots of other functionality to explore.

I would recommend to first look at overrides to try manipulating the collection. I started by making tests that removed the security and tried to call the API. You can stipulate which response from the OpenAPI you wish to receive. I was expecting a 401 to be returned. The Portman documentation has details of all of the functionality on offer.

## Summary

APIs need to match their documentation. Whether or not you start with Design in OpenAPI or start with code, contract testing can ensure the 2 are in sync so your consumers don't get surprises and raise issues.