dvr

package module
v0.0.0-...-f6080fe Latest Latest
Warning

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

Go to latest
Published: Aug 2, 2017 License: Apache-2.0 Imports: 21 Imported by: 0

README

Note

This is a copy of ochestrate-io's dvr library repo that is no longer hosted on github.

DVR

DVR is a library for capturing and replaying HTTP calls for golang tests.

Installation

go get github.com/cintosyntax/dvr

Usage

The functionality is primarily documented in the godoc documentation, however a high level is provided here.

This library is intended to allow off line testing of remote API calls. It can be run against the test once in a "record" mode which captures all the queries and stores them in a file. A second test run can then be put into "replay" mode which will match incoming queries against those in the stored file.

The inspiration for this library came from the Python VCR library.. Though the concept is the same several key components have been change to make it more idiomatic golang.

Testing

Continuous Integration Documentation Coverage

Contribution

Pull requests will be reviewed and accepted via github.com, and issues will be worked on as time permits. New feature requests should be filed as an issue against the github repo.

License (Apache 2)

Copyright 2014 Orchestrate, Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Documentation

Overview

Package dvr attempts to make testing far easier by allowing calls to remote HTTP services to be captured and replayed when running the tests a second time.

In recording mode (-dvr.record) each request will be captured and recorded to a file (-dvr.file, which defaults to testdata/archive.dvr). In replay mode each request will be matched against of the requests in the archive. This ensures that a unit test can remove all dependencies on remote services while running, which is ideal for most testing environments.

Note that this library works be replaying net.http's DefaultTransport with one that will intercept queries. If you are using a custom client, or replacing the http.DefaultTransport you may need to sub a RoundTripper from this package in place.

All common error types will be preserved and returned via the archive, however some types can not be restored due to the way that gob works. In these cases an error will be returned that satisfies the error interface but it will be a different type.

When in replay mode requests are matched if all of the following are the same: URL, Body, Headers, Trailers. If all of these elements are the same as a recorded request then the response will be returned to the client. If no request matches then the test will panic since re-requesting may cause all sorts of issues. If this matching strategy is not sufficient then you can make value Match() contain a function that can parse two requests and establish if they are the same.

This library is intended to be user during unit testing so much of its design is wrapped around this, and while it can be used outside of unit tests it is strongly not recommended.

Example (BasicUsage)

For the most basic of use cases you need only ensure that the dvr library is included in your test file. Including it with an underscore, like in this example, is all that is necessary to get it in place.

package main

import (
	"net/http"
	"net/url"
	"testing"

	_ "github.com/lensrentals/dvr"
)

// When running this test you can run it in one of three modes:
//
// Pass through: In this mode nothing is recorded or replayed.
//
//	go test .
//
// Recording: In this mode all HTTP calls are recorded into a file (the default
//
//	         is testdata/archive.dvr, and is control by -dvr.file)
//	go test -dvr.record .
//
// Replay: In this mode all HTTP calls are replayed from the recording file
//
//		      captured in Recording mode above.
//		go test -dvr.replay .
//
//	  - Note that this function needs the leading underscore removed in order
//	    to work in the real world. It exists purely because of the rules around
//	    "playable" document examples.
func _TestCallToApi(t *testing.T) {
	var err error
	req := &http.Request{}
	req.URL, err = url.Parse("http://golang.org")
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		t.Fatalf("Error from net.http: %s", err)
	} else if resp.StatusCode != 200 {
		t.Fatalf("Bad status code: %d", resp.StatusCode)
	}
}

// For the most basic of use cases you need only ensure that the dvr library
// is included in your test file. Including it with an underscore, like in
// this example, is all that is necessary to get it in place.
func main() {
	// Though this library can be used outside of golang's testing library
	// its not recommended. This main() exists only to make the example
	// render in godoc.

}
Output:

Index

Examples

Constants

View Source
const InterceptorToken = "dvr_gzipper_token_a9s87d9aish2"

This token allows us to intercept startup and therefor act as a command line "gzip" process. If os.Argv[1] is this value then we simply take os.Stdin and gzip it into os.Stdout.

This is necessary since Go's test library doesn't have any way of indicating or calling out when all the tests have finished which means that it is impossible to close a gzip file.

Variables

View Source
var (

	// If this is set to true then -dvr.replay becomes default if not
	// other flags are provided. If this is falls then the default will be
	// to pass queries through without recording or replaying them
	DefaultReplay bool
)
View Source
var DefaultRoundTripper http.RoundTripper

This is the round tripper that replaced the default round tripper in the net/http library. Its stored here so it can be retrieved if lost.

View Source
var Matcher func(left, right *RequestResponse) bool

This function is used by the replay component of this library to determine if an incoming request matches a request from the archive. If this function returns true then the requests are deemed to have "matched". Note that mutation of either object (other than the UserData field) will likely result in a panic or crash. The left object will not have Response* fields populated.

The default matcher will match a request if it Request's URL, Body, Headers and Trailers are all the same.

View Source
var Obfuscator func(*RequestResponse)

If this value is anything other than nil it will be called on a copy of the passed in *http.Request and a copy of the returned *http.Response object. Any mutations to these objects will be stored in the archive, but NOT be altered in the recording unit test. The intention of this function is to allow obfuscation of data you do not want recorded.

An example usage of this function is to change the password used to authenticate against a web service in order to allow any user to run the test. See the "RequestObfuscation" example for details.

View Source
var OriginalDefaultTransport http.RoundTripper

This is the round tripper that we overwrote in net/http. It is preserved here in case it needs be recovered.

Functions

func BasicAuthObfuscator

func BasicAuthObfuscator(username, password string) func(*RequestResponse)

This function call will return a function that can act as a Obfuscator which removes any HTTP Basic Auth credential and replaces it with the given arguments. The results of this call can be directly used with the Obfuscator variable.

func IsPassingThrough

func IsPassingThrough() bool

Returns true if the DVR library is in pass through mode.

func IsRecording

func IsRecording() bool

Returns true if the DVR library is in recording mode.

func IsReplay

func IsReplay() bool

Returns true if the DVR library is in replay mode.

func NewRoundTripper

func NewRoundTripper(fallback http.RoundTripper) http.RoundTripper

This creates a new RoundTripper object with the given RoundTripper object as its fall back (for pass through and recording modes).

func RegisterErrorType

func RegisterErrorType(err error)

Adds an error interface object to the list of known types that this library will be able to encode. This is necessary due to the way that gob encodes interface object. The only error types here are those that will be returned from the RoundTripper object. Typical use cases should not need this at all. If you are using this you must do it via your modules init() otherwise results can be unpredictable.

func ReplayTimestamp

func ReplayTimestamp() time.Time

ReplayTimestamp returns the modification time of the recordFile.

Types

type RequestResponse

type RequestResponse struct {
	// This is the Request object that was passed in to the RoundTripper
	// call. This object will have it's Body field set to nil, with the body
	// being represented in the byte array 'RequestBody'. The error (if any)
	// returned when reading from Body is stored in RequestBodyError.
	Request          *http.Request
	RequestBody      []byte
	RequestBodyError error

	// This is the Response object that was returned to the caller. Note that
	// Body in this field is saved in the ResponseBody field, and the error
	// returned from the server is stored in ResponseBodyError.
	Response          *http.Response
	ResponseBody      []byte
	ResponseBodyError error

	// This is the error returned from the RountTrip() call.
	Error error

	// This stores any user data that is necessary for the Matcher() function.
	UserData interface{}
}

This structure stores information about a Request/Response pairing. It is intended to keep the data together for use when matching and such.

Jump to

Keyboard shortcuts

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