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.

By · · 8 min read

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 dialogAPIs panel
Resulta collectiona spec you can edit, plus a linked collection
Lintingnoyes, with file and line numbers
Contract tests from the specnoyes
Sync when the spec changesre-importUpdate collection merges changes
Best fora quick look at a third-party APIan 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 specIn 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 parametersquery and header rows; optional ones can be added switched off
request bodiesexample bodies built from example/examples or from the schema
documented responsessaved examples with status, headers and an example body
securitySchemescollection 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:

EnvironmentbaseUrl
Staginghttps://staging-api.example.com/v1
Productionhttps://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:

  1. The status code is documented. A 404 passes only if the operation lists 404, a matching range such as 4XX, or default.
  2. The Content-Type is documented for that response (skipped for 204).
  3. The JSON body matches the documented schema, using swc.response.to.have.jsonSchema.

A generated block looks like this (shortened):

JavaScript
// <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 a null type, so null values pass;
  • writeOnly properties are not required in responses;
  • OpenAPI 3.0 boolean exclusiveMinimum/exclusiveMaximum become numeric bounds;
  • format is dropped, so date-time or email formats 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:

JavaScript
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:

RuleExample
unresolved-refa $ref points to a schema that does not exist
path-param-missing/orders/{id} has no id path parameter declared
duplicate-operation-idtwo operations share an operationId
required-propertyrequired lists a property that is not in properties
get-request-bodya GET operation declares a request body
no-serversno servers, so requests will use an empty {{baseUrl}}
unused-componenta 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.

Try it on your own API

Swastik Codes runs in the browser and is free to use. Create an account to send requests, sync your workspaces and invite your team.