testy

package module
v0.14.0 Latest Latest
Warning

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

Go to latest
Published: Nov 8, 2023 License: MIT Imports: 29 Imported by: 13

README

Testy

Testy is a collection of utilities to facilitate unit testing in Go.

This software is released under the MIT license, as outlined in the included LICENSE.md file.

Documentation

Overview

Package testy provides a collection of disparate testing-related functions.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CopyTempDir

func CopyTempDir(t *testing.T, source string, depth int) string

CopyTempDir recursively copies the contents of path to a new temporary dir whose path is returned. The depth argument controls how deeply path is placed into the temp dir. Examples:

copyDir(t, "/foo/bar/baz", 0) // copies /foo/bar/baz/* to /tmp-XXX/*
copyDir(t, "/foo/bar/baz", 1) // copies /foo/bar/baz/* to /tmp-XXX/baz/*
copyDir(t, "/foo/bar/baz", 3) // copies /foo/bar/baz/* to /tmp-XXX/foo/bar/baz/*

func DelayReader

func DelayReader(delay time.Duration) io.ReadCloser

DelayReader returns an io.Reader that never returns any data, but will delay before return io.EOF. It is intended to be used in conjunction with io.MultiReader to construct test scenarios. Each call to Read() will delay, then return (0, io.EOF), so it is safe to re-use the return value. A call to Close() will always return nil.

func Environ

func Environ() map[string]string

Environ returns all current environment variables, parsed into a map.

func Error deprecated

func Error(t *testing.T, expected string, actual error)

Error compares actual.Error() against expected, and triggers an error if they do not match. If actual is non-nil, t.SkipNow() is called as well.

Deprecated: Do not use this function. Consider using ErrorMatches instead.

func ErrorMatches added in v0.4.0

func ErrorMatches(want string, got error) bool

ErrorMatches returns true if want matches got's error text, or if want is empty and got is nil.

func ErrorMatchesRE added in v0.8.0

func ErrorMatchesRE(want string, got error) bool

ErrorMatchesRE returns true if want matches got's error text. As a special case, want=="" matches got==nil

func ErrorRE deprecated

func ErrorRE(t *testing.T, expected string, actual error)

ErrorRE compares actual.Error() against expected, which is treated as a regular expression, and triggers an error if they do not match. If actual is non-nil, t.SkipNow() is called as well.

Deprecated: Do not use this function. Consider ErrorMatchesRE instead.

func ErrorReader

func ErrorReader(s string, err error) io.ReadCloser

ErrorReader returns an io.Reader which behaves the same as strings.NewReader(s), except that err will be returned at the end, rather than io.EOF. A call to Close() will also return err.

func ErrorWriter

func ErrorWriter(count int, err error) io.WriteCloser

ErrorWriter returns a new io.Writer, which will accept count bytes (discarding them), then return err as an error. A call to Close() will also return err.

func ExitStatus

func ExitStatus(err error) int

ExitStatus returns the exit status embedded in the error, or 1 (unknown error) if there is no specific status code.

func ExitStatusError

func ExitStatusError(t *testing.T, expected string, eStatus int, actual error)

ExitStatusError compares actual.Error() and the embedded exit status against expected, and triggers an error if they do not match. If actual is non-nil, t.SkipNow() is called as well.

func ExitStatusErrorRE

func ExitStatusErrorRE(t *testing.T, expected string, eStatus int, actual error)

ExitStatusErrorRE compares actual.Error() and the embedded exit status against expected, and triggers an error if they do not match. If actual is non-nil, t.SkipNow() is called as well.

func FormRequest added in v0.7.2

func FormRequest(method, url string, v url.Values) *http.Request

FormRequest returns an HTTP request with v converted to url-encoded values as the body, and the Content-Type header set to application/x-www-form-urlencoded.

func FullError

func FullError(t *testing.T, expected string, status, eStatus int, actual error)

FullError compares actual.Error() and the embedded HTTP and exit statuses against expected, and triggers an error if they do not match. If actual is non-nil, t.SkipNow() is called as well.

func HTTPClient

func HTTPClient(fn HTTPResponder) *http.Client

HTTPClient returns a customized *http.Client, which passes the request to fn, rather than to the network.

func JSONReader added in v0.7.0

