oaichecker

package module
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 13, 2018 License: Apache-2.0 Imports: 16 Imported by: 0

README

license Build Status GoDoc codecov GolangCI Go Report Card

OpenAPI Checker

Run you server tests and at the same time check if you tests match with you OpenAPI specs.

Why?

As a developper I often forget to change the specs after a server modification and so my API documentation is always deprecated after 2 commits. In order to fix that I have written a little lib which takes you tests HTTP request/responses an matches them against your API specs. If you request doesn't matchs the specs, you request will fail and so you test also fail.

How?

This lib permits you to generate an http.RoundTripper which can be easily integrated inside you http.Client from you already existing tests.

Example

import (
	"github.com/stretchr/testify/assert"
	"github.com/Peltoche/oaichecker"
)

var client http.Client

func init() {
	// Loads the specs file.
	//
	// It contains only a the specs for the endpoint 'GET /pets'.
	specs, err := oaichecker.NewSpecsFromFile("./dataset/petstore_minimal.json")
	if err != nil {
		panic(err)
	}

	// Create a client which the custom transport
	client = http.Client{
		Transport: oaichecker.NewTransport(specs),
	}
}

func Test_Posting_a_valid_pet(t *testing.T) {
	// Make the requests as usual.
	//
	// In this case the request is valid but the specs are not followed because
	// the endpoint 'POST /v2/pet' is not defined inside the specs, only 'GET /pets'.
	_, err := client.Post("http://petstore.swagger.io/v2/pet", "application/json", strings.NewReader(`{
	"name": "doggie",
	"photoUrls": ["some-url"]}`))

	// This assert should success but as the specs are not followed, `req` is
	// nil and `err` contains the following message:
	//
	// "Post http://petstore.swagger.io/v2/pet: operation not defined inside the specs"
	assert.NoError(t, err)
}

Documentation

Overview

Example (Post_request_validation)
package main

import (
	"fmt"
	"net/http"
	"strings"

	"github.com/Peltoche/oaichecker"
)

func main() {
	// Load the specs file.
	specs, err := oaichecker.NewSpecsFromFile("./dataset/petstore.json")
	if err != nil {
		panic(err)
	}

	// Create a client which matches the requests/responses against the given
	// specs.
	client := http.Client{
		Transport: oaichecker.NewTransport(specs),
	}

	// Make a request with a required field missing.
	_, err = client.Post("http://petstore.swagger.io/pet", "application/json", strings.NewReader(`{
		"photoUrls": ["some-url"]
	}`))
	if err != nil {
		fmt.Println(err)
	}

}
Output:

Post http://petstore.swagger.io/pet: validation failure list:
.name in body is required
Example (Specs_format_validations)
package main

import (
	"fmt"

	"github.com/Peltoche/oaichecker"
)

func main() {
	// Load the specs file.
	specs, err := oaichecker.NewSpecsFromFile("./dataset/petstore_invalid.json")
	if err != nil {
		panic(err)
	}

	// Validate the specs file format.
	err = specs.Validate()
	if err != nil {
		fmt.Println(err)
	}

}
Output:

validation failure list:
"paths./pets.get.responses.200" must validate one and only one schema (oneOf). Found none valid
"paths./pets.get.responses.200.schema" must validate one and only one schema (oneOf). Found none valid
items in paths./pets.get.responses.200.schema is required

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Analyzer

type Analyzer struct {
	// contains filtered or unexported fields
}

Analyzer analyze a pair of http.Request/http.Response with the previously Specs loaded at initialization.

func NewAnalyzer

func NewAnalyzer(specs *Specs) *Analyzer

NewAnalyzer instantiate a new Analyzer based on the given Specs.

If the specs is nil, the function panics.

func (*Analyzer) Analyze

func (t *Analyzer) Analyze(req *http.Request, res *http.Response) error

Analyze the given pair of http.Request/http.Response with the previously loaded Specs.

This method checks: - If the Operation exists (method / path) - The Parameters defined inside the Operation (path / header / body / query / formData) - The Response (status / body)

In case of incorrectess, an error is returned.

type Specs

type Specs struct {
	// contains filtered or unexported fields
}

Specs represent some loaded OpenAPI specs.

It can be used inside an Analyzer or a Transport.

func NewSpecsFromFile

func NewSpecsFromFile(path string) (*Specs, error)

NewSpecsFromFile load a new OpenAPI specifications file from a filepath.

This specs can be either in JSON or YAML format. Any relatives references ("$ref": "./pet_definition.json" for example) will be resolved based on the given path.

func NewSpecsFromRaw

func NewSpecsFromRaw(rawSpec []byte) (*Specs, error)

NewSpecsFromRaw load a new raw OpenAPI specifications.

This specs can be either in JSON or YAML format. Any relatives references ("$ref": "./pet_definition.json" for example) will be resolved based on the result of os.Getwd().

func (*Specs) Validate

func (t *Specs) Validate() error

Validate the specs correctness.

It checks that: - Definition can't declare a property that's already defined by one of its ancestors - Definition's ancestor can't be a descendant of the same model - Path uniqueness: each api path should be non-verbatim (account for path param names) unique per method - Each security reference should contain only unique scopes - Each security scope in a security definition should be unique - Parameters in path must be unique - Each path parameter must correspond to a parameter placeholder and vice versa - Each referenceable definition must have references - Each definition property listed in the required array must be defined in the properties of the model - Each parameter should have a unique `name` and `type` combination - Each operation should have only 1 parameter of type body - Each reference must point to a valid object - Every default value that is specified must validate against the schema for that property - Items property is required for all schemas/definitions of type `array` - Path parameters must be declared a required - Headers must not contain $ref - Schema and property examples provided must validate against their respective object's schema - Examples provided must validate their schema

type Transport

type Transport struct {
	Transport http.RoundTripper
	// contains filtered or unexported fields
}

Transport is a http.RoundTripper implementation destined to be injected inside an htttp.Client.Transport.

It allows to make HTTP calls as usual but it will intercept the http.Request and http.Response and will validate them against the OpenAPI specs given during instantiation.

func NewTransport

func NewTransport(specs *Specs) *Transport

NewTransport instantiate a new Transport with the given Specs.

func (*Transport) RoundTrip

func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error)

RoundTrip implement http.RoundTripper.

If a validation error occures an error will returned with a new Response.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL