baloo

package module
v3.1.0+incompatible Latest Latest
Warning

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

Go to latest
Published: Aug 9, 2022 License: MIT Imports: 10 Imported by: 1

README

baloo Build Status GitHub release GoDoc Coverage Status Go Report Card

Expressive and versatile end-to-end HTTP API testing made easy in Go (golang), built on top of gentleman HTTP client toolkit.

Take a look to the examples to get started.

Features

  • Versatile built-in expectations.
  • Extensible custom expectations.
  • Declarative, expressive, fluent API.
  • Response body matching and strict equality expectations.
  • Deep JSON comparison.
  • JSON Schema validation.
  • Full-featured HTTP client built on top of gentleman toolkit.
  • Intuitive and semantic HTTP client DSL.
  • Easy to configure and use.
  • Composable chainable assertions.
  • Works with Go's testing package (more test engines might be added in the future).
  • Convenient helpers and abstractions over Go's HTTP primitives.
  • Middleware-oriented via gentleman's middleware layer.
  • Extensible and hackable API.

Versions

  • v3 - Latest stable version with better JSON assertion. Uses gentleman@v2. Recommended.
  • v2 - Stable version. Uses gentleman@v2.
  • v1 - First version. Stable. Uses gentleman@v1. Actively maintained.

Installation

go get -u gopkg.in/h2non/baloo.v3

Requirements

  • Go 1.7+

Examples

See examples directory for featured examples.

Simple request expectation
package simple

import (
  "testing"

  "gopkg.in/h2non/baloo.v3"
)

// test stores the HTTP testing client preconfigured
var test = baloo.New("http://httpbin.org")

func TestBalooSimple(t *testing.T) {
  test.Get("/get").
    SetHeader("Foo", "Bar").
    Expect(t).
    Status(200).
    Header("Server", "apache").
    Type("json").
    JSON(map[string]string{"bar": "foo"}).
    Done()
}
Custom assertion function
package custom_assertion

import (
  "errors"
  "net/http"
  "testing"

  "gopkg.in/h2non/baloo.v3"
)

// test stores the HTTP testing client preconfigured
var test = baloo.New("http://httpbin.org")

// assert implements an assertion function with custom validation logic.
// If the assertion fails it should return an error.
func assert(res *http.Response, req *http.Request) error {
  if res.StatusCode >= 400 {
    return errors.New("Invalid server response (> 400)")
  }
  return nil
}

func TestBalooClient(t *testing.T) {
  test.Post("/post").
    SetHeader("Foo", "Bar").
    JSON(map[string]string{"foo": "bar"}).
    Expect(t).
    Status(200).
    Type("json").
    AssertFunc(assert).
    Done()
}
JSON Schema assertion
package json_schema

import (
  "testing"

  "gopkg.in/h2non/baloo.v3"
)

const schema = `{
  "title": "Example Schema",
  "type": "object",
  "properties": {
    "origin": {
      "type": "string"
    }
  },
  "required": ["origin"]
}`

// test stores the HTTP testing client preconfigured
var test = baloo.New("http://httpbin.org")

func TestJSONSchema(t *testing.T) {
  test.Get("/ip").
    Expect(t).
    Status(200).
    Type("json").
    JSONSchema(schema).
    Done()
}
Custom global assertion by alias
package alias_assertion

import (
  "errors"
  "net/http"
  "testing"

  "gopkg.in/h2non/baloo.v3"
)

// test stores the HTTP testing client preconfigured
var test = baloo.New("http://httpbin.org")

func assert(res *http.Response, req *http.Request) error {
  if res.StatusCode >= 400 {
    return errors.New("Invalid server response (> 400)")
  }
  return nil
}

func init() {
  // Register assertion function at global level
  baloo.AddAssertFunc("test", assert)
}

func TestBalooClient(t *testing.T) {
  test.Post("/post").
    SetHeader("Foo", "Bar").
    JSON(map[string]string{"foo": "bar"}).
    Expect(t).
    Status(200).
    Type("json").
    Assert("test").
    Done()
}

API

See godoc reference for detailed API documentation.

HTTP assertions
Status(code int)

Asserts the response HTTP status code to be equal.

StatusRange(start, end int)

Asserts the response HTTP status to be within the given numeric range.

StatusOk()

Asserts the response HTTP status to be a valid server response (>= 200 && < 400).

StatusError()

Asserts the response HTTP status to be a valid clint/server error response (>= 400 && < 600).

StatusServerError()

Asserts the response HTTP status to be a valid server error response (>= 500 && < 600).

StatusClientError()

Asserts the response HTTP status to be a valid client error response (>= 400 && < 500).

Type(kind string)

Asserts the Content-Type header. MIME type aliases can be used as kind argument.

Supported aliases: json, xml, html, form, text and urlencoded.

Header(key, value string)

Asserts a response header field value matches.

Regular expressions can be used as value to perform the specific assertions.

HeaderEquals(key, value string)

Asserts a response header field with the given value.

HeaderNotEquals(key, value string)

Asserts that a response header field is not equal to the given value.

HeaderPresent(key string)

Asserts if a header field is present in the response.

HeaderNotPresent(key string)

Asserts if a header field is not present in the response.

BodyEquals(value string)

Asserts a response body as string using strict comparison.

Regular expressions can be used as value to perform the specific assertions.

BodyMatchString(pattern string)

Asserts a response body matching a string expression.

Regular expressions can be used as value to perform the specific assertions.

BodyLength(length int)

Asserts the response body length.

JSON(match interface{})

Asserts the response body with the given JSON struct.

JSONSchema(schema string)

Asserts the response body againts the given JSON schema definition.

data argument can be a string containing the JSON schema, a file path or an URL pointing to the JSON schema definition.

Assert(alias string)

Assert adds a new assertion function by alias name.

Assertion function must be previosly registered via baloo.AddAssertFunc("alias", function).

See an example here.

AssertFunc(func (*http.Response, *http.Request) error)

Adds a new custom assertion function who should return an detailed error in case that the assertion fails.

Development

Clone this repository:

git clone https://github.com/h2non/baloo.git && cd baloo

Install dependencies:

go get -u ./...

Run tests:

go test ./...

Lint code:

go test ./...

Run example:

go test ./_examples/simple/simple_test.go

License

MIT - Tomas Aparicio

Documentation

Index

Constants

View Source
const Version = "3.1.0"

Version defines the current semantic version.

Variables

View Source
var Assertions = make(map[string]assert.Func)

Assertions stores global assertion functions by alias name. Use Expect.Assert('<assertion name>') to use new assertion at request expectation level.

View Source
var NewHandler = gentleman.NewHandler

NewHandler is a convenient alias to gentleman.NewHandler factory.

View Source
var (
	// UserAgent represents the static user agent name and version.
	UserAgent = "baloo/" + Version
)

Functions

func AddAssertFunc

func AddAssertFunc(name string, fn assert.Func)

AddAssertFunc adds a new assertion function at global level by alias name. Then you can trigger the assertion function in any expectation test.

func FlushAssertFuncs

func FlushAssertFuncs()

FlushAssertFuncs flushes registered assertion functions.

Types

type Client

type Client struct {
	// Parent stores an optional parent baloo Client instance.
	Parent *Client
	// Client entity has it's own Context that will be inherited by requests or child clients.
	Client *gentleman.Client
}

Client represents a high-level HTTP client entity capable with a built-in middleware and context.

func New

func New(url string) *Client

New creates a new high level client entity able to perform HTTP requests.

func (*Client) AddCookie

func (c *Client) AddCookie(cookie *http.Cookie) *Client

AddCookie sets a new cookie field bsaed on the given http.Cookie struct without overwriting any existent cookie.

func (*Client) AddCookies

func (c *Client) AddCookies(data []*http.Cookie) *Client

AddCookies sets a new cookie field based on a list of http.Cookie without overwriting any existent cookie.

func (*Client) AddHeader

func (c *Client) AddHeader(name, value string) *Client

AddHeader adds a new header field by name and value without overwriting any existent header.

func (*Client) BaseURL

func (c *Client) BaseURL(uri string) *Client

BaseURL defines the URL schema and host for client requests. Useful to define at client level the base URL used by client child requests.

func (*Client) CookieJar

func (c *Client) CookieJar() *Client

CookieJar creates a cookie jar to store HTTP cookies when they are sent down.

func (*Client) Delete

func (c *Client) Delete(path string) *Request

Delete creates a new DELETE request.

func (*Client) Get

func (c *Client) Get(path string) *Request

Get creates a new GET request.

func (*Client) Head

func (c *Client) Head(path string) *Request

Head creates a new HEAD request.

func (*Client) Method

func (c *Client) Method(name string) *Client

Method defines a the default HTTP method used by outgoing client requests.

func (*Client) Param

func (c *Client) Param(name, value string) *Client

Param replaces a path param based on the given param name and value.

func (*Client) Params

func (c *Client) Params(params map[string]string) *Client

Params replaces path params based on the given params key-value map.

func (*Client) Patch

func (c *Client) Patch(path string) *Request

Patch creates a new PATCH request.

func (*Client) Path

func (c *Client) Path(path string) *Client

Path defines the URL base path for client requests.

func (*Client) Post

func (c *Client) Post(path string) *Request

Post creates a new POST request.

func (*Client) Put

func (c *Client) Put(path string) *Request

Put creates a new PUT request.

func (*Client) Request

func (c *Client) Request() *Request

Request creates a new Request based on the current Client

func (*Client) SetHeader

func (c *Client) SetHeader(key, value string) *Client

SetHeader sets a new header field by name and value. If another header exists with the same key, it will be overwritten.

func (*Client) SetHeaders

func (c *Client) SetHeaders(fields map[string]string) *Client

SetHeaders adds new header fields based on the given map.

func (*Client) URL

func (c *Client) URL(uri string) *Client

URL defines the URL for client requests. Useful to define at client level the base URL and base path used by child requests.

func (*Client) Use

func (c *Client) Use(p plugin.Plugin) *Client

Use uses a new plugin to the middleware stack.

func (*Client) UseError

func (c *Client) UseError(fn context.HandlerFunc) *Client

UseError uses a new middleware function for error phase.

func (*Client) UseHandler

func (c *Client) UseHandler(phase string, fn context.HandlerFunc) *Client

UseHandler uses a new middleware function for the given phase.

func (*Client) UseParent

func (c *Client) UseParent(parent *Client) *Client

UseParent uses another Client as parent inheriting its middleware stack and configuration.

func (*Client) UseRequest

func (c *Client) UseRequest(fn context.HandlerFunc) *Client

UseRequest uses a new middleware function for request phase.

func (*Client) UseResponse

func (c *Client) UseResponse(fn context.HandlerFunc) *Client

UseResponse uses a new middleware function for response phase.

type Expect

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

Expect represents the HTTP expectation suite who is able to define multiple assertion functions to match the response.

func NewExpect

func NewExpect(req *Request) *Expect

NewExpect creates a new testing expectation instance.

func (*Expect) Assert

func (e *Expect) Assert(assertions ...string) *Expect

Assert adds a new assertion function by alias name. Assertion function must be previosly registered via baloo.AddAssertFunc("alias", function).

func (*Expect) AssertFunc

func (e *Expect) AssertFunc(assertion ...assert.Func) *Expect

AssertFunc adds a new assertion function.

func (*Expect) BindTest

func (e *Expect) BindTest(t TestingT) *Expect

BindTest binds the Go testing instance to the current suite. In the future multiple testing interfaces can be supported via adapters.

func (*Expect) BodyEquals

func (e *Expect) BodyEquals(pattern string) *Expect

BodyEquals asserts as strict equality comparison the response body with a given string string.

func (*Expect) BodyLength

func (e *Expect) BodyLength(length int) *Expect

BodyLength asserts a response body length.

func (*Expect) BodyMatchString

func (e *Expect) BodyMatchString(pattern string) *Expect

BodyMatchString asserts a response body matching a string expression. Regular expressions can be used as value to perform the specific assertions.

func (*Expect) Done

func (e *Expect) Done() error

Done performs and asserts the HTTP response based on the defined expectations.

func (*Expect) End

func (e *Expect) End() error

End is an alias to `Done()`.

func (*Expect) Header

func (e *Expect) Header(key, value string) *Expect

Header asserts a response header field value matches. Regular expressions can be used as value to perform the specific assertions.

func (*Expect) HeaderEquals

func (e *Expect) HeaderEquals(key, value string) *Expect

HeaderEquals asserts a response header field value is equal to the given value.

func (*Expect) HeaderNotEquals

func (e *Expect) HeaderNotEquals(key, value string) *Expect

HeaderNotEquals asserts that a response header field value is not equal to the given one.

func (*Expect) HeaderNotPresent

func (e *Expect) HeaderNotPresent(key string) *Expect

HeaderNotPresent asserts if a header field is not present in the response.

func (*Expect) HeaderPresent

func (e *Expect) HeaderPresent(key string) *Expect

HeaderPresent asserts if a header field is present in the response.

func (*Expect) JSON

func (e *Expect) JSON(data interface{}) *Expect

JSON asserts the response body with the given JSON struct.

func (*Expect) JSONSchema

func (e *Expect) JSONSchema(schema string) *Expect

JSONSchema asserts the response body with the given JSON schema definition.

func (*Expect) RedirectTo

func (e *Expect) RedirectTo(uri string) *Expect

RedirectTo asserts the server response redirects to the given URL pattern. Regular expressions are supported.

func (*Expect) Send

func (e *Expect) Send() (*gentleman.Response, error)

Send does the same as `Done()`, but it also returns the `*http.Response` along with the `error`.

func (*Expect) Status

func (e *Expect) Status(code int) *Expect

Status asserts the response status code with the given status.

func (*Expect) StatusClientError

func (e *Expect) StatusClientError() *Expect

StatusClientError asserts the response status code as server error response (>= 400 && < 500).

func (*Expect) StatusError

func (e *Expect) StatusError() *Expect

StatusError asserts the response status code as client/server error response (>= 400 && < 600).

func (*Expect) StatusOk

func (e *Expect) StatusOk() *Expect

StatusOk asserts the response status code as valid response (>= 200 && < 400).

func (*Expect) StatusServerError

func (e *Expect) StatusServerError() *Expect

StatusServerError asserts the response status code as server error response (>= 500 && < 600).

func (*Expect) Type

func (e *Expect) Type(kind string) *Expect

Type asserts the response MIME type with the given alias or value.

type Request

type Request struct {

	// Optional reference to the parent Client instance.
	Client *Client

	// Request stores the reference to gentleman.Request instance.
	Request *gentleman.Request
	// contains filtered or unexported fields
}

Request HTTP entity for gentleman. Provides middleware capabilities, built-in context and convenient methods to easily setup request params.

func NewRequest

func NewRequest() *Request

NewRequest creates a new Request entity.

func (*Request) AddCookie

func (r *Request) AddCookie(cookie *http.Cookie) *Request

AddCookie sets a new cookie field bsaed on the given http.Cookie struct without overwriting any existent cookie.

func (*Request) AddCookies

func (r *Request) AddCookies(data []*http.Cookie) *Request

AddCookies sets a new cookie field based on a list of http.Cookie without overwriting any existent cookie.

func (*Request) AddHeader

func (r *Request) AddHeader(name, value string) *Request

AddHeader adds a new header field by name and value without overwriting any existent header.

func (*Request) AddPath

func (r *Request) AddPath(path string) *Request

AddPath defines the request URL path to be used in the outgoing request.

func (*Request) AddQuery

func (r *Request) AddQuery(name, value string) *Request

AddQuery adds a new URL query param field without overwriting any existent query field.

func (*Request) Assert

func (r *Request) Assert(t TestingT) *Expect

Assert is an alias to .Expect().

func (*Request) BaseURL

func (r *Request) BaseURL(uri string) *Request

BaseURL parses the given URL and uses the URL schema and host in the outgoing request.