func JSONReader(i interface{}) io.ReadCloser

JSONReader returns an io.ReadCloser that will produce i marshaled as JSON. Any marshaling error will be returned as an error to Read().

func JSONRequest added in v0.7.2

func JSONRequest(method, url string, i interface{}) *http.Request

JSONRequest returns an HTTP request with i converted to JSON as the body, and the Content-Type header set to application/json.

func NeverReader

func NeverReader() io.Reader

NeverReader returns an io.Reader that never returns data, blocking forever when Read() is called.

func QueryReader added in v0.7.0

func QueryReader(v url.Values) io.ReadCloser

QueryReader returns an io.ReadCloser that will produce the encoded value of v.

func ReadHTTPResponseFromFile

func ReadHTTPResponseFromFile(filename string, req *http.Request) (*http.Response, error)

ReadHTTPResponseFromFile reads an http.Response from a file. The req parameter optionally specifies the Request that corresponds to this Response. If nil, a GET request is assumed.

func Recorder added in v0.3.0

func Recorder() io.ReadWriteCloser

Recorder returns an io.ReadWriteCloser, which can be used for testing writes. The Read() method will block until Close() is called the first time, at which point any further Write() calls will fail, and any data previously written will be read back. A second call to Close() clears the buffer and will cause further Read() calls to fail as well.

func RedirIO

func RedirIO(in io.Reader, fn func()) (stdout, stderr io.Reader)

RedirIO runs fn, with stdin redirected from in, and anything sent to stdout or stderr returned.

func RestoreEnv

func RestoreEnv() func()

RestoreEnv returns a function which restores the environment to the original state. It is intended to be used in conjunction with defer, to temporarily modify the environment during tests.

Example:

func TestFoo(t *testing.T) {
    defer RestoreEnv()()
    os.SetEnv( ... ) // Set temporary values
}

func ServeResponse

func ServeResponse(r *http.Response) *httptest.Server

ServeResponse starts a test HTTP server that serves r.

func ServeResponseValidator

func ServeResponseValidator(t *testing.T, r *http.Response, fn RequestValidator) *httptest.Server

ServeResponseValidator wraps a ResponseHandler with ValidateRequest middleware for a complete response-serving, request-validating test server.

func SetEnv

func SetEnv(env map[string]string) error

SetEnv sets the environment variables contained in the map.

func SkipVer added in v0.5.0

func SkipVer(t *testing.T, expr string)

SkipVer skips the test if the current version of Go matches expr. See https://pkg.go.dev/github.com/Masterminds/semver/v3#hdr-Basic_Comparisons for an explanation of the supported format of expr.

To determine the current version of Go, runtime.Version() is called, the 'go' prefix is stripped, and if an rc version, a '-' character is inserted before the 'rc' substring, to make the version conform to semver.

func StatusCode

func StatusCode(err error) int

StatusCode returns the HTTP status code embedded in the error, or 500 if there is no specific status code.

It will unwrap errors, according to pkg/errors and Go 1.13 Unwrap conventions, looking for an error with an embedded status code.

To embed an HTTP status code, implement an error that satisfies one of the following interfaces, which are checked in this order:

 interface {
     HTTPStatus() int
}

 interface {
     StatusCode() int
}

func StatusError deprecated

func StatusError(t *testing.T, expected string, status int, actual error)

StatusError compares actual.Error() and the embedded HTTP status code against expected, and triggers an error if they do not match. If actual is non-nil, t.SkipNow() is called as well.

Deprecated: Do not use this function. Consider ErrorMatches instead.

func StatusErrorRE deprecated

func StatusErrorRE(t *testing.T, expected string, status int, actual error)

StatusErrorRE compares actual.Error() and the embedded HTTP status code against expected, and triggers an error if they do not match. If actual is non-nil, t.SkipNow() is called as well.

Deprecated: Do not use this function. Consider ErrorMatchesRE instead.

func Stub

func Stub(t *testing.T) string

Stub returns t.Name(), with whitespace and slashes converted to underscores.

func Swarn

func Swarn(args ...interface{}) string

Swarn returns a Warn-formatted string.

func Swarnf

func Swarnf(format string, args ...interface{}) string

Swarnf returns a Warn-formatted string.

func Swarnln

func Swarnln(args ...interface{}) string

Swarnln works like Warnln, but returns the string rather than outputting it.

func TempDir

func TempDir(t *testing.T, dirname *string) func()

TempDir creates a temporary directory, assigning the name to dirname, and returning a cleanup function, which will remove the tempdir and all contents. An error during creation will be passed to t.Fatal(). An error during cleanup will be ignored.

It is meant to be run as so:

   t.Run(func(t *testing.T) {
       var tmpdir string
       defer testy.TempDir(t, &tmpdir)()
       /*  here you can use tmpdir  */
   })

Or:

    tests := testy.NewTable()
    tests.Add("foo", func(t *testing.T) interface{} {
        var tmpdir string
        tests.Cleanup(testy.TempDir(t, &tmpdir))
        // ...
     })

func UpdateMode

func UpdateMode() bool

UpdateMode returns true if update mode is enabled, which indicates whether a detected diff should cause a File to be overwritten. To enable UpdateMode, run `go test -tag=update` or `go test -update`.

func ValidateRequest

func ValidateRequest(t *testing.T, fn RequestValidator) func(http.Handler) http.Handler

ValidateRequest returns a middleware that calls fn(), to validate the HTTP request, before continuing. An error returned by fn() will result in the addition of an X-Error header, a 400 status, and the error added to the body of the response.

func Warn

func Warn(args ...interface{})

Warn outputs the arguments to STDERR, prefixed with some useful debugging info. The output prefix is in the following format:

[PID/GID file:lineno]

func Warnf

func Warnf(f io.Writer, format string, args ...interface{}) (int, error)

Warnf warns to the specified io.Writer.

func Warnln

func Warnln(args ...interface{})

Warnln outputs the arguments to STDERR, prefixed with some useful debugging info, and suffixed with a newline.

func ZeroDate added in v0.5.0

func ZeroDate(h http.Header) bool

ZeroDate sets the Date header, if found, to January 1, 1970. It returns false if the Date header was not found.

Types

type Diff

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

Diff is the result of a diff function. It may be nil, if the inputs were considered identical, or accessed via the String() method to return the diff. Any errors are returned as their textual representation via String() as well.

func DiffAsJSON

func DiffAsJSON(expected, actual interface{}, re ...Replacement) *Diff

DiffAsJSON marshals two objects as JSON, then compares the output. If an input object is an io.Reader, it is treated as a JSON stream. If it is a []byte or json.RawMessage, it is treated as raw JSON. Any raw JSON source is unmarshaled then remarshaled with indentation for normalization and comparison.

func DiffHTTPRequest

func DiffHTTPRequest(expected, actual interface{}, re ...Replacement) *Diff

DiffHTTPRequest compares the metadata and bodies of the two HTTP requests, and returns the difference. Inputs must be of the type *http.Request, or of one of the following types, in which case the input is interpreted as a raw HTTP request. - io.Reader - string - []byte

If the actual request does not contain a Content-Length header or Transfer-Encoding: chunked, and it should contain one, then Content-Length is added, so that reading the request will succeed.

func DiffHTTPResponse

func DiffHTTPResponse(expected, actual interface{}, re ...Replacement) *Diff

DiffHTTPResponse compares the metadata and bodies of the two HTTP responses, and returns the difference. Inputs must be of the type *http.Response, or of one of the following types, in which case the input is interpreted as a raw HTTP response. - io.Reader - string - []byte

func DiffInterface

func DiffInterface(expected, actual interface{}, re ...Replacement) *Diff

DiffInterface compares two objects with reflect.DeepEqual, and if they differ, it returns a diff of the spew.Dump() outputs.

If expected is an instance of File, the file's contents is read and compared directly against actual's spew.Dump() output, and the DeepEqual check is skipped.

func DiffJSON

func DiffJSON(expected, actual interface{}, re ...Replacement) *Diff

DiffJSON unmarshals two JSON strings, then calls AsJSON on them. The arguments must be byte slices, strings, or io.Readers. As a special case, an empty input unmarshals to nil.

func DiffText

func DiffText(expected, actual interface{}, re ...Replacement) *Diff

DiffText compares two strings, line-by-line, for differences. expected and actual must be of one of the following types: - string - []byte - io.Reader

func DiffTextSlices

func DiffTextSlices(expected, actual []string) *Diff

DiffTextSlices compares two slices of text, treating each element as a line of text. Newlines are added to each element, if they are found to be missing.

func DiffURLQuery added in v0.6.0

func DiffURLQuery(expected, actual interface{}, re ...Replacement) *Diff

DiffURLQuery unmarshals two url query strings (can also be application/x-www-form-urlencoded bodies), then calls DiffInterface on them.

func (*Diff) String

func (r *Diff) String() string

type File

type File struct {
	Path string
	// contains filtered or unexported fields
}

File converts a file into an io.Reader. When UpdateMode is true, a detected difference will cause File to be overwritten with the actual value, when File is the expected value.

func Snapshot

func Snapshot(t *testing.T, suffix ...string) *File

Snapshot returns a File object suitable for storing test output. It is essentially shorthand for:

&File{Path: "testdata/"+Stub(t)}

but with colons in the stub converted to underscores, for better compatibility certain tools.

The optional suffix argument(s) are appended to the generated name. This is useful when multiple snapshots are used per test.

func (*File) Read

func (f *File) Read(p []byte) (int, error)

type Final added in v0.1.1

type Final interface{}

A Final can be used to do any final checks, clean up after an individual test, or a complete table of tests. It must be a function with one of the following signatures:

  • func()
  • func(*testing.T)
  • func() error

In the latter case, any non-nil error will be passed to t.Fatal().

type HTTPResponder

type HTTPResponder func(*http.Request) (*http.Response, error)

HTTPResponder is a function which intercepts and responds to an HTTP request.

func (HTTPResponder) RoundTrip

func (t HTTPResponder) RoundTrip(r *http.Request) (*http.Response, error)

RoundTrip satisfies the http.RoundTripper interface

type JSONDir

type JSONDir struct {
	// Path is the filesystem path to be serialized.
	Path string
	// NoMD5Sum suppresses the output of the MD5 sum in output.
	NoMD5Sum bool
	// NoSize suppresses the file size output.
	NoSize bool
	// FileContent turns on the inclusion of file contents.
	FileContent bool
	// MaxContentSize sets the limit for included content. Files larger than
	// this will be truncated in their output.
	MaxContentSize int
}

JSONDir implements a json marshaler on the filesystem path specified by the Path field. All other fields are optional, with reasonable defaults for most use cases.

func (JSONDir) MarshalJSON

func (d JSONDir) MarshalJSON() ([]byte, error)

MarshalJSON satisfies the json.Marshaler interface.

type Replacement

type Replacement struct {
	Regexp      *regexp.Regexp
	Replacement string
}

Replacement is a replacement rule to be used on input before diffing.

type RequestValidator

type RequestValidator func(*testing.T, *http.Request)

RequestValidator is a function that takes a *http.Request for validation.

type ResponseHandler

type ResponseHandler struct {
	*http.Response
}

ResponseHandler wraps an existing http.Response, to be served as a standard http.Handler

func (*ResponseHandler) ServeHTTP

func (h *ResponseHandler) ServeHTTP(w http.ResponseWriter, _ *http.Request)

type Table

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

Table is a table of one or more tests to run against a single test function.

func NewTable

func NewTable() *Table

NewTable returns a new Table instance.

func (*Table) Add

func (tb *Table) Add(name string, test interface{}, final ...Final)

Add adds a single named test to the table, and optionally one or more cleanup functions. The cleanup function may also be returned by the test generator, if that is easier for scoping of closures.

test may be of the following types:

  • interface{}
  • func() interface{}
  • func(*testing.T) interface{}
  • func() (interface{}, CleanupFunc)
  • func(*testing.T) (interface{}, CleanupFunc)

If multiple cleanup functions are provided, first the one returned by the generator is executed, then any passed to Add() are executed, in the order provided.

func (*Table) Cleanup

func (tb *Table) Cleanup(fn Final)

Cleanup takes a single function to be called after all Table tests have been executed.

func (*Table) Run

func (tb *Table) Run(t *testing.T, testFn interface{})

Run cycles through the defined tests, passing them one at a time to testFn. testFn must be a function which takes two arguments: *testing.T, and an arbitrary type, which must match the return value of the Generator functions.

Jump to

Keyboard shortcuts

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