OpenAPI · Swagger · API testing · Contract testing · Tutorial
Import an OpenAPI spec and generate API tests
From OpenAPI file to a running test suite: what the import generates, environments for base URLs, contract tests from response schemas, linting, collection sync and runs.
To test an API from its OpenAPI spec, import the OpenAPI 3 or Swagger 2 file into an API client, which turns every operation into a ready-to-send request, point the base URL at your server, and add tests that check each response against the status codes and schemas the spec documents. In Swastik Codes you can import the file as a collection in one step, or add it under APIs and generate contract tests that validate status, Content-Type and the JSON body schema for every operation, then run them in the collection runner.
This guide covers both routes, explains what the generated collection contains, and shows how to keep the collection in step with the spec as it changes.
Two ways to bring in a spec
| Import dialog | APIs panel | |
|---|---|---|
| Result | a collection | a spec you can edit, plus a linked collection |
| Linting | no | yes, with file and line numbers |
| Contract tests from the spec | no | yes |
| Sync when the spec changes | re-import | Update collection merges changes |
| Best for | a quick look at a third-party API | an API you own or test regularly |
Both accept OpenAPI 3.0 and 3.1 and Swagger 2.0, in JSON or YAML.
Import as a collection
Open Import in the app and choose File, Folder, Link or Raw (paste the YAML or JSON). A link is fetched by your browser, so it must allow cross-origin requests; if it does not, download the file and use File instead. A preview lists what will be created, and the import settings for OpenAPI files let you choose:
- Naming requests: by summary or
operationId, or by URL. - Folder organization: by tag, by path segment, or no folders.
- Parameter generation: values from the spec's examples, or type placeholders such as
<string>from the schema. - Whether optional parameters are switched on, whether deprecated operations are included, and whether OpenAPI 3.1 webhooks become requests.
Add it to APIs
Open APIs in the sidebar and use Import a definition file, or create a new API and paste the definition. The spec then gets its own view with Definition, Documentation, Collection sync, Contract tests and Versions tabs. The rest of this guide mostly uses this route, because it keeps the spec and the tests connected. See API design for the editor itself.
What the generated collection contains
Generation follows the same rules on both routes:
| In the spec | In the collection |
|---|---|
each operation (GET /orders/{id}) | one request, named from summary, operationId or the URL |
| tags (or path segments) | folders |
first entry of servers (or host + basePath + first scheme in Swagger 2) | the baseUrl collection variable, with server variables filled from their defaults |
path templates {id} | path variables :id, with example values |
| query and header parameters | query and header rows; optional ones can be added switched off |
| request bodies | example bodies built from example/examples or from the schema |
| documented responses | saved examples with status, headers and an example body |
securitySchemes | collection or request auth: Bearer with {{bearerToken}}, API key with {{apiKey}}, Basic, Digest and OAuth 2.0 |
Every URL starts with {{baseUrl}}, so changing one variable moves the whole collection to another server. Path and operation-level servers that differ from the global one are kept on those requests. If the spec has no servers, baseUrl is empty and you must set it before sending.
Step 1: set base URLs with environments
The generated baseUrl is a collection variable. Create an environment per server and define baseUrl in each:
| Environment | baseUrl |
|---|---|
| Staging | https://staging-api.example.com/v1 |
| Production | https://api.example.com/v1 |
Environment variables take precedence over collection variables, so selecting an environment switches every request at once. Put the credentials the auth expects (bearerToken, apiKey) in the same environments, as current values or in the vault, so they stay on your device. Environments and variables explains scopes in detail.
Requests from the web app are sent through the swastik.codes server, which needs a free account and does not connect to private or loopback addresses. To test a server running on your own machine, use the desktop app for Windows or Linux; see testing a localhost API.
Step 2: generate contract tests from the spec
Open the spec's Contract tests tab. It lists the operations and how many of them have a response schema, and offers two actions:
- Add to "your collection" (or Generate collection with tests if none is linked yet) writes tests into the requests of the linked collection.
- Create test suite collection builds a separate collection from the spec that holds only the generated tests, and Update test suite refreshes it later.
For each request matched to an operation by method and path, the generated script checks three things:
- The status code is documented. A
404passes only if the operation lists404, a matching range such as4XX, ordefault. - The
Content-Typeis documented for that response (skipped for204). - The JSON body matches the documented schema, using
swc.response.to.have.jsonSchema.
A generated block looks like this (shortened):
// <contract-tests> generated from "Orders API" for GET /orders/{id}. Regenerating replaces this block.
(function () {
var contract = { "200": { "contentTypes": ["application/json"], "schema": { "type": "object", "required": ["id", "status"], "properties": { ... } } },
"404": { "contentTypes": ["application/problem+json"] } };
var code = String(swc.response.code);
...
swc.test('Response body matches the ' + key + ' schema', function () {
swc.response.to.have.jsonSchema(expected.schema);
});
})();
// </contract-tests>The block sits between // <contract-tests> markers in the request's post-response script. Regenerating replaces only that block, so tests you wrote yourself above or below it are kept. A report after each run of the generator lists requests with no matching operation and operations that no request covers, which is a quick way to find untested endpoints.
How spec schemas become test schemas
OpenAPI schemas are close to JSON Schema but not identical, so the generator converts them:
- local
$refs are inlined (a recursive reference becomes an empty schema that accepts anything); nullable: true(OpenAPI 3.0) becomes anulltype, sonullvalues pass;writeOnlyproperties are not required in responses;- OpenAPI 3.0 boolean
exclusiveMinimum/exclusiveMaximumbecome numeric bounds; formatis dropped, sodate-timeoremailformats are not checked;- schemas larger than 200,000 characters are left out of the script.
If you need format checks, add your own schema test next to the block; JSON Schema validation in API tests shows how.
Step 3: add your own tests
Contract tests answer "does the response match the spec". They do not know your business rules. Add those to the request's post-response script, outside the markers:
const order = swc.response.json();
swc.test('total equals the sum of the lines', function () {
const sum = order.lines.reduce((s, l) => s + l.quantity * l.unitPrice, 0);
swc.expect(order.total).to.be.closeTo(sum, 0.001);
});
swc.collectionVariables.set('orderId', order.id);Saving ids like this lets later requests use {{orderId}}, so a create → read → update → delete sequence can run end to end. Chaining API requests covers the pattern, and writing tests with swc.* scripts lists the assertions.
Also test the error paths the spec documents. Duplicate a request, send an invalid body or a missing id, and the contract test checks that the error status and its schema are documented too.
Step 4: lint the spec
Tests generated from a broken spec give misleading results, so fix the definition first. The Definition tab validates on the server as you edit and lists errors and warnings with the file, line, JSON path and rule. Typical findings:
| Rule | Example |
|---|---|
unresolved-ref | a $ref points to a schema that does not exist |
path-param-missing | /orders/{id} has no id path parameter declared |
duplicate-operation-id | two operations share an operationId |
required-property | required lists a property that is not in properties |
get-request-body | a GET operation declares a request body |
no-servers | no servers, so requests will use an empty {{baseUrl}} |
unused-component | a component is never referenced |
Click an issue to jump to it. A definition can span several files with $refs between them; one file is the root, and validation resolves references across files.
Step 5: keep the collection and the spec in sync
When the spec changes, the header of the spec view shows Collection out of sync. Press Update collection. In the default Sync mode the merge is keyed on METHOD /path:
- new operations are added as requests;
- changed operations are updated;
- request ids, test scripts, auth, saved examples and values you edited are kept;
- requests whose operation was removed are kept as orphans, unless you tick Remove orphan requests.
A sync report lists what was added, updated, removed or orphaned. The other mode, Replace, regenerates every request and loses your edits, so choose it only on purpose. After a sync, run the contract test generator again so the embedded schemas match the new spec; it replaces only the marked blocks.
Tag a version under Versions when you release. Each version records a changelog of added, changed and removed operations against the previous one.
Step 6: run the whole suite
From the Contract tests tab, Run test suite (or Run on the linked collection) opens the collection runner. Pick the environment, set iterations or a data file if needed, and start. The summary shows passed and failed tests per request, and you can export the run as JSON, JUnit XML or a self-contained HTML report. To check the API against its spec every hour or every day, attach the collection to a monitor.
Frequently asked questions
Can I import Swagger 2.0 as well as OpenAPI 3?
Yes. Swagger 2.0, OpenAPI 3.0 and OpenAPI 3.1 are supported, in JSON or YAML. For Swagger 2 the base URL is built from schemes, host and basePath.
Does it validate responses against the OpenAPI schema?
Yes, through generated contract tests. Each test checks that the status and content type are documented and that the JSON body matches the response schema. Formats are not checked by the generated tests, and request bodies are not validated.
Will updating the collection delete my tests?
No. Sync mode keeps your scripts, auth, examples and edited values, and the generated contract tests live in a marked block that is the only part regenerated. Only Replace mode rebuilds requests from scratch.
What if my spec has no servers?
The baseUrl variable is created empty. Define baseUrl in an environment or on the collection before sending. The linter warns about this with the no-servers rule.
Can I go the other way, from a collection to OpenAPI?
Yes. Collections export to OpenAPI 3 in JSON or YAML; see import and export.