How to Test an OpenAPI Spec: Check the Document, Then the API
To test an OpenAPI spec you test two things: the document, and the API against the document. Work through both on the sandbox store, then generate tests and run them in Shift-Left API.
This is lesson 5.2 of OpenAPI, Contract and Schema Testing. In lesson 5.1 you learned to read a spec; now you test one, using the sandbox store's spec and, for the demo, the free edition of Shift-Left API.
How do you test an OpenAPI spec?
To test OpenAPI spec files properly, you test two things, in order. First the document: does it parse, are its rules consistent, and do its examples match its own schemas? Then the API against the document: does every operation answer with a documented status, a body that fits its schema, and a refusal for each kind of invalid input? Skip the first pass and the second inherits every mistake in the spec. Skip the second and you have a tidy document that nobody has checked against reality.
Pass one: test the document
A spec is code, so it gets the checks code gets. Three of them:
- Validate it. A parser checks the document against the OpenAPI schema for its version and resolves every
$ref. A broken reference or a wrong type for a keyword fails here. - Lint it. A linter such as Spectral applies style and quality rules that are valid OpenAPI but still bad practice: an operation with no 4xx response, a missing
operationId, a schema with no description. You choose the rule set. - Check the examples. Every example should validate against the schema it illustrates.
Run the sandbox spec through those checks and two findings come up, both common in real specs:
- A 3.1 keyword form in a 3.0 document. The spec is
openapi: 3.0.3, but the product price usesexclusiveMinimum: 0. In OpenAPI 3.0,exclusiveMinimumis a boolean that works withminimum; the numeric form arrived with 3.1. A strict 3.0 validator rejects it, and a lenient tool may quietly ignore the bound. - No required fields on responses. The response schemas list properties but mark none as required, so a body with almost nothing in it still matches. As a contract, that is weak.
Neither stops a tool from importing the spec. Both change what tests can be derived from it, which is why this pass comes first.
Pass two: test the API against it
Now the running API. Take Create a new product (POST /api/v1/products). Its request schema says name is required, 1 to 100 characters; price is required and must be greater than 0; stock is an integer of at least 0; and unknown fields are not allowed (additionalProperties: false). The spec documents two answers: 201 and 400.
Here is a swagger API testing example, built straight from those rules:
| Case | Body | Expected |
|---|---|---|
| Valid, minimal | name and price only | 201, defaults filled in |
| Price on the wrong side of its limit | price: 0 | 400, error on price |
| Required field missing | no name | 400, error on name |
| Unknown field | an extra colour | 400, error on colour |
| Name too long | 101 characters | 400, error on name |
| Stock below its minimum | stock: -1 | 400, error on stock |
Send the first three yourself:
/api/v1/productscurl -X POST 'https://demo.totalshiftleft.ai/api/v1/products' \
-H 'Content-Type: application/json' \
-d '{"name":"Desk Lamp","price":19.5}'A 201. The response also shows description as an empty string, stock as 0 and category as general: the defaults the spec declares, applied by the API. That is worth a check of its own.
/api/v1/productscurl -X POST 'https://demo.totalshiftleft.ai/api/v1/products' \
-H 'Content-Type: application/json' \
-d '{"name":"Desk Lamp","price":0}'A 400 with error set to VALIDATION_ERROR and a details entry naming price. Now the extra field:
/api/v1/productscurl -X POST 'https://demo.totalshiftleft.ai/api/v1/products' \
-H 'Content-Type: application/json' \
-d '{"name":"Desk Lamp","price":19.5,"colour":"black"}'Also a 400, naming colour. Each refusal is documented and names the field, which is what a client needs.
The pieces of an OpenAPI testing framework
Whatever tools you pick, an OpenAPI testing framework has five parts, and each maps to one of the steps above:
| Part | Job | Pass |
|---|---|---|
| Parser and validator | Read the spec, resolve references, reject an invalid document | One |
| Linter | Apply your quality rules to a valid document | One |
| Test design | Turn each rule into cases, by hand or with a generator | Two |
| Runner | Send the requests against a chosen environment | Two |
| Reporter and gate | Record results and fail the build below a pass rate | Two |
Teams usually assemble this from several tools. What matters is that every part runs on every change to the spec, not only on the day it was written. For the tools commonly used at each step, read OpenAPI testing: how to test Swagger and OpenAPI APIs.
An OpenAPI response example belongs in pass one
It is tempting to assert against the examples in a spec. Don't: an OpenAPI response example is a sample for readers. In the sandbox spec, the 400 response's error field has the example BAD_REQUEST, while the API answers VALIDATION_ERROR. The schema only says error is a string, so both are valid.
Check examples in pass one, against their schemas. In pass two, assert on the schema's rules: the status, the types, the required fields, the allowed values.
Common mistakes
- Testing only the happy path. One 201 tells you almost nothing about a schema with six rules.
- Trusting a lenient import. A tool that accepts a slightly invalid spec is convenient, but it can drop the rule you most needed to test. Lint the spec as well.
- Asserting the human-readable message. Assert the status, the error code and the field named in
details; message wording changes. - Never re-running pass one. Specs change in every release. Validate and lint in the same pipeline that runs the tests.
In Shift-Left API: generate tests from the spec and run them
Shift-Left API covers the test design, the runner and the results for pass two. Its import is lenient on purpose: if strict validation fails, it still imports the dereferenced spec, so keep a linter in your pipeline for pass one.
In the free edition, with the sandbox spec imported (as in lesson 5.1):
- Open Products, then Create a new product.
- Click Generate tests. The coverage engine plans the tests from the spec: valid products, and negative and boundary cases for each rule in the schema, each with a severity.
- Tick the checkbox in the table header to select every test.
- Click Run Selected. The tests run against the environment the spec's
serversentry gave the project, the live sandbox. - Read the Bulk Run Summary: Total, Passed, Failed and Error. When a run has failures, the summary also groups them into causes.
The OpenAPI test automation page shows where this fits with the rest of the product. Lesson 5.3 opens up the generator: which schema keywords become which tests.
Try it yourself
In the free edition, import https://demo.totalshiftleft.ai/openapi/rest.json, open Products, then Create a new product, and click Generate tests. Select every test with the header checkbox and click Run Selected. How many ran, and did any fail? Open one that failed and compare its expected status with the actual one.
Recap
- To test an OpenAPI spec, check the document first (validate, lint, check examples), then test the API against it.
- A swagger API testing example starts with one operation: each rule in its schema gives a case that must pass and a case that must be refused.
- An OpenAPI testing framework needs a parser, a linter, test design, a runner and a gate, all running on every spec change.
Next: lesson 5.3, swagger test case generation, where each schema keyword turns into test cases.
Try it: In the free edition, import https://demo.totalshiftleft.ai/openapi/rest.json, open Products, then Create a new product, click Generate tests, tick the checkbox in the table header to select every test and click Run Selected.
- Use this sandbox asset
- https://demo.totalshiftleft.ai/openapi/rest.json
- You got it right when
- A Bulk Run Summary opens with Total, Passed, Failed and Error counts, and Total equals the number of tests you selected.
Frequently asked questions
What is a simple swagger API testing example?+
Take one operation, such as creating a product, and test both sides of each rule its schema states. A valid product should get the documented 201. A price of 0, a missing name or an unknown extra field should get the documented 400 with a field-level error. Each rule in the spec becomes at least one passing case and one refused case.
What makes up an OpenAPI testing framework?+
Five parts: a parser that reads the spec and resolves its references, a linter that checks the spec against your style and quality rules, a generator or a person that turns the spec into test cases, a runner that sends the requests against an environment, and a reporter that turns results into a pass rate a pipeline can gate on. One tool can cover several parts, but all five need to be there.
Should tests assert on an OpenAPI response example?+
Not directly. An OpenAPI response example is a sample body for readers, and it often drifts out of date without breaking anything. Validate the example against its own schema as part of linting the spec, and point your response assertions at the schema's rules instead.
Related lessons
Swagger testing means checking an API against its OpenAPI (Swagger) document. Learn which parts of a spec a tester reads, why examples aren't the contract, and explore one in Shift-Left API.
Every keyword in a schema is a rule, and every rule gives test cases. See the mapping keyword by keyword, what no generator can derive from a spec, and how to judge one, then generate tests in Shift-Left API.
Your OpenAPI spec is most of a test plan already. Import it into Shift-Left API, explore what it creates, and generate tests from it with no requirements needed.
Read more on the blog
A practical guide to OpenAPI and Swagger API testing: how spec-driven testing works, the six kinds of tests a spec makes possible, a worked pytest and Schemathesis example against the public Petstore API, CI wiring, tools, common mistakes and a checklist.
Compare the best OpenAPI testing tools for automated test generation, contract validation, and CI/CD integration. Side-by-side analysis of Shift-Left API, Schemathesis, Dredd, Postman, and more.