func (*Request) Body

func (r *Request) Body(reader io.Reader) *Request

Body defines the request body based on a io.Reader stream.

func (*Request) BodyString

func (r *Request) BodyString(data string) *Request

BodyString defines the request body based on the given string. If using this method, you should define the proper Content-Type header representing the real content MIME type.

func (*Request) Clone

func (r *Request) Clone() *Request

Clone creates a new side-effects free Request based on the current one.

func (*Request) CookieJar

func (r *Request) CookieJar() *Request

CookieJar creates a cookie jar to store HTTP cookies when they are sent down.

func (*Request) Expect

func (r *Request) Expect(t TestingT) *Expect

Expect creates and returns the request test expectation suite.

func (*Request) File

func (r *Request) File(name string, reader io.Reader) *Request

File serializes and defines the request body as multipart/form-data containing one file field.

func (*Request) Files

func (r *Request) Files(files []multipart.FormFile) *Request

Files serializes and defines the request body as multipart/form-data containing the given file fields.

func (*Request) Form

func (r *Request) Form(data multipart.FormData) *Request

Form serializes and defines the request body as multipart/form-data based on the given form data.

func (*Request) JSON

func (r *Request) JSON(data interface{}) *Request

JSON serializes and defines as request body based on the given input. The proper Content-Type header will be transparently added for you.

func (*Request) Method

func (r *Request) Method(method string) *Request

Method defines the HTTP verb to be used.

func (*Request) Param

func (r *Request) Param(name, value string) *Request

Param replaces a path param based on the given param name and value.

func (*Request) Params

func (r *Request) Params(params map[string]string) *Request

Params replaces path params based on the given params key-value map.

func (*Request) Path

func (r *Request) Path(path string) *Request

Path defines the request URL path to be used in the outgoing request.

func (*Request) Send

func (r *Request) Send() (*gentleman.Response, error)

Send executes the current request and returns the response or error.

func (*Request) SetClient

func (r *Request) SetClient(cli *Client) *Request

SetClient Attach a client to the current Request This is mostly done internally.

func (*Request) SetHeader

func (r *Request) SetHeader(name, value string) *Request

SetHeader sets a new header field by name and value. If another header exists with the same key, it will be overwritten.

func (*Request) SetHeaders

func (r *Request) SetHeaders(fields map[string]string) *Request

SetHeaders adds new header fields based on the given map.

func (*Request) SetQuery

func (r *Request) SetQuery(name, value string) *Request

SetQuery sets a new URL query param field. If another query param exists with the same key, it will be overwritten.

func (*Request) SetQueryParams

func (r *Request) SetQueryParams(params map[string]string) *Request

SetQueryParams sets URL query params based on the given map.

func (*Request) Type

func (r *Request) Type(name string) *Request

Type defines the Content-Type header field based on the given type name alias or value. You can use the following content type aliases: json, xml, form, html, text and urlencoded.

func (*Request) URL

func (r *Request) URL(uri string) *Request

URL parses and defines the URL to be used in the outgoing request.

func (*Request) Use

func (r *Request) Use(p plugin.Plugin) *Request

Use uses a new plugin in the middleware stack.

func (*Request) UseError

func (r *Request) UseError(fn context.HandlerFunc) *Request

UseError uses an error middleware handler.

func (*Request) UseHandler

func (r *Request) UseHandler(phase string, fn context.HandlerFunc) *Request

UseHandler uses an new middleware handler for the given phase.

func (*Request) UseRequest

func (r *Request) UseRequest(fn context.HandlerFunc) *Request

UseRequest uses a request middleware handler.

func (*Request) UseResponse

func (r *Request) UseResponse(fn context.HandlerFunc) *Request

UseResponse uses a response middleware handler.

func (*Request) XML

func (r *Request) XML(data interface{}) *Request

XML serializes and defines the request body based on the given input. The proper Content-Type header will be transparently added for you.

type TestingT

type TestingT interface {
	Error(args ...interface{})
	Fail()
	Logf(format string, args ...interface{})
}

TestingT implements part of the same interface as testing.T

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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