OpenAPI (Swagger) specifications that write your tests for you (sort of)
Tags: openapi, node, javascript, swagger
Published: 2019-09-28 12:30:43

---
title: OpenAPI (Swagger) specifications that write your tests for you (sort of)
published: true
tags: open-api,nodejs,javascript,swagger
canonical_url: https://medium.com/@Scampiuk/openapi-swagger-specifications-that-write-your-tests-for-you-sort-of-82276a491c68
---

I recently wrote the article [Handling API validation with OpenAPI (Swagger) documents in NodeJS](https://medium.com/@Scampiuk/handling-api-validation-with-openapi-swagger-documents-in-nodejs-1f09c133d4d2?source=your_stories_page---------------------------), which went into how to pass on the work of input validation to the OpenAPI spec. This follows on, showing how to lighten the testing load and ensure your API is producing exactly the output you’ve painstakingly documented.

![](https://cdn-images-1.medium.com/max/1024/1*dztNVuObpOSvrLaBbE9q2Q.jpeg)<figcaption>Photo by <a href="https://unsplash.com/@pinjasaur?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Paul Esch-Laurent</a> on <a href="https://unsplash.com/s/photos/javascript?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption>

### Faster testing by relying on the OpenAPI spec as a single source of truth.

There is nothing, _nothing,_ more predictable than API documentation being wrong.

It’s hard to keep that document up to date with all the other pressures of having to, you know, maintain the API. It’s simpler to push the fix or feature and then update the doc. Eventually.

I would be lying if I was looking for the solution to this exact problem, but I’ve discovered one as a by-product of two other things:

1. Using the API spec document for validation.  
We covered this in [https://medium.com/@Scampiuk/handling-api-validation-with-openapi-swagger-documents-in-nodejs-1f09c133d4d2](https://dev.to/scampiuk/handling-api-validation-with-openapi-swagger-documents-in-nodejs-17d0)
2. Using the API spec document for testing. ( This guide )

This little duo means the API spec _has_ to be up to date, else you can’t pass any of your tests. Nice, hu?

We’re going to start with as simple as a test application as possible:

```
npm install express
```

{% gist https://gist.github.com/scampiuk/a655a89b6390b9792f07f9adcfa5bbea %}

Let’s run it…

```
chris@chris-laptop:~/Projects/openapi-testing$ curl localhost:3000
{"version":"1.0.0"}
```

Ok so that’s simple and working, let’s create a spec that defines this, rather limited, API. Using OpenAPI 3 spec, we’ll be quite verbose in the way we build the objects up so we can re-use them in the future:

{% gist https://gist.github.com/scampiuk/d2d77f0218d30c56b50ec2c423719154 %}

We can see that our GET / endpoint needs to return an object with the a property called version which has a pattern of ^\d\.\d\.\d$ , and it requires a header called X-Request-Id which is a [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier).

But our current endpoint doesn’t fulfill this criteria! We’ve created the thing we hate, the thing worst than no API documentation: _bad_ API documentation. The solution? Tests.

```
npm install supertest chai mocha --save-dev
```

Once we have that installed, let’s create a nice simple test

{% gist https://gist.github.com/scampiuk/8d88b6d60b62d886ca9b80951f6c1e12 %}

Then in package.json , under the scripts block, add

```
"test": "./node\_modules/.bin/mocha --exit --timeout 10000"
```

This will run our test we’ve just created, exit once it’s done, have a sane time-out time.

![](https://cdn-images-1.medium.com/max/547/1*k2wT93ReEq-ASuXMBKWp0w.png)

We’ve expelled some effort to test this endpoint, but the tests are a false positive — we know the spec requires the X-Request-Id to be defined, and our test doesn’t cover that.

We’re going to look at the same tooling as we used in the previous guide, express-openapi-validate . This thing is going to ingest our spec file, and in the same way we used it previously to validate the input to an API, we’re going to use it to validate the _output_ of the API.

```
npm install express-openapi-validate js-yaml app-root-path --save-dev
```

And now we’re going to change the index.spec.js around a bit, taking out the explicit definition of what we expect in the endpoint, and adding in the OpenApiValidator…

{% gist https://gist.github.com/scampiuk/f597fea920908328d955c23bedad3f51 %}

and run the test again…

![](https://cdn-images-1.medium.com/max/895/1*17D_Ty865erMcFL9wFJSIQ.png)

There! It failed this time, and told us why it failed: response.headers should have required property "x-request-id"

Note we’ve not had to define that in the test: in fact we’ve taken out code for testing what shape the response is, it’s taken the spec and worked out what’s required for a GET / request. Let’s fix the endpoint.

```
npm install faker
```

( if you’ve not looked at [faker](https://www.npmjs.com/package/faker) before, I strongly recommend it, I’m abusing it here slightly but it’s a fantastic fake data generator))

![](https://cdn-images-1.medium.com/max/633/1*NDAt_1pzx8WqCMsvkS24Mg.png)

We changed the response to set the X-Request-Id header with a UUID, and now the tests pass.

What happens if we break the format of version? We’ll change the request to send x1.0.0 instead, which doesn’t match the pattern for Version …

![](https://cdn-images-1.medium.com/max/910/1*iHIRd8nryi66U9oeSDHTFw.png)

Tests fail, because you’re sending the wrong value.

This is crazy powerful. Now, because you’ve defined things in your spec file correctly, you can re-use patterns in your API and ensure that the spec is being fulfilled on your tests, while updating _all_ your tests if you update the spec file. You write less lines in your tests, focus on putting the effort into the spec file (because that’s now driving your tests…) and things become simpler.

#### In conclusion

Using the OpenAPI spec to control how data gets into your API, and using it to build your tests around, means that it becomes the single source of truth about your API. Sure, there are ways of cheating this and not documenting all the objects, or not testing endpoints, but why do that?

By combining these two approaches, we’ve found that workflow on the API now _starts_ with the OpenAPI specification, then building tests, then implementing the endpoints. TDD becomes almost the de facto way of approaching development. While before API development may have started by firing up Postman and thrashing through some ideas, now it’s all tested by this near-magic combination of [supertest](https://www.npmjs.com/package/supertest), [mocha](https://www.npmjs.com/package/mocha), [chai](https://www.npmjs.com/package/chai), and [OpenApiValidator](https://www.npmjs.com/package/express-openapi-validate).

There are a couple of things missing from this set-up which I’m still working on:

1. I would like code coverage reports via nyc to ensure that all the endpoints and response codes defined in the OpenAPI spec document are implemented
2. I would like the test validation to error if there are objects or properties in the API responses that are _not_ documented — I just can’t work that one out at the moment.

I would love to hear how you use this in your projects! Get me on [https://twitter.com/Scampiuk](https://twitter.com/Scampiuk